Ticket #169: terrain_triangulation_test4.patch

File terrain_triangulation_test4.patch, 12.4 KB (added by Xin, 14 years ago)
  • PatchRData.cpp

     
    8888
    8989struct STmpSplat {
    9090    Handle m_Texture;
    91     u16 m_Indices[4];
     91    u16 m_Indices[6];   //a splat is now composed of two triangles instead of a single quad
    9292};
    9393
     94void CPatchRData::GetTriangulation(const CVector3D& v1, const CVector3D& v2, const CVector3D& v3, const CVector3D& v4, std::vector<CVector3D>& out)
     95{
     96    std::list<unsigned short> triangulation = m_Triangulation[v3];
     97    std::list<unsigned short>::iterator it;
     98    for (it = triangulation.begin(); it != triangulation.end(); it++)
     99    {
     100        if (m_Vertices[*it].m_Position == v1)
     101            out.push_back(v1);
     102        else if (m_Vertices[*it].m_Position == v2)
     103            out.push_back(v2);
     104        else if (m_Vertices[*it].m_Position == v3)
     105            out.push_back(v3);
     106        else
     107            out.push_back(v4);
     108    }
     109}
     110
    94111void CPatchRData::BuildBlends()
    95112{
    96113    m_BlendIndices.clear();
     
    237254                        m_BlendVertices.push_back(dst);
    238255                        m_BlendVertexIndices.push_back(((j+1)*vsize)+i);
    239256
    240                         // build a splat for this quad
     257                        // build a splat for this quad (really two tris)
    241258                        STmpSplat splat;
    242259                        splat.m_Texture=neighbourTextures[k].m_Handle;
    243                         splat.m_Indices[0]=(u16)(vindex);
     260                        /*splat.m_Indices[0]=(u16)(vindex);
    244261                        splat.m_Indices[1]=(u16)(vindex+1);
    245262                        splat.m_Indices[2]=(u16)(vindex+2);
    246263                        splat.m_Indices[3]=(u16)(vindex+3);
     264                        */
     265                       
     266                        //match up the triangulation calculated by BuildIndices() for this blend tile
     267                        std::list<unsigned short> triangulation = m_Triangulation[vtx2.m_Position];
     268                        std::list<unsigned short>::iterator it;
     269                        int splatIndex = 0;
     270                        for (it = triangulation.begin(); it != triangulation.end(); it++)
     271                        {
     272                            CVector3D pos = m_Vertices[*it].m_Position;
     273                            if (m_Vertices[*it].m_Position == vtx0.m_Position)
     274                            {
     275                                splat.m_Indices[splatIndex++]=((u16)(vindex));
     276                            }
     277                            else if (m_Vertices[*it].m_Position == vtx1.m_Position)
     278                            {
     279                                splat.m_Indices[splatIndex++]=((u16)(vindex+1));
     280                            }
     281                            else if (m_Vertices[*it].m_Position == vtx2.m_Position)
     282                            {
     283                                splat.m_Indices[splatIndex++]=((u16)(vindex+2));
     284                            }
     285                            else if (m_Vertices[*it].m_Position == vtx3.m_Position)
     286                            {
     287                                splat.m_Indices[splatIndex++]=((u16)(vindex+3));
     288                            }
     289                            else
     290                            {
     291                                debug_printf(L"WARNING: Triangulation matching failed.");
     292                                debug_break();
     293                            }
     294                        }
    247295                        splats.push_back(splat);
    248296
    249297                        // add this texture to set of unique splat textures
     
    284332                    m_BlendIndices.push_back(splats[k].m_Indices[1]+base);
    285333                    m_BlendIndices.push_back(splats[k].m_Indices[2]+base);
    286334                    m_BlendIndices.push_back(splats[k].m_Indices[3]+base);
    287                     splat.m_IndexCount+=4;
     335                    m_BlendIndices.push_back(splats[k].m_Indices[4]+base);
     336                    m_BlendIndices.push_back(splats[k].m_Indices[5]+base);
     337                    splat.m_IndexCount+=6;
    288338                }
    289339            }
    290340            splatCount++;
     
    302352
    303353    // release existing indices and bins
    304354    m_Indices.clear();
    305     m_ShadowMapIndices.clear();
    306355    m_Splats.clear();
    307356
    308357    // build grid of textures on this patch and boundaries of adjacent patches
     
    332381        for (ssize_t j=0;j<PATCH_SIZE;j++) {
    333382            for (ssize_t i=0;i<PATCH_SIZE;i++) {
    334383                if (texgrid[j][i]==h){
     384
     385                    //save these values for convenience
     386                    u16 index1 = u16(((j+0)*vsize+(i+0))+base);
     387                    u16 index2 = u16(((j+0)*vsize+(i+1))+base);
     388                    u16 index3 = u16(((j+1)*vsize+(i+1))+base);
     389                    u16 index4 = u16(((j+1)*vsize+(i+0))+base);
     390
     391                    //calculate triangulation
     392                    //reminder: incrementing i shifts x coordinates, j shifts z
     393                    //first, get all the positions of the vertices in world space
     394                    CVector3D v1 = m_Vertices[(j+0)*vsize+(i+0)].m_Position;
     395                    CVector3D v2 = m_Vertices[(j+0)*vsize+(i+1)].m_Position;
     396                    CVector3D v3 = m_Vertices[(j+1)*vsize+(i+1)].m_Position;
     397                    CVector3D v4 = m_Vertices[(j+1)*vsize+(i+0)].m_Position;
     398                   
     399                    /*
     400                    debug_printf(L"Vertex 1 is at position: %f, %f, %f\n", v1.X, v1.Y, v1.Z);
     401                    debug_printf(L"Vertex 2 is at position: %f, %f, %f\n", v2.X, v2.Y, v2.Z);
     402                    debug_printf(L"Vertex 3 is at position: %f, %f, %f\n", v3.X, v3.Y, v3.Z);
     403                    debug_printf(L"Vertex 4 is at position: %f, %f, %f\n", v4.X, v4.Y, v4.Z);
     404                    */
     405
     406                   
     407                    //we have two possible triangulations to check: (123, 143) and (234, 214)
     408                    //our goal is to pick the one that minimizes the angle between the planes formed by the triangles
     409                    //the normals are constructed in such a way as to avoid having to normalize the vectors for the dot product
     410                    CVector3D normal1 = (v1-v2).Cross(v3-v2);
     411                    CVector3D normal2 = (v1-v4).Cross(v3-v4);
     412                    CVector3D normal3 = (v4-v3).Cross(v2-v3);
     413                    CVector3D normal4 = (v4-v1).Cross(v2-v1);
     414                    float angle1 = normal1.Dot(normal2);    //since we don't need the exact angle, we can just use the value of the dot product
     415                    float angle2 = normal3.Dot(normal4);
     416
     417                    //cos gets smaller as the angle increases so we take the triangulation with the larger value
     418                    if (angle1 < angle2)
     419                    {
     420                        m_Indices.push_back(index3);
     421                        m_Indices.push_back(index4);
     422                        m_Indices.push_back(index2);
     423                        m_Indices.push_back(index2);
     424                        m_Indices.push_back(index4);
     425                        m_Indices.push_back(index1);
     426
     427                        //now add to the triangulation map
     428                        std::list<unsigned short> triangulation;
     429                        triangulation.push_back(index3-base);
     430                        triangulation.push_back(index4-base);
     431                        triangulation.push_back(index2-base);
     432                        triangulation.push_back(index2-base);
     433                        triangulation.push_back(index4-base);
     434                        triangulation.push_back(index1-base);
     435                        m_Triangulation.insert( std::pair<CVector3D,std::list<unsigned short>>(v3,triangulation) );
     436                        /* Debug code
     437                        std::pair<std::map<CVector3D, std::list<unsigned short>, veccmp>::iterator, bool> ret = m_Triangulation.insert( std::pair<CVector3D,std::list<unsigned short>>(v3,triangulation) );
     438                        if(ret.second == false)
     439                            debug_break();
     440                            */
     441                    }
     442                    else
     443                    {
     444                        m_Indices.push_back(index2);
     445                        m_Indices.push_back(index3);
     446                        m_Indices.push_back(index1);
     447                        m_Indices.push_back(index1);
     448                        m_Indices.push_back(index3);
     449                        m_Indices.push_back(index4);
     450                       
     451                        //now add to the triangulation map
     452                        std::list<unsigned short> triangulation;
     453                        triangulation.push_back(index2-base);
     454                        triangulation.push_back(index3-base);
     455                        triangulation.push_back(index1-base);
     456                        triangulation.push_back(index1-base);
     457                        triangulation.push_back(index3-base);
     458                        triangulation.push_back(index4-base);
     459                        m_Triangulation.insert( std::pair<CVector3D,std::list<unsigned short>>(v3,triangulation) );
     460                        /* Debug code
     461                        std::pair<std::map<CVector3D, std::list<unsigned short>, veccmp>::iterator, bool> ret = m_Triangulation.insert( std::pair<CVector3D,std::list<unsigned short>>(v3,triangulation) );
     462                        if(ret.second == false)
     463                            debug_break();
     464                            */
     465                    }
     466                   
     467                    /*
    335468                    m_Indices.push_back(u16(((j+0)*vsize+(i+0))+base));
    336469                    m_Indices.push_back(u16(((j+0)*vsize+(i+1))+base));
    337470                    m_Indices.push_back(u16(((j+1)*vsize+(i+1))+base));
    338471                    m_Indices.push_back(u16(((j+1)*vsize+(i+0))+base));
     472                    */
     473
    339474                }
    340475            }
    341476        }
    342477        splat.m_IndexCount=m_Indices.size()-splat.m_IndexStart;
    343478    }
    344 
    345     // build indices for the shadow map pass
    346     for (ssize_t j=0;j<PATCH_SIZE;j++) {
    347         for (ssize_t i=0;i<PATCH_SIZE;i++) {
    348             m_ShadowMapIndices.push_back(u16(((j+0)*vsize+(i+0))+base));
    349             m_ShadowMapIndices.push_back(u16(((j+0)*vsize+(i+1))+base));
    350             m_ShadowMapIndices.push_back(u16(((j+1)*vsize+(i+1))+base));
    351             m_ShadowMapIndices.push_back(u16(((j+1)*vsize+(i+0))+base));
    352         }
    353     }
    354479}
    355480
    356481
     
    519644        ogl_tex_bind(splat.m_Texture);
    520645
    521646        if (!g_Renderer.m_SkipSubmit) {
    522             glDrawElements(GL_QUADS, (GLsizei)splat.m_IndexCount,
     647            glDrawElements(GL_TRIANGLES, (GLsizei)splat.m_IndexCount,
    523648                GL_UNSIGNED_SHORT, &m_Indices[splat.m_IndexStart]);
    524649        }
    525 
     650       
    526651        // bump stats
    527652        g_Renderer.m_Stats.m_DrawCalls++;
    528653        g_Renderer.m_Stats.m_TerrainTris+=splat.m_IndexCount/2;
     
    552677
    553678    // render all base splats at once
    554679    if (!g_Renderer.m_SkipSubmit) {
    555         glDrawElements(GL_QUADS,(GLsizei)m_Indices.size(),GL_UNSIGNED_SHORT,&m_Indices[0]);
     680        glDrawElements(GL_TRIANGLES,(GLsizei)m_Indices.size(),GL_UNSIGNED_SHORT,&m_Indices[0]);
    556681    }
    557682
    558683    // bump stats
     
    591716        ogl_tex_bind(splat.m_Texture);
    592717
    593718        if (!g_Renderer.m_SkipSubmit) {
    594             glDrawElements(GL_QUADS, (GLsizei)splat.m_IndexCount,
     719            glDrawElements(GL_TRIANGLES, (GLsizei)splat.m_IndexCount,
    595720                GL_UNSIGNED_SHORT, &m_BlendIndices[splat.m_IndexStart]);
    596721        }
    597722
  • PatchRData.h

     
    4040    void RenderBlends();
    4141    void RenderOutline();
    4242    void RenderStreams(int streamflags, bool losColor);
     43    void GetTriangulation(const CVector3D& v1, const CVector3D& v2, const CVector3D& v3, const CVector3D& v4, std::vector<CVector3D>& out);
    4344
    4445private:
    4546    struct SSplat {
     
    8283        int m_Priority;
    8384    };
    8485
     86    struct veccmp
     87    {
     88        //comparison function for use by the triangulation map
     89        bool operator() (const CVector3D& lhs, const CVector3D& rhs) const
     90        {
     91            if (lhs.Y < rhs.Y)
     92                return true;
     93            else if (lhs.Y == rhs.Y)
     94            {
     95                if (lhs.Z < rhs.Z)
     96                    return true;
     97                else if (lhs.Z == rhs.Z)
     98                {
     99                    if (lhs.X < rhs.X)
     100                        return true;
     101                    else
     102                        return false;
     103                }
     104                else
     105                    return false;
     106            }
     107            else
     108                return false;
     109        }
     110    };
     111
    85112    // build this renderdata object
    86113    void Build();
    87114
     
    104131    // indices into base vertices for the base splats
    105132    std::vector<unsigned short> m_Indices;
    106133
    107     // indices into base vertices for the shadow map pass
    108     std::vector<unsigned short> m_ShadowMapIndices;
    109 
    110134    // list of base splats to apply to this patch
    111135    std::vector<SSplat> m_Splats;
    112136
     
    122146
    123147    // splats used in blend pass
    124148    std::vector<SSplat> m_BlendSplats;
     149
     150    // stores the triangulation used for individual tiles to improve triangulation matching performance
     151    // it is keyed on the third vertex of a tile (the i+1, j+1 one)
     152    std::map<CVector3D, std::list<unsigned short>, veccmp> m_Triangulation;
    125153};
    126154
    127155
  • TerrainOverlay.cpp

     
    2323#include "ps/Game.h"
    2424#include "ps/World.h"
    2525#include "graphics/Terrain.h"
     26#include "graphics/Patch.h"
     27#include "renderer/PatchRData.h"
    2628#include "maths/MathUtil.h"
    2729#include "lib/ogl.h"
    2830
     
    182184   
    183185    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    184186
     187    /*
    185188    CVector3D pos;
    186189    glBegin(GL_QUADS);
    187190        glColor4fv(colour.FloatArray());
     
    190193        m_Terrain->CalcPosition(i+1, j+1, pos); glVertex3fv(pos.GetFloatArray());
    191194        m_Terrain->CalcPosition(i,   j+1, pos); glVertex3fv(pos.GetFloatArray());
    192195    glEnd();
     196    */
     197
     198    //because the terrain now renders as triangles instead of quads, trying to draw a quad on top of the terrain results in nasty z-fighting so
     199    //we draw triangles and match it up to the triangulation of the underlying patch
     200    CPatch* patch = m_Terrain->GetPatch(i/PATCH_SIZE,j/PATCH_SIZE);
     201    if (patch != NULL)
     202    {
     203        if (patch->GetRenderData() != NULL)
     204        {
     205            CPatchRData* renderPatch = (CPatchRData*)patch->GetRenderData();
     206            CVector3D v1; m_Terrain->CalcPosition(i,   j,   v1);
     207            CVector3D v2; m_Terrain->CalcPosition(i+1, j,   v2);
     208            CVector3D v3; m_Terrain->CalcPosition(i+1, j+1, v3);
     209            CVector3D v4; m_Terrain->CalcPosition(i,   j+1, v4);
     210
     211            std::vector<CVector3D> vertices(6);
     212            renderPatch->GetTriangulation(v1,v2,v3,v4, vertices);
     213
     214            /* I clearly have no idea what I'm doing here...
     215            unsigned short indices[] = {0,1,2,3,4,5,6};
     216            glVertexPointer (3, GL_FLOAT, (GLsizei)sizeof(CVector3D), &vertices);
     217            glColorPointer(4,GL_FLOAT,(GLsizei)sizeof(colour.FloatArray()),colour.FloatArray());
     218            glDrawElements(GL_TRIANGLES, (GLsizei)vertices.size(),GL_UNSIGNED_SHORT, indices);
     219            */
     220
     221            glBegin(GL_TRIANGLES);
     222                glColor4fv(colour.FloatArray());
     223                for (size_t k = 0; k < vertices.size(); k++)
     224                    glVertex3fv(vertices[k].GetFloatArray());
     225            glEnd();
     226        }
     227    }
    193228}
    194229
    195230void TerrainOverlay::RenderTileOutline(const CColor& colour, int line_width, bool draw_hidden)