MSVC 2010 Release build different than Debug? [SOLVED]

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
oringe
Posts: 41
Joined: Tue Jul 05, 2011 7:06 am
Location: San Francisco

MSVC 2010 Release build different than Debug? [SOLVED]

Post by oringe »

My game works fine when built under the Debug configuration in MSVC 2010 Express, but my custom scene nodes are not rendering correctly when I build under the Release config.
Instead of rendering EPT_QUADS I'm getting 3d lines that look like they span the aabbox extents?
I've carefully ensured that my Project Properties are all the same for both builds, including the same Directories, etc.
Very odd, I'm not sure where to begin debugging this?

Debug build: ( how it should look)
Image

Release build: ??
The gray square is rendering correctly because it is an irr::scene::CCubeSceneNode
Only my custom cubes are not rendering correctly
Image

Perhaps it has something to do with the way I've designed my custom cubes:

Code: Select all

class kxCubeNode : public ISceneNode
{
public:
    //! constructor
    kxCubeNode();
    virtual ~kxCubeNode() {}
 
    virtual void OnRegisterSceneNode();
 
    virtual void render();
 
    virtual const core::aabbox3d<f32>& getBoundingBox() const { return m_box; }
 
    virtual video::SMaterial& getMaterial( u32 i ) { return m_material; }
    virtual video::SMaterial& getEdgeMaterial() { return m_edgeMat; }
    virtual u32 getMaterialCount() const { return 1; }
 
    virtual ESCENE_NODE_TYPE getType() const { return (ESCENE_NODE_TYPE) KNT_CUBE; }
 
    virtual void makeMesh(); // creates a new unit cube
    virtual void setSize( const f32 newSize );  // multiplies all vertices positions by newSize
    f32 getSize() { return m_size; }
 
    virtual void setPosition( const vector3df& pos ) { ISceneNode::setPosition( pos ); }
 
 
    bool m_showNormals;
    f32 m_size;
 
    SMaterial m_material;
    SMaterial m_edgeMat;
 
    core::aabbox3d<f32> m_box;
    array< S3DVertex > m_vertices;
    array< u16 > m_indices;
    array< u16 > m_edgeIndices;
 
    kx& k; // context
};
 
kxCubeNode::kxCubeNode():
    k( kx::getInstance() ),
    ISceneNode( kx::getInstance().smgr->getRootSceneNode(), kx::getInstance().smgr, KNT_CUBE ),
    m_size( 1.6f ), m_showNormals( false )
{
    #ifdef _DEBUG
    setDebugName( "kxCubeNode" );
    #endif
    setName( "kxCubeNode" );
 
    m_material.setTexture( 0, k.grayTex );
    m_material.Lighting= true;
    m_material.GouraudShading= false; 
    m_edgeMat.Lighting= false;
 
    makeMesh();
    setSize( m_size );
}
 
 
void kxCubeNode::makeMesh()
{
    /*
     * 24 vertices; each face gets it's own 4 with normals
     * rendered with EPT_QUADS
                     
        5.8.18-----------3.11.19  
            /|          /|        +y
           / |         / |        ^   +z
          /  |        /  |        |  /
    4.9.22-----------0.10.21      | /
         |   |       |   |        |/
       6.14.17-------|--2.15.16   *----->+x
         |  /        |  / 
         | /         | / 
         |/          |/ 
   7.13.23-----------1.12.20
 
    */
 
    // vertex array
    f32 s= m_size/2;
    const f32 va[192] = 
    //   Pos          Normals      TCoords   Vertex  Face
    {
         s,  s, -s,   1,  0,  0,   0, 0,     // 0    +x
         s, -s, -s,   1,  0,  0,   0, 1,     // 1
         s, -s,  s,   1,  0,  0,   1, 1,     // 2
         s,  s,  s,   1,  0,  0,   1, 0,     // 3
 
        -s,  s, -s,  -1,  0,  0,   1, 0,     // 4    -x
        -s,  s,  s,  -1,  0,  0,   0, 0,     // 5
        -s, -s,  s,  -1,  0,  0,   0, 1,     // 6
        -s, -s, -s,  -1,  0,  0,   1, 1,     // 7
 
        -s,  s,  s,   0,  1,  0,   0, 0,     // 8    +y
        -s,  s, -s,   0,  1,  0,   0, 1,     // 9
         s,  s, -s,   0,  1,  0,   1, 1,     // 10
         s,  s,  s,   0,  1,  0,   1, 0,     // 11
 
         s, -s, -s,   0, -1,  0,   0, 1,     // 12   -y
        -s, -s, -s,   0, -1,  0,   1, 1,     // 13
        -s, -s,  s,   0, -1,  0,   1, 0,     // 14
         s, -s,  s,   0, -1,  0,   0, 0,     // 15
 
         s, -s,  s,   0,  0,  1,   0, 1,     // 16   +z
        -s, -s,  s,   0,  0,  1,   1, 1,     // 17
        -s,  s,  s,   0,  0,  1,   1, 0,     // 18
         s,  s,  s,   0,  0,  1,   0, 0,     // 19
 
         s, -s, -s,   0,  0, -1,   1, 1,     // 20   -z
         s,  s, -s,   0,  0, -1,   1, 0,     // 21
        -s,  s, -s,   0,  0, -1,   0, 0,     // 22
        -s, -s, -s,   0,  0, -1,   0, 1      // 23
    };
 
    // Vertices
    video::S3DVertex vx;
    //vx.Color.set(255,255,255,255);
 
    u32 i=0;
    for( s32 j=0; j<24; j++ )
    {
        vx.Pos.set( vector3df( va[i++], va[i++], va[i++] ));
        vx.Normal.set( vector3df( va[i++], va[i++], va[i++] ));
        vx.TCoords.set( vector2df( va[i++], va[i++] ));
        m_vertices.push_back( vx );
    }
 
    // quad indices
    for (u16 k=0; k<24; k++)
        m_indices.push_back( k );
 
    m_box= aabbox3df( m_vertices[0].Pos, m_vertices[6].Pos );
 
    // edge indices
    const u16 ei[24] = { 0,1, 1,2, 2,3, 3,0, 4,5, 5,6, 6,7, 7,4, 0,4, 1,7, 2,6, 3,5 };
    for (u16 e=0; e<24; e++)
        m_edgeIndices.push_back( ei[e] );
    }
 
void kxCubeNode::setSize( const f32 newSize )
{
    for( u32 vx= 0; vx<m_vertices.size(); vx++ )
    {
        m_vertices[vx].Pos *= vector3df( newSize/m_size );
        //m_vertices[vx].Normal *= vector3df( m_size/2 );
    }
    m_size= newSize;
}
 
void kxCubeNode::render()
{
    k.driver->setMaterial( m_material );
    k.driver->setTransform( ETS_WORLD, AbsoluteTransformation );
    k.driver->drawVertexPrimitiveList(
        &m_vertices[0], m_vertices.size(), 
        &m_indices[0], 
        6, // primitive count
        EVT_STANDARD, EPT_QUADS, 
        EIT_16BIT
    );
 
    // DRAW EDGES
    // build nudge matrix to avoid z-fighting
    vector3df camV= SceneManager->getActiveCamera()->getAbsolutePosition() - RelativeTranslation; 
    f32 length= .01f;
    f32 scale= ( camV.getLength() - length ) / camV.getLength();
    camV.setLength( length );
    camV += RelativeTranslation;
    matrix4 mx;
    mx.setScale( scale * RelativeScale );
    mx.setRotationDegrees( RelativeRotation );
    mx.setTranslation( camV );
 
    k.driver->setTransform( ETS_WORLD, mx );
    k.driver->setMaterial( m_edgeMat ); 
    k.driver->drawVertexPrimitiveList( &m_vertices[0], m_vertices.size(), &m_edgeIndices[0], 12, EVT_STANDARD, EPT_LINES );
 
    if( m_showNormals )
        for( u32 vx= 0; vx<m_vertices.size(); vx++ )
            k.driver->draw3DLine 
            (
                m_vertices[vx].Pos,
                m_vertices[vx].Pos + m_vertices[vx].Normal,
                SColor( 255,255,0,255 ) // purple
            );
}
 
Last edited by oringe on Wed Mar 27, 2013 4:49 am, edited 1 time in total.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: MSVC 2010 Release build different than Debug?

Post by CuteAlien »

Don't see anything wrong on a quick view (but I certainly might miss it as well). One of the most common reason for differences between debug and release builds are stuff like uninitialized variables. The way to debug those problems is using divide and conquer. Meaning you remove everything from your program that is not the bug (you divide your program source until the bug vanished, then add stuff back in until bug comes back, then remove code again, etc). In this example you should probably try to use this custom scenenode in a minimal application that contains nothing but a camera pointed ot a single node of this type and a minimal renderloop. If that works the problem is not in your customscenenode code and you can search for other places that could go wrong - if that already doesn't work you have a complete testcode to post here for getting more help.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
oringe
Posts: 41
Joined: Tue Jul 05, 2011 7:06 am
Location: San Francisco

Re: MSVC 2010 Release build different than Debug? [SOLVED]

Post by oringe »

oof, that was an intense debugging session. Finally figured it out.
I don't know the exact details between MSVC 2010 Express' debug build and the release build, but my research yielded a couple major things. Release builds generally include compiler optimizations, as well as handling uninitialized variables differently. My guess is that the debug build is more forgiving, and will compile things that a release build would either not compile, or throw an error at.
Anyway, I set up an isolated test environment and started with Irrlicht's Custom Scene Node example. After ensuring it worked in both build configs, I brought in my class and began comparing and contrasting and slowly replacing components until I had narrowed it down to the problem. After two hours I finally found it.
It was hiding in my usage of multiple post increment operators on a single line. Like this:

Code: Select all

    // Vertices
    video::S3DVertex vx;
    vx.Color.set(255,255,255,255);
 
    u16 i=0;
    for( u16 j=0; j<24; j++ )
    {
        vx.Pos.set( vector3df( va[i++], va[i++], va[i++] ));
        vx.Normal.set( vector3df( va[i++], va[i++], va[i++] ));
        vx.TCoords.set( vector2df( va[i++], va[i++] ));
        m_vertices.push_back( vx );
    }
 


"It is undefined behaviour to increment the same variable multiple times in a statement."
Here lies the problem. Changing the above code to something like this fixes it:

Code: Select all

        vx.Pos.set( vector3df( va[i], va[i+1], va[i+2] ));
        i += 3;
 
Apparently the Debug build configuration allows multiple increments in a single statement, while the Release will not. Lesson learned: Compile Release builds early and often!
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: MSVC 2010 Release build different than Debug? [SOLVED]

Post by CuteAlien »

Nice bug :-)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply