Не вроде нету, я использую glm( gl mathematics), нашел ее на Khonors.org, в ней используются типы и функции как в glsl. Вот как строится фасетная нормаль:
Код | vec3 CreateNormal(GLfloat * A, GLfloat * B, GLfloat * C ) { vec3 BA = vec3( A[0],A[1],A[2] ) - vec3( B[0],B[1],B[2] ); vec3 CB = vec3( B[0],B[1],B[2] ) - vec3( C[0],C[1],C[2] ); return cross(CB,BA); }
|
а б ц это массивы с координатами вершины. Все эти координаты хнранятся в массиве структур: struct GLVertex
Код | { GLfloat Position[3]; GLfloat TexCoord[2]; GLfloat Normal[3]; };
|
Вначале строил вершинные нормали от всех граней которые содержат вершину, находил их сумму и нормализовал. теперь строю просто от 8ми соседних точек, ну тоесть нахожу вначале фасетную нормаль треугольничков окружающих вершину, складываю их и нормализую но эффект тотже самый.
Код | void CreateHMNormal( GLVertex * Vert1, GLVertex Vert2, GLVertex Vert3, GLVertex Vert4, GLVertex Vert5, GLVertex Vert6, GLVertex Vert7, GLVertex Vert8, GLVertex Vert9 ) { vec3 normal = CreateNormal( Vert1->Position, Vert2.Position, Vert3.Position ) + CreateNormal( Vert1->Position, Vert3.Position, Vert4.Position ) + CreateNormal( Vert1->Position, Vert4.Position, Vert5.Position ) + CreateNormal( Vert1->Position, Vert5.Position, Vert6.Position ) + CreateNormal( Vert1->Position, Vert6.Position, Vert7.Position ) + CreateNormal( Vert1->Position, Vert7.Position, Vert8.Position ) + CreateNormal( Vert1->Position, Vert8.Position, Vert9.Position ) + CreateNormal( Vert1->Position, Vert9.Position, Vert2.Position ); normal = normalize( normal ); Vert1->Normal[0] = normal.x; Vert1->Normal[1] = normal.y; Vert1->Normal[2] = normal.z; };
|
Т.е. просто в цикле передаю вершину и восемь вокруг нее. Может глюк в использовании типов и функций glm, но врятле бы Khonors.org рекомедовал бы ее. кстати функция cross с этойже библиотеки. Ну на последок цикл, не даже всю функцию создания Карты высот:
Код | bool GLTerrain::CreateFromRGBA(char * fileName, GLfloat stepX, GLfloat stepY, GLfloat stepZ) { GLuint sizeX, sizeZ; GLubyte * HeightMap;
if( TextureExtractAlpfha( fileName, &HeightMap, &sizeX, &sizeZ ) ) тут просто извлекается альфа канал, по видимому нормально { Materials = new GLMaterial[1]; Materials[0].ambient = vec4(0.3f,0.3f,0.3f,1.0f); Materials[0].diffuse = vec4(0.8f,0.8f,0.8f,1.0f); Materials[0].specular = vec4(0.5f,0.5f,0.5f,1.0f); Materials[0].shininess = 20.0f; Materials[0].texture = TextureCreateFromTGA( fileName );
Meshes = new GLMesh[1]; Meshes[0].Material = 0; numMeshes = 2; numMaterials = 1;
SizeX = sizeX; SizeZ = sizeZ; GLVertex * Vertices = new GLVertex[sizeX*sizeZ];
GLuint VertexCount = 0; GLfloat ox = -(sizeX*stepX)/2; GLfloat oy = -(128*stepY); GLfloat oz = -(sizeZ*stepZ)/2; for( int i = 0; i < sizeX; i++ ) for( int j = 0; j < sizeZ; j++ ) тут заполняются координаты, ну и нормаль по дефолту { Vertices[VertexCount].Position[0] = ox + stepX*i; Vertices[VertexCount].Position[1] = oy + stepY*HeightMap[(sizeX-i) + (sizeZ*j)]; Vertices[VertexCount].Position[2] = oz + stepZ*j; Vertices[VertexCount].TexCoord[0] = (1.0f/sizeX)*(sizeX-i); Vertices[VertexCount].TexCoord[1] = (1.0f/sizeZ)*j; Vertices[VertexCount].Normal[0] = 0.0f; Vertices[VertexCount].Normal[1] = 1.0f; Vertices[VertexCount].Normal[2] = 0.0f; VertexCount++; }; if( VertexCount != sizeX*sizeZ ) return 0; проверка что все совпало Meshes[0].numIndices = (sizeX-1)*(sizeZ-1)*6;
GLuint * Indices = new GLuint[Meshes[0].numIndices]; GLuint IndexCount = 0;
for( int i = 0; i < sizeX-1; i++ ) for( int j = 0; j < sizeZ-1; j++ ) { Indices[IndexCount] = i*sizeX+j; Indices[IndexCount+1] = (i+1)*sizeX+j; Indices[IndexCount+2] = (i+1)*sizeX+(j+1); IndexCount += 3; Indices[IndexCount] = i*sizeX+j; Indices[IndexCount+1] = (i+1)*sizeX+(j+1); Indices[IndexCount+2] = i*sizeX+(j+1); IndexCount += 3; };
for (int i=1; i<(sizeX-1); i++) for(int j=1; j<(sizeZ-1); j++) тут вот и создаю нормали, индексы должны быть правильными. { CreateHMNormal( &Vertices[i*sizeX+j], Vertices[i*sizeX+(j-1)], Vertices[(i+1)*sizeX+(j-1)], Vertices[(i+1)*sizeX+j], Vertices[(i+1)*sizeX+(j+1)],Vertices[i*sizeX+(j+1)], Vertices[(i-1)*sizeX+(j+1)], Vertices[(i-1)*sizeX+j], Vertices[(i-1)*sizeX+(j-1)]); };
Ну а тут уже данные передаются в буферы.
glGenVertexArrays( 1, &Meshes[0].VAO ); glBindVertexArray( Meshes[0].VAO ); glGenBuffers( 2, Meshes[0].VBO ); glBindBuffer(GL_ARRAY_BUFFER, Meshes[0].VBO[0] ); glBufferData(GL_ARRAY_BUFFER, VertexCount * sizeof(GLVertex), Vertices, GL_STATIC_DRAW); // Set the size and data of our VBO and set it to STATIC_DRAW glVertexAttribPointer(VERT_POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(GLVertex), 0); // Set up our vertex attributes pointer glEnableVertexAttribArray(VERT_POSITION); glVertexAttribPointer(VERT_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex),(const GLvoid*)(3*sizeof(float))); glEnableVertexAttribArray(VERT_TEXCOORD); glVertexAttribPointer(VERT_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(GLVertex),(const GLvoid*)(3*sizeof(float)+2*sizeof(float))); glEnableVertexAttribArray(VERT_NORMAL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Meshes[0].VBO[1]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, IndexCount * sizeof(unsigned int), Indices, GL_STATIC_DRAW); glBindVertexArray(0); // Disable our Vertex Buffer Object Loaded = true; return 1; }; return 0; };
|
Незнаю може где чо натупил но вроде все правильно, а вот идея про округление мне нравится, но только гдеж собака зарыта))
|