Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Мультимедия, OpenGL/DirectX > Катра высот


Автор: Vetos 17.4.2011, 01:45
Здравствуйте!
Второй день бьюсь над картой высот.
Вот что у меня получается, это чтото очень далеко напоминает сглажженую карту высот.

Автор: Vetos 17.4.2011, 01:51
А вот это я делал еще на старом OpenGL, и там у меня все получилось отлично, жаль только исходников неосталось.
Может ктонибудь на глаз определит в чем проблема.
Нашел на форуме подобную проблему, человек нашел ошибку в хранении данных, но я не совсем уверен что это тоже самое, и найти эту ошибку я не смогу, т.к. фактически все работает, но плохо :(

Автор: BorisVorontsov 17.4.2011, 22:46
Очень похоже на округление. Нет ли у тебя там где-нибудь конвертации через int?

Автор: Vetos 18.4.2011, 19:16
Не вроде нету, я использую 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;
};



Незнаю може где чо натупил но вроде все правильно, а вот идея про округление мне нравится, но только гдеж собака зарыта))

Автор: Vetos 19.4.2011, 02:19
Ура, закончились мучения и я обрел покой. после того как я попробовал загрузить вертексы с карты через один, результат немного приоткрыл глаза, И я просто стал просчитывать нормали не от соседних точек а через 2,3,5,10 и на десятке картинка радует глаз

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)