Jeff Molofee - NeHe's OpenGL Tutorials
Здесь есть возможность читать онлайн «Jeff Molofee - NeHe's OpenGL Tutorials» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.
- Название:NeHe's OpenGL Tutorials
- Автор:
- Жанр:
- Год:неизвестен
- ISBN:нет данных
- Рейтинг книги:3 / 5. Голосов: 1
-
Избранное:Добавить в избранное
- Отзывы:
-
Ваша оценка:
- 60
- 1
- 2
- 3
- 4
- 5
NeHe's OpenGL Tutorials: краткое содержание, описание и аннотация
Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «NeHe's OpenGL Tutorials»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.
NeHe's OpenGL Tutorials — читать онлайн бесплатно полную книгу (весь текст) целиком
Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «NeHe's OpenGL Tutorials», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.
Интервал:
Закладка:
First we have the definition of INFINITY, which represents how far to extend the shadow volume polygons (this will be explained more later on). If you are using a larger or smaller coordinate system, adjust this value accordingly.
// Definition Of "INFINITY" For Calculating The Extension Vector For The Shadow Volume
#define INFINITY 100
Next is the definition of the object structures.
The Point3f structure holds a coordinate in 3D space. This can be used for vertices or vectors.
// Structure Describing A Vertex In An Object
struct Point3f {
GLfloat x, y, z;
};
The Plane structure holds the 4 values that form the equation of a plane. These planes will represent the faces of the object.
// Structure Describing A Plane, In The Format: ax + by + cz + d = 0
struct Plane {
GLfloat a, b, c, d;
};
The Face structure contains all the information necessary about a triangle to cast a shadow.
• The indices specified are from the object's array of vertices.
• The vertex normals are used to calculate the orientation of the face in 3D space, so you can determine which are facing the light source when casting the shadows.
• The plane equation describes the plane that this triangle lies in, in 3D space.
• The neighbour indices are indices into the array of faces in the object. This allows you to specify which face joins this face at each edge of the triangle.
• The visible parameter is used to specify whether the face is "visible" to the light source which is casting the shadows.
// Structure Describing An Object's Face
struct Face {
int vertexIndices[3]; // Index Of Each Vertex Within An Object That Makes Up The Triangle Of This Face
Point3f normals[3]; // Normals To Each Vertex
Plane planeEquation; // Equation Of A Plane That Contains This Triangle
int neighbourIndices[3]; // Index Of Each Face That Neighbours This One Within The Object
bool visible; // Is The Face Visible By The Light?
};
Finally, the ShadowedObject structure contains all the vertices and faces in the object. The memory for each of the arrays is dynamically created when it is loaded.
struct ShadowedObject {
int nVertices;
Point3f *pVertices; // Will Be Dynamically Allocated
int nFaces;
Face *pFaces; // Will Be Dynamically Allocated
};
The readObject function is fairly self explanatory. It will fill in the given object structure with the values read from the file, allocating memory for the vertices and faces. It also initializes the neighbours to –1, which means there isn't one (yet). They will be calculated later.
bool readObject(const char *filename, ShadowedObject& object) {
FILE *pInputFile;
int i;
pInputFile = fopen(filename, "r");
if (pInputFile == NULL) {
cerr << "Unable to open the object file: " << filename << endl;
return false;
}
// Read Vertices
fscanf( pInputFile, "%d", &object.nVertices );
object.pVertices = new Point3f[object.nVertices];
for ( i = 0; i < object.nVertices; i++ ) {
fscanf( pInputFile, "%f", &object.pVertices[i].x );
fscanf( pInputFile, "%f", &object.pVertices[i].y );
fscanf( pInputFile, "%f", &object.pVertices[i].z );
}
// Read Faces
fscanf( pInputFile, "%d", &object.nFaces );
object.pFaces = new Face[object.nFaces];
for ( i = 0; i < object.nFaces; i++ ) {
int j;
Face *pFace = &object.pFaces[i];
for ( j = 0; j < 3; j++ ) pFace->neighbourIndices[j] = –1; // No Neigbours Set Up Yet
for ( j = 0; j < 3; j++ ) {
fscanf( pInputFile, "%d", &pFace->vertexIndices[j] );
pFace->vertexIndices[j]-; // Files Specify Them With A 1 Array Base, But We Use A 0 Array Base
}
for ( j = 0; j < 3; j++ ) {
fscanf( pInputFile, "%f", &pFace->normals[j].x );
fscanf( pInputFile, "%f", &pFace->normals[j].y );
fscanf( pInputFile, "%f", &pFace->normals[j].z );
}
}
return true;
}
Likewise, killObject is self-explanatory — just delete all those dynamically allocated arrays inside the object when you are done with them. Note that a line was added to KillGLWindow to call this function for the object in question.
void killObject( ShadowedObject& object ) {
delete[] object.pFaces;
object.pFaces = NULL;
object.nFaces = 0;
delete[] object.pVertices;
object.pVertices = NULL;
object.nVertices = 0;
}
Now, with setConnectivity it starts to get interesting. This function is used to find out what neighbours there are to each face of the object given. Here's some pseudo code:
for each face (A) in the object
for each edge in A
if we don't know this edges neighbour yet
for each face (B) in the object (except A)
for each edge in B
if A's edge is the same as B's edge, then they are neighbouring each other on that edge
set the neighbour property for each face A and B, then move onto next edge in A
The last two lines are accomplished with the following code. By finding the two vertices that mark the ends of an edge and comparing them, you can discover if it is the same edge. The part (edgeA+1)%3 gets a vertex next to the one you are considering. Then you check if the vertices match (the order may be different, hence the second case of the if statement).
int vertA1 = pFaceA->vertexIndices[edgeA];
int vertA2 = pFaceA->vertexIndices[( edgeA+1 )%3];
int vertB1 = pFaceB->vertexIndices[edgeB];
int vertB2 = pFaceB->vertexIndices[( edgeB+1 )%3];
// Check If They Are Neighbours – IE, The Edges Are The Same
if (( vertA1 == vertB1 && vertA2 == vertB2 ) || ( vertA1 == vertB2 && vertA2 == vertB1 )) {
pFaceA->neighbourIndices[edgeA] = faceB;
pFaceB->neighbourIndices[edgeB] = faceA;
edgeFound = true;
break;
}
Luckily, another easy function while you take a breath. drawObject renders each face one by one.
// Draw An Object – Simply Draw Each Triangular Face.
void drawObject( const ShadowedObject& object ) {
glBegin( GL_TRIANGLES );
for ( int i = 0; i < object.nFaces; i++ ) {
const Face& face = object.pFaces[i];
for ( int j = 0; j < 3; j++ ) {
const Point3f& vertex = object.pVertices[face.vertexIndices[j]];
glNormal3f( face.normals[j].x, face.normals[j].y, face.normals[j].z );
glVertex3f( vertex.x, vertex.y, vertex.z );
}
}
glEnd();
}
Интервал:
Закладка:
Похожие книги на «NeHe's OpenGL Tutorials»
Представляем Вашему вниманию похожие книги на «NeHe's OpenGL Tutorials» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.
Обсуждение, отзывы о книге «NeHe's OpenGL Tutorials» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.