Horde3D

Next-Generation Graphics Engine
It is currently 13.05.2024, 21:37

All times are UTC + 1 hour




Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: 04.08.2011, 17:35 
Offline

Joined: 09.09.2009, 18:58
Posts: 107
Hey all, for a while I have been using code copied from the Bullet physics extension as part of my engine, and as the engine has progressed, I have noticed that the code does not hold up well. Here is the code I am currently using. I would like to note that I am not using the physics extension itself, just the code from it.

Code:
struct MeshData
{
    unsigned int GeoResource;
    unsigned int VertexOffset, IndexOffset;
    unsigned int NumVertices,  NumTriangleIndices, VertRStart;
 
    float* VertexBase;
 
    unsigned int* TriangleBase32;
    unsigned short* TriangleBase16;
 
    unsigned int TriangleMode;

    MeshData()
        : VertexOffset(0),
          IndexOffset(0),
          NumVertices(0),
          NumTriangleIndices(0),
          VertRStart(0),
          GeoResource(0)
    {
    }
};

void COLSHAPE_GetMeshData(int node,MeshData* data)
{
    switch(h3dGetNodeType(node))
    {
    case H3DNodeTypes::Mesh:
        data->GeoResource = h3dGetNodeParamI(h3dGetNodeParent(node), H3DModel::GeoResI);
        data->NumVertices = h3dGetNodeParamI(node, H3DMesh::VertREndI) - h3dGetNodeParamI(node, H3DMesh::VertRStartI) + 1;
        data->NumTriangleIndices = h3dGetNodeParamI(node, H3DMesh::BatchCountI);       
        data->VertRStart = h3dGetNodeParamI(node, H3DMesh::VertRStartI);
        data->VertexOffset = h3dGetNodeParamI(node, H3DMesh::VertRStartI) * 3;
        data->IndexOffset = h3dGetNodeParamI(node, H3DMesh::BatchStartI);
        break;
    case H3DNodeTypes::Model:
        data->GeoResource = h3dGetNodeParamI(node, H3DModel::GeoResI);
        data->NumVertices = h3dGetResParamI(data->GeoResource, H3DGeoRes::GeometryElem, 0, H3DGeoRes::GeoVertexCountI);
        data->NumTriangleIndices = h3dGetResParamI(data->GeoResource, H3DGeoRes::GeometryElem, 0, H3DGeoRes::GeoIndexCountI);     
        break;
    /*case H3DEXT_NodeType_Terrain:
        unloadTerrainGeoRes();
        geoResource = h3dextCreateTerrainGeoRes(
            node,
            h3dGetNodeParamStr( node, H3DNodeParams::NameStr ),
            h3dGetNodeParamF( node, H3DEXTTerrain::MeshQualityF, 0) );     
        data->NumVertices = h3dGetResParamI(geoResource, H3DGeoRes::GeometryElem, 0, H3DGeoRes::GeoVertexCountI);
        data->NumTriangleIndices = h3dGetResParamI(geoResource, H3DGeoRes::GeometryElem, 0, H3DGeoRes::GeoIndexCountI);     
        m_terrainGeoRes = geoResource;
        break;*/
    }
    float* vb = (float*)h3dMapResStream(data->GeoResource, H3DGeoRes::GeometryElem, 0, H3DGeoRes::GeoVertPosStream, true, false);
    data->VertexBase = new float[(data->NumVertices*3)];
    memcpy(data->VertexBase, vb+data->VertexOffset, sizeof(float)*data->NumVertices*3);
    h3dUnmapResStream(data->GeoResource);
 
    //Triangle indices, must cope with 16 bit and 32 bit
    if (h3dGetResParamI(data->GeoResource, H3DGeoRes::GeometryElem, 0, H3DGeoRes::GeoIndices16I)) {
        unsigned short* tb = (unsigned short*)h3dMapResStream(data->GeoResource, H3DGeoRes::GeometryElem, 0, H3DGeoRes::GeoIndexStream, true, false);
        data->TriangleBase16 = new unsigned short[data->NumTriangleIndices];
        memcpy(data->TriangleBase16, tb+data->IndexOffset, sizeof(unsigned short)*data->NumTriangleIndices);
        h3dUnmapResStream(data->GeoResource);
    } else {
        unsigned int* tb = (unsigned int*)h3dMapResStream(data->GeoResource, H3DGeoRes::GeometryElem, 0, H3DGeoRes::GeoIndexStream, true, false);
        data->TriangleBase32 = new unsigned int[data->NumTriangleIndices];
        memcpy(data->TriangleBase32, tb+data->IndexOffset, sizeof(unsigned int)*data->NumTriangleIndices);
        h3dUnmapResStream(data->GeoResource);
    }

}
void CollisionShape::SetAsStaticMesh(int node)
{
    string out = "Beginning generation of static mesh... ";

    MeshData mesh_data;

    COLSHAPE_GetMeshData(node,&mesh_data);

    if(   mesh_data.VertexBase && (mesh_data.TriangleBase32 || mesh_data.TriangleBase16))
    {
        m_smile->triangle_mesh = new btTriangleMesh();
        int offset = 3;

        // copy mesh from graphics to physics
        bool index16 = false;
        if (mesh_data.TriangleBase16)
            index16 = true;

        for (unsigned int i = 0; i < mesh_data.NumTriangleIndices - 2; i+=offset)
        {
            unsigned int index1 = index16 ?
                (mesh_data.TriangleBase16[i]-mesh_data.VertRStart)*3 :
                (mesh_data.TriangleBase32[i]-mesh_data.VertRStart)*3;

            unsigned int index2 = index16 ?
                (mesh_data.TriangleBase16[i+1]-mesh_data.VertRStart)*3 :
                (mesh_data.TriangleBase32[i+1]-mesh_data.VertRStart)*3;

            unsigned int index3 = index16 ?
                (mesh_data.TriangleBase16[i+2]-mesh_data.VertRStart)*3 :
                (mesh_data.TriangleBase32[i+2]-mesh_data.VertRStart)*3;

            m_smile->triangle_mesh->addTriangle(
                btVector3( mesh_data.VertexBase[index1], mesh_data.VertexBase[index1+1], mesh_data.VertexBase[index1+2] ),
                btVector3( mesh_data.VertexBase[index2], mesh_data.VertexBase[index2+1], mesh_data.VertexBase[index2+2] ),
                btVector3( mesh_data.VertexBase[index3], mesh_data.VertexBase[index3+1], mesh_data.VertexBase[index3+2] )
            );
        }                                          

        bool useQuantizedAabbCompression = true;                                          
        m_CollisionShape = new btBvhTriangleMeshShape(
           m_smile->triangle_mesh,useQuantizedAabbCompression
        );
        m_smile->is_set = true;
    }

   float scal_x, scal_y, scal_z;
   int child_mesh = 0;

    out += "DING!!! Done!";
    Log::Info(out);
}

void CollisionShape::SetAsDynamicMesh(int node)
{
    string out = "Beginning generation of dynamic mesh... ";

    // Since the node that is passed can be almost any node at all, we need
    // to walk the scenegraph to find a model node.

    MeshData mesh_data;

    COLSHAPE_GetMeshData(node,&mesh_data);
   
    if(mesh_data.VertexBase && (mesh_data.TriangleBase32 || mesh_data.TriangleBase16))
    {
        // Create new mesh in physics engine
        m_smile->triangle_mesh = new btTriangleMesh();
        int offset = 3;
        //if (triangleMode == 5) // Triangle Strip
        //   offset = 1;

        // copy mesh from graphics to physics
        bool index16 = false;
        if(mesh_data.TriangleBase16)
            index16 = true;

        for(unsigned int i = 0; i < mesh_data.NumTriangleIndices - 2; i+=offset)
        {
            unsigned int index1 = index16 ?
                (mesh_data.TriangleBase16[i]-mesh_data.VertRStart)*3 :
                (mesh_data.TriangleBase32[i]-mesh_data.VertRStart)*3;
            unsigned int index2 = index16 ?
                (mesh_data.TriangleBase16[i+1]-mesh_data.VertRStart)*3 :
                (mesh_data.TriangleBase32[i+1]-mesh_data.VertRStart)*3;
            unsigned int index3 = index16 ?
                (mesh_data.TriangleBase16[i+2]-mesh_data.VertRStart)*3 :
                (mesh_data.TriangleBase32[i+2]-mesh_data.VertRStart)*3;

            m_smile->triangle_mesh->addTriangle(
                btVector3(
                    mesh_data.VertexBase[index1], mesh_data.VertexBase[index1+1], mesh_data.VertexBase[index1+2]
                ),
                btVector3(
                    mesh_data.VertexBase[index2], mesh_data.VertexBase[index2+1], mesh_data.VertexBase[index2+2]
                ),
                btVector3(
                    mesh_data.VertexBase[index3], mesh_data.VertexBase[index3+1], mesh_data.VertexBase[index3+2]
                )
            );
        }                                    

        // You can use GImpact or convex
        // decomposition of bullet to handle more complex meshes
        m_CollisionShape = new btConvexTriangleMeshShape(m_smile->triangle_mesh);
        //m_CollisionShape = new btGImpactConvexDecompositionShape(m_smile->triangle_mesh,btVector3(1,1,1),btScalar(0.1f),true);
        //m_CollisionShape->updateBound();

        m_smile->is_set = true;
    }

   float scal_x, scal_y, scal_z;
   int child_mesh = 0;

    out += "DING!!! Done!";
    Log::Info(out);

}


m_smile is a pointer to a struct that implements the 'pimpl' idiom. Private Implementation. Basically holds all of the member variables in the implementation as opposed to the declaration. Complete separation of the interface from the implementation is a godsend. That aside, are there new things about the resource mapping that should be taken into account with Beta 5?

My next problem is with the Bullet debug drawing. I am using their debug drawer, and no combination of state saves/changes/beatingswithahammer are allowing the debug geometry to work.

I do not believe there is anything wrong with the rendering class itself, but I'll post it anyway along with the actual invocation of the debug rendering.

Code:
// Rendering routine.
void Renderer::Render()
{
    DumpHorde3DLog();

   boost::mutex::scoped_lock sl(GetRenderMutex());

    int r;
    Window* w = Engine::I()->GetWindow();
    Stage* s = Engine::I()->GetStage();

    int win_w = w->GetWidth();
    int win_h = w->GetHeight();

   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glViewport(0,0,win_w,win_h);

   int stage_camera = Engine::I()->GetStage()->GetActiveCamera();

   Matrix4f camera_world_transform;
    Matrix4f camera_projection_matrix;
    glPushAttrib(GL_ALL_ATTRIB_BITS);

    if(stage_camera)
    {

        h3dRender(stage_camera);

        h3dGetCameraProjMat(stage_camera,camera_projection_matrix.x);
        h3dGetNodeTransMats(stage_camera,NULL,(const float**)&camera_world_transform.x);

    }

    h3dFinalizeFrame();

    glPopAttrib();

   glActiveTexture(0);
   glBindBuffer(GL_ARRAY_BUFFER,0);
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
   glBindBuffer(GL_PIXEL_PACK_BUFFER,0);
   glBindBuffer(GL_PIXEL_UNPACK_BUFFER,0);
   glUseProgram(0);
   // */
   
    /*glMatrixMode(GL_PROJECTION);
    glLoadMatrixf(camera_projection_matrix.x);

    glMatrixMode(GL_MODELVIEW);
    glLoadMatrixf(camera_world_transform.inverted().x);

    s->GetWorld()->DebugDraw();
    // */

    s->GetCanvas()->Activate();
   s->PropagatePostRender();
   s->GetCanvas()->Deactivate();

    glPopAttrib();
}


Debug drawing class implementation.
Code:
void   GLDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& fromColor, const btVector3& toColor)
{
   btVector3 f(from); btVector3 t(to);
   f.setX(from.x() / Irre::Physics_Scale_Factor);
   f.setY(from.y() / Irre::Physics_Scale_Factor);
   f.setZ(from.z() / Irre::Physics_Scale_Factor);
   t.setX(to.x() / Irre::Physics_Scale_Factor);
   t.setY(to.y() / Irre::Physics_Scale_Factor);
   t.setZ(to.z() / Irre::Physics_Scale_Factor);

    //glLineWidth(2.f);
   glBegin(GL_LINES);
      glColor3f(fromColor.getX(), fromColor.getY(), fromColor.getZ());
      glVertex3d(f.getX(), f.getY(), f.getZ());
      glColor3f(toColor.getX(), toColor.getY(), toColor.getZ());
      glVertex3d(t.getX(), t.getY(), t.getZ());
   glEnd();
}

void   GLDebugDrawer::drawLine(const btVector3& from,const btVector3& to,const btVector3& color)
{
   btVector3 f(from); btVector3 t(to);
   f.setX(from.x() / Irre::Physics_Scale_Factor);
   f.setY(from.y() / Irre::Physics_Scale_Factor);
   f.setZ(from.z() / Irre::Physics_Scale_Factor);
   t.setX(to.x() / Irre::Physics_Scale_Factor);
   t.setY(to.y() / Irre::Physics_Scale_Factor);
   t.setZ(to.z() / Irre::Physics_Scale_Factor);


    //glLineWidth(2.f);
    glBegin(GL_LINES);
      glColor3f(color.getX(), color.getY(), color.getZ());
      glVertex3d(f.getX(),f.getY(),f.getZ());
      glColor3f(color.getX(), color.getY(), color.getZ());
      glVertex3d(t.getX(), t.getY(), t.getZ());
   glEnd();
}

void GLDebugDrawer::drawSphere (const btVector3& p, btScalar radius, const btVector3& color)
{
   btVector3 pp(p);
   pp.setX(p.x() / Irre::Physics_Scale_Factor);
   pp.setY(p.y() / Irre::Physics_Scale_Factor);
   pp.setZ(p.z() / Irre::Physics_Scale_Factor);


   glColor4f (color.getX(), color.getY(), color.getZ(), btScalar(1.0f));
   glPushMatrix ();
   glTranslatef (pp.getX(),pp.getY(), pp.getZ());

   int lats = 5;
   int longs = 5;

   int i, j;
   for(i = 0; i <= lats; i++) {
      btScalar lat0 = SIMD_PI * (-btScalar(0.5) + (btScalar) (i - 1) / lats);
      btScalar z0  = radius*sin(lat0);
      btScalar zr0 =  radius*cos(lat0);

      btScalar lat1 = SIMD_PI * (-btScalar(0.5) + (btScalar) i / lats);
      btScalar z1 = radius*sin(lat1);
      btScalar zr1 = radius*cos(lat1);

      glBegin(GL_QUAD_STRIP);
      for(j = 0; j <= longs; j++) {
         btScalar lng = 2 * SIMD_PI * (btScalar) (j - 1) / longs;
         btScalar x = cos(lng);
         btScalar y = sin(lng);

         glNormal3f(x * zr0, y * zr0, z0);
         glVertex3f(x * zr0, y * zr0, z0);
         glNormal3f(x * zr1, y * zr1, z1);
         glVertex3f(x * zr1, y * zr1, z1);
      }
      glEnd();
   }

   glPopMatrix();
}

void GLDebugDrawer::drawBox (const btVector3& boxMin, const btVector3& boxMax, const btVector3& color, btScalar alpha)
{
   btVector3 halfExtent = (boxMax - boxMin) / Irre::Physics_Scale_Factor;// * btScalar(0.5f);
   btVector3 center = ((boxMax + boxMin) * btScalar(0.5f)) / Irre::Physics_Scale_Factor;

   glColor4f (color.getX(), color.getY(), color.getZ(), alpha);

   glPushMatrix();

   //glTranslatef (center.getX(), center.getY(), center.getZ());
   //glScaled(2*halfExtent[0], 2*halfExtent[1], 2*halfExtent[2]);

   glBegin(GL_QUADS);
   {
      glColor4f (color.getX(), color.getY(), color.getZ(), POLY_ALPHA);

      glVertex3f(boxMin.getX(),boxMin.getY(),boxMin.getZ());
      glVertex3f(boxMin.getX(),boxMin.getY(),boxMax.getZ());
      glVertex3f(boxMin.getX(),boxMax.getY(),boxMax.getZ());
      glVertex3f(boxMax.getX(),boxMax.getY(),boxMax.getZ());
   }
   glEnd();

   glPopMatrix ();


}

void   GLDebugDrawer::drawTriangle(const btVector3& a,const btVector3& b,const btVector3& c,const btVector3& color,btScalar alpha)
{
   btVector3 aa(a); btVector3 bb(b); btVector3 cc(c);
   aa.setX(a.x() / Irre::Physics_Scale_Factor); aa.setY(a.y() / Irre::Physics_Scale_Factor); aa.setZ(a.z() / Irre::Physics_Scale_Factor);
   bb.setX(b.x() / Irre::Physics_Scale_Factor); bb.setY(b.y() / Irre::Physics_Scale_Factor); bb.setZ(b.z() / Irre::Physics_Scale_Factor);
   cc.setX(c.x() / Irre::Physics_Scale_Factor); cc.setY(c.y() / Irre::Physics_Scale_Factor); cc.setZ(c.z() / Irre::Physics_Scale_Factor);
//   if (m_debugMode > 0)
   {
      const btVector3   n=btCross(bb-aa,cc-aa).normalized();
      glBegin(GL_TRIANGLES);      
         glColor4f(color.getX(), color.getY(), color.getZ(),alpha);
         glNormal3d(n.getX(),n.getY(),n.getZ());
         glVertex3d(aa.getX(),aa.getY(),aa.getZ());
         glVertex3d(bb.getX(),bb.getY(),bb.getZ());
         glVertex3d(cc.getX(),cc.getY(),cc.getZ());
      glEnd();
   }
}

void   GLDebugDrawer::setDebugMode(int debugMode)
{
   m_debugMode = debugMode;
}

void   GLDebugDrawer::draw3dText(const btVector3& location,const char* textString)
{
}

void   GLDebugDrawer::reportErrorWarning(const char* warningString)
{
   printf("%s\n",warningString);
}

void   GLDebugDrawer::drawContactPoint(const btVector3& pointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)
{
   
   {
      btVector3 to=pointOnB+normalOnB*distance;
      const btVector3&from = pointOnB;
      glColor4f(color.getX(), color.getY(), color.getZ(),1.f);
      //glColor4f(0,0,0,1.f);

      glBegin(GL_LINES);
      glVertex3d(from.getX(), from.getY(), from.getZ());
      glVertex3d(to.getX(), to.getY(), to.getZ());
      glEnd();

      
      glRasterPos3f(from.x(),  from.y(),  from.z());
      char buf[12];
      sprintf(buf," %d",lifeTime);
      //BMF_DrawString(BMF_GetFont(BMF_kHelvetica10),buf);


   }
}


I guess I am asking for advice on what I currently have. The strange thing is that while the bullet debug renderer is broken, my canvas works fine. I am actually very tempted to just write a low level drawing extension that ties in with the Horde renderer just to solve this problem once and for all, unless somebody else has already. Or else, would anyone be willing to collaborate on such an extension? This would just be something that, for the time being, would allow us to draw geometry and lines at a lower level without having to worry about the OpenGL state outside of Horde3D for things such as Bullet debug drawing. This could also be expanded to a generic canvas similar to the one I have implemented for my game engine. I even have the AntiGrain Graphics library giving me these nice 2D vector graphics.


Top
 Profile  
Reply with quote  
PostPosted: 05.08.2011, 13:44 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
Before going into details, isn't there one glPopAttrib call to much after h3dFinalizeFrame() ?
And not sure currently if Horde3D restores all states when calling render. So maybe it would be better to push the attribs after finalizeFrame and make sure all states are properly set for your external rendering code and then call pop attrib afterwards


Top
 Profile  
Reply with quote  
PostPosted: 05.08.2011, 14:53 
Offline

Joined: 09.09.2009, 18:58
Posts: 107
Perhaps. I'll give that a look. The bigger problem here is the collision geometry not being generated properly. Were there changes to how the resources are mapped out?


Top
 Profile  
Reply with quote  
PostPosted: 22.08.2011, 13:54 
Offline

Joined: 09.09.2009, 18:58
Posts: 107
Fixed the problem. Turned out to be an issue to where the nodes were nott having their types validated before attempting to generate the collision geometry.

I would still like to figure out how to get the debug rendering working however, so if anyone has any suggestions, please, don't all rush in at once. :mrgreen:


Top
 Profile  
Reply with quote  
PostPosted: 23.08.2011, 10:51 
Offline

Joined: 24.03.2010, 10:17
Posts: 55
To me the push/pop looks fine (we're doing it the same way).
But why do you load the camera's inverted world matrix into modelview before debug drawing.
We simply load an identity matrix - that should be fine.
Also: I guess debug drawing does work if you comment the horde render block, right?


Top
 Profile  
Reply with quote  
PostPosted: 23.08.2011, 11:43 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
AlexL wrote:
To me the push/pop looks fine (we're doing it the same way).

push and pop in general is fine of course, I ment that there are two glPopAttrib calls where as there is only one glPushAttrib call.


Top
 Profile  
Reply with quote  
PostPosted: 23.08.2011, 18:16 
Offline

Joined: 24.03.2010, 10:17
Posts: 55
Yes, I missed that - there are 2 glPopAttrib calls. but as far as I remember, when the attrib stack is empty, should be ok - nevertheless one call should be removed.
Let's see what Orm has to report


Top
 Profile  
Reply with quote  
PostPosted: 24.08.2011, 16:53 
Offline

Joined: 09.09.2009, 18:58
Posts: 107
Not much I am afraid. I got some of it working wheere the debug info is drawn to screenspace, but not properly to worldspace. It seems like the projection matrix I'm getting from the engine doesn't like me a whole bunch. The attributes, however, are fine right now. It would be nice to see how somebody else has handled this aside from the game engine project. They seem to have greatly overcomplicated the matter. :roll:


Top
 Profile  
Reply with quote  
PostPosted: 25.08.2011, 08:37 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
Orm wrote:
They seem to have greatly overcomplicated the matter. :roll:

I won't take that personally :-)

You can have a look at the Horde3D editor. In GLWidget.cpp have a look at the renderEditorInfo() method.


Top
 Profile  
Reply with quote  
PostPosted: 25.08.2011, 15:41 
Offline

Joined: 09.09.2009, 18:58
Posts: 107
Or I could have been exaggerating. Perhaps I was looking at the wrong methods, because the code in GLPhysicsView looks pretty simple. I'll take a look at the code you linked and see what I can do.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group