virtual void render(const btDiscreteDynamicsWorld* rbWorld) 
	{
		//clear the color buffer
		TGAColor clearColor;
		clearColor.bgra[0] = 255;
		clearColor.bgra[1] = 255;
		clearColor.bgra[2] = 255;
		clearColor.bgra[3] = 255;
		
		clearBuffers(clearColor);
	
		
		ATTRIBUTE_ALIGNED16(btScalar modelMat[16]);
		ATTRIBUTE_ALIGNED16(float viewMat[16]);
		ATTRIBUTE_ALIGNED16(float projMat[16]);

		m_camera.getCameraProjectionMatrix(projMat);
		m_camera.getCameraViewMatrix(viewMat);
		
		btVector3 lightDirWorld(-5,200,-40);
		switch (m_upAxis)
		{
		case 1:
    			lightDirWorld = btVector3(-50.f,100,30);
    		break;
		case 2:
				lightDirWorld = btVector3(-50.f,30,100);
				break;
		default:{}
		};
		
		lightDirWorld.normalize();
		
		
		for (int i=0;i<rbWorld->getNumCollisionObjects();i++)
		{
			btCollisionObject* colObj = rbWorld->getCollisionObjectArray()[i];
			int colObjIndex = colObj->getUserIndex();
			int shapeIndex = colObj->getCollisionShape()->getUserIndex();
			if (colObjIndex>=0 && shapeIndex>=0)
			{
				
				TinyRenderObjectData* renderObj = 0;
				
				int* cptr = m_swInstances[colObjIndex];
				if (cptr)
				{
					int c = *cptr;
					TinyRenderObjectData** sptr = m_swRenderObjects[c];
					if (sptr)
					{
						renderObj = *sptr;
						//sync the object transform
						const btTransform& tr = colObj->getWorldTransform();
						tr.getOpenGLMatrix(modelMat);
				
						for (int i=0;i<4;i++)
						{
							for (int j=0;j<4;j++)
							{
								
								renderObj->m_projectionMatrix[i][j] = projMat[i+4*j];
								renderObj->m_modelMatrix[i][j] = modelMat[i+4*j];
								renderObj->m_viewMatrix[i][j] = viewMat[i+4*j];
								renderObj->m_localScaling = colObj->getCollisionShape()->getLocalScaling();
								renderObj->m_lightDirWorld = lightDirWorld;
							}
						}
						TinyRenderer::renderObject(*renderObj);
					}
				}
			}
		}
		
		
		static int counter=0;
		counter++;
		if ((counter&7)==0)
		{
			
			char filename[1024];
			sprintf(filename,"framebuf%d.tga",counter);
			m_rgbColorBuffer.flip_vertically();
			getFrameBuffer().write_tga_file(filename,true);
		}
		float color[4] = {1,1,1,1};
		
	}
void TinyRendererVisualShapeConverter::render(const float viewMat[16], const float projMat[16]) 
{
    //clear the color buffer
    TGAColor clearColor;
    clearColor.bgra[0] = 255;
    clearColor.bgra[1] = 255;
    clearColor.bgra[2] = 255;
    clearColor.bgra[3] = 255;
    
    clearBuffers(clearColor);

    
    ATTRIBUTE_ALIGNED16(btScalar modelMat[16]);
    
    
    btVector3 lightDirWorld(-5,200,-40);
    switch (m_data->m_upAxis)
    {
    case 1:
            lightDirWorld = btVector3(-50.f,100,30);
        break;
    case 2:
            lightDirWorld = btVector3(-50.f,30,100);
            break;
    default:{}
    };
    
    lightDirWorld.normalize();
    
  //  printf("num m_swRenderInstances = %d\n", m_data->m_swRenderInstances.size());
    for (int i=0;i<m_data->m_swRenderInstances.size();i++)
    {
        TinyRendererObjectArray** visualArrayPtr = m_data->m_swRenderInstances.getAtIndex(i);
        if (0==visualArrayPtr)
            continue;//can this ever happen?
        TinyRendererObjectArray* visualArray = *visualArrayPtr;

        btHashPtr colObjHash = m_data->m_swRenderInstances.getKeyAtIndex(i);
        
        
        const btCollisionObject* colObj = (btCollisionObject*) colObjHash.getPointer();
        
        for (int v=0;v<visualArray->m_renderObjects.size();v++)
        {
            
            TinyRenderObjectData* renderObj = visualArray->m_renderObjects[v];
            
        
            //sync the object transform
            const btTransform& tr = colObj->getWorldTransform();
            tr.getOpenGLMatrix(modelMat);
    
            for (int i=0;i<4;i++)
            {
                for (int j=0;j<4;j++)
                {
                    
                    renderObj->m_projectionMatrix[i][j] = projMat[i+4*j];
                    renderObj->m_modelMatrix[i][j] = modelMat[i+4*j];
                    renderObj->m_viewMatrix[i][j] = viewMat[i+4*j];
                    renderObj->m_localScaling = colObj->getCollisionShape()->getLocalScaling();
                    renderObj->m_lightDirWorld = lightDirWorld;
                }
            }
            TinyRenderer::renderObject(*renderObj);
        }
    }
	//printf("write tga \n");
	//m_data->m_rgbColorBuffer.write_tga_file("camera.tga");
//	printf("flipped!\n");
	m_data->m_rgbColorBuffer.flip_vertically();

	//flip z-buffer
	{
		int half = m_data->m_swHeight>>1;
		for (int j=0; j<half; j++)
		{
			unsigned long l1 = j*m_data->m_swWidth;
			unsigned long l2 = (m_data->m_swHeight-1-j)*m_data->m_swWidth;
			for (int i=0;i<m_data->m_swWidth;i++)
			{
				btSwap(m_data->m_depthBuffer[l1+i],m_data->m_depthBuffer[l2+i]);
			}
		}
	}
}
	virtual void render(const btDiscreteDynamicsWorld* rbWorld)
	{
		OpenGLGuiHelper::render(rbWorld);

		//clear the color buffer
		TGAColor clearColor;
		clearColor.bgra[0] = 255;
		clearColor.bgra[1] = 255;
		clearColor.bgra[2] = 255;
		clearColor.bgra[3] = 255;

		clearBuffers(clearColor);

		ATTRIBUTE_ALIGNED16(btScalar modelMat[16]);
		ATTRIBUTE_ALIGNED16(float viewMat[16]);
		ATTRIBUTE_ALIGNED16(float projMat[16]);

		CommonRenderInterface* render = getRenderInterface();

		render->getActiveCamera()->getCameraProjectionMatrix(projMat);
		render->getActiveCamera()->getCameraViewMatrix(viewMat);

		btVector3 lightDirWorld(-5, 200, -40);
		switch (1)  //app->getUpAxis())
		{
			case 1:
				lightDirWorld = btVector3(-50.f, 100, 30);
				break;
			case 2:
				lightDirWorld = btVector3(-50.f, 30, 100);
				break;
			default:
			{
			}
		};

		lightDirWorld.normalize();

		for (int i = 0; i < rbWorld->getNumCollisionObjects(); i++)
		{
			btCollisionObject* colObj = rbWorld->getCollisionObjectArray()[i];
			int colObjIndex = colObj->getUserIndex();
			int shapeIndex = colObj->getCollisionShape()->getUserIndex();
			if (colObjIndex >= 0 && shapeIndex >= 0)
			{
				TinyRenderObjectData* renderObj = 0;

				int* cptr = m_swInstances[colObjIndex];
				if (cptr)
				{
					int c = *cptr;
					TinyRenderObjectData** sptr = m_swRenderObjects[c];
					if (sptr)
					{
						renderObj = *sptr;
						//sync the object transform
						const btTransform& tr = colObj->getWorldTransform();
						tr.getOpenGLMatrix(modelMat);

						for (int i = 0; i < 4; i++)
						{
							for (int j = 0; j < 4; j++)
							{
								renderObj->m_projectionMatrix[i][j] = projMat[i + 4 * j];
								renderObj->m_modelMatrix[i][j] = modelMat[i + 4 * j];
								renderObj->m_viewMatrix[i][j] = viewMat[i + 4 * j];
							}
						}
						renderObj->m_localScaling = colObj->getCollisionShape()->getLocalScaling();
						renderObj->m_lightDirWorld = lightDirWorld;
						renderObj->m_lightAmbientCoeff = 0.6;
						renderObj->m_lightDiffuseCoeff = 0.35;
						renderObj->m_lightSpecularCoeff = 0.05;
						TinyRenderer::renderObject(*renderObj);
					}
				}
			}
		}

		for (int y = 0; y < m_swHeight; ++y)
		{
			unsigned char* pi = m_image + (y)*m_swWidth * 3;
			for (int x = 0; x < m_swWidth; ++x)
			{
				const TGAColor& color = getFrameBuffer().get(x, y);
				pi[0] = color.bgra[2];
				pi[1] = color.bgra[1];
				pi[2] = color.bgra[0];
				pi += 3;
			}
		}
		render->activateTexture(m_textureHandle);
		render->updateTexture(m_textureHandle, m_image);

		static int counter = 0;
		counter++;
		if ((counter & 7) == 0)
		{
			char filename[1024];
			sprintf(filename, "framebuf%d.tga", counter);
			getFrameBuffer().write_tga_file(filename, true);
		}
		float color[4] = {1, 1, 1, 1};
		m_primRenderer->drawTexturedRect(0, 0, m_swWidth, m_swHeight, color, 0, 0, 1, 1, true);
	}