Native Rendersystem Calls        

How do use native OpenGL and Direct3D calls inside Ogre by Assaf Raman- http://www.ogre3d.org/forums/viewtopic.php?f=1&t=43156

/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

You may use this sample code for anything you like, it is not covered by the
LGPL like the rest of the engine.
-----------------------------------------------------------------------------
*/

/**
    \file 
        NativeRenderSystemCommands.h
    \brief
	 A sample demonstrating how to add render system specific native code to an existing scene.  
	 I based this sample on the SkyDome sample, just added a FrameListener
   
*/


#include "..\..\SkyDome\include\SkyDome.h"
#include <gl\gl.h>
#include <d3d9.h>

class RenderSystemCommandsRenderQueueListener : public RenderQueueListener
{
protected:
	MovableObject* mObject;		
	const Camera* mCamera;		
	SceneManager* mSceneMgr;
	RenderWindow* mWindow;

	virtual void Render() = 0;
	virtual void PreRender() = 0;
	virtual void PostRender() = 0;
public:	
	RenderSystemCommandsRenderQueueListener(MovableObject* object, const Camera* camera, RenderWindow* window, SceneManager* sceneMgr) :
	mObject(object),
	mCamera(camera),
	mWindow(window),
	mSceneMgr(sceneMgr)
	{

	}

	virtual void renderQueueStarted(uint8 queueGroupId, const String& invocation, 
		bool& skipThisInvocation) { }

	virtual void renderQueueEnded(uint8 queueGroupId, const String& invocation, 
		bool& repeatThisInvocation)
	{
		// Set wanted render queue here - make sure there are - make sure that something is on
		// this queue - else you will never pass this if.
		if (queueGroupId != RENDER_QUEUE_MAIN) 
			return;

		PreRender();

		Render();

		PostRender();
	}

};

class OpenGLRenderSystemCommandsRenderQueueListener : public RenderSystemCommandsRenderQueueListener
{
protected:
	virtual void PreRender() 
	{
		// save matrices
		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();
		glMatrixMode(GL_PROJECTION);
		glPushMatrix();
		glMatrixMode(GL_TEXTURE);
		glPushMatrix();
		glLoadIdentity(); //Texture addressing should start out as direct.

		RenderSystem* renderSystem = mObject->_getManager()->getDestinationRenderSystem();
		Node* parentNode = mObject->getParentNode();
		renderSystem->_setWorldMatrix(parentNode->_getFullTransform());
		renderSystem->_setViewMatrix(mCamera->getViewMatrix());
		renderSystem->_setProjectionMatrix(mCamera->getProjectionMatrixRS());

		static Pass* clearPass = NULL;
		if (!clearPass)
		{
			MaterialPtr clearMat = MaterialManager::getSingleton().getByName("BaseWhite");
			clearPass = clearMat->getTechnique(0)->getPass(0);
		}
		//Set a clear pass to give the renderer a clear renderstate
		mSceneMgr->_setPass(clearPass, true, false);

		// save attribs
		glPushAttrib(GL_ALL_ATTRIB_BITS);

	}
	

	virtual void PostRender()
	{
		// restore original state
		glPopAttrib();

		// restore matrices
		glMatrixMode(GL_TEXTURE);
		glPopMatrix();
		glMatrixMode(GL_PROJECTION);
		glPopMatrix();
		glMatrixMode(GL_MODELVIEW);
		glPopMatrix();
	}
public:
	OpenGLRenderSystemCommandsRenderQueueListener(MovableObject* object, const Camera* camera, RenderWindow* window, SceneManager* sceneMgr) :
	  RenderSystemCommandsRenderQueueListener(object, camera, window, sceneMgr)
	  {

	  }

};


class CubeOpenGLRenderSystemCommandsRenderQueueListener : public OpenGLRenderSystemCommandsRenderQueueListener
{
protected:
	void Render()
	{

		GLboolean depthTestEnabled=glIsEnabled(GL_DEPTH_TEST);
		glDisable(GL_DEPTH_TEST);
		GLboolean stencilTestEnabled = glIsEnabled(GL_STENCIL_TEST);
		glDisable(GL_STENCIL_TEST);

		glDisable(GL_TEXTURE_2D);
		glDisable(GL_LIGHTING);

		glScalef(30.0, 30.0, 30.0);

		// I took the following sample code from here: http://www.oreillynet.com/network/2000/06/23/magazine/cube.c

		// OK, let's start drawing our planer quads.
		glBegin(GL_QUADS); 


		// Bottom Face.  Red, 75% opaque, magnified texture

		glNormal3f( 0.0f, -1.0f, 0.0f); // Needed for lighting
		glColor4f(0.9,0.2,0.2,.75); // Basic polygon color

		glTexCoord2f(0.800f, 0.800f); glVertex3f(-1.0f, -1.0f, -1.0f); 
		glTexCoord2f(0.200f, 0.800f); glVertex3f( 1.0f, -1.0f, -1.0f);
		glTexCoord2f(0.200f, 0.200f); glVertex3f( 1.0f, -1.0f,  1.0f);
		glTexCoord2f(0.800f, 0.200f); glVertex3f(-1.0f, -1.0f,  1.0f);


		// Top face; offset.  White, 50% opaque.

		glNormal3f( 0.0f, 1.0f, 0.0f);  glColor4f(0.5,0.5,0.5,.5);

		glTexCoord2f(0.005f, 1.995f); glVertex3f(-1.0f,  1.3f, -1.0f);
		glTexCoord2f(0.005f, 0.005f); glVertex3f(-1.0f,  1.3f,  1.0f);
		glTexCoord2f(1.995f, 0.005f); glVertex3f( 1.0f,  1.3f,  1.0f);
		glTexCoord2f(1.995f, 1.995f); glVertex3f( 1.0f,  1.3f, -1.0f);


		// Far face.  Green, 50% opaque, non-uniform texture cooridinates.

		glNormal3f( 0.0f, 0.0f,-1.0f);  glColor4f(0.2,0.9,0.2,.5); 

		glTexCoord2f(0.995f, 0.005f); glVertex3f(-1.0f, -1.0f, -1.3f);
		glTexCoord2f(2.995f, 2.995f); glVertex3f(-1.0f,  1.0f, -1.3f);
		glTexCoord2f(0.005f, 0.995f); glVertex3f( 1.0f,  1.0f, -1.3f);
		glTexCoord2f(0.005f, 0.005f); glVertex3f( 1.0f, -1.0f, -1.3f);


		// Right face.  Blue; 25% opaque

		glNormal3f( 1.0f, 0.0f, 0.0f);  glColor4f(0.2,0.2,0.9,.25);

		glTexCoord2f(0.995f, 0.005f); glVertex3f( 1.0f, -1.0f, -1.0f); 
		glTexCoord2f(0.995f, 0.995f); glVertex3f( 1.0f,  1.0f, -1.0f);
		glTexCoord2f(0.005f, 0.995f); glVertex3f( 1.0f,  1.0f,  1.0f);
		glTexCoord2f(0.005f, 0.005f); glVertex3f( 1.0f, -1.0f,  1.0f);


		// Front face; offset.  Multi-colored, 50% opaque.

		glNormal3f( 0.0f, 0.0f, 1.0f); 

		glColor4f( 0.9f, 0.2f, 0.2f, 0.5f);
		glTexCoord2f( 0.005f, 0.005f); glVertex3f(-1.0f, -1.0f,  1.3f);
		glColor4f( 0.2f, 0.9f, 0.2f, 0.5f);
		glTexCoord2f( 0.995f, 0.005f); glVertex3f( 1.0f, -1.0f,  1.3f);
		glColor4f( 0.2f, 0.2f, 0.9f, 0.5f);
		glTexCoord2f( 0.995f, 0.995f); glVertex3f( 1.0f,  1.0f,  1.3f); 
		glColor4f( 0.1f, 0.1f, 0.1f, 0.5f);
		glTexCoord2f( 0.005f, 0.995f); glVertex3f(-1.0f,  1.0f,  1.3f);


		// Left Face; offset.  Yellow, varying levels of opaque.

		glNormal3f(-1.0f, 0.0f, 0.0f);  

		glColor4f(0.9,0.9,0.2,0.0);
		glTexCoord2f(0.005f, 0.005f); glVertex3f(-1.3f, -1.0f, -1.0f); 
		glColor4f(0.9,0.9,0.2,0.66);
		glTexCoord2f(0.995f, 0.005f); glVertex3f(-1.3f, -1.0f,  1.0f);
		glColor4f(0.9,0.9,0.2,1.0);
		glTexCoord2f(0.995f, 0.995f); glVertex3f(-1.3f,  1.0f,  1.0f);
		glColor4f(0.9,0.9,0.2,0.33);
		glTexCoord2f(0.005f, 0.995f); glVertex3f(-1.3f,  1.0f, -1.0f);


		// All polygons have been drawn.
		glEnd();


		if (depthTestEnabled)
		{
			glEnable(GL_DEPTH_TEST);
		}
		if (stencilTestEnabled)
		{
			glEnable(GL_STENCIL_TEST);
		}


	}
public:
	CubeOpenGLRenderSystemCommandsRenderQueueListener(MovableObject* object, const Camera* camera, RenderWindow* window, SceneManager* sceneMgr) :
	  OpenGLRenderSystemCommandsRenderQueueListener(object, camera, window, sceneMgr)
	  {

	  }
};

/////////////////////////////////////////

class D3D9RenderSystemCommandsRenderQueueListener : public RenderSystemCommandsRenderQueueListener
{
protected:
	virtual void PreRender() 
	{


		RenderSystem* renderSystem = mObject->_getManager()->getDestinationRenderSystem();
		Node* parentNode = mObject->getParentNode();
		renderSystem->_setWorldMatrix(parentNode->_getFullTransform());
		renderSystem->_setViewMatrix(mCamera->getViewMatrix());
		renderSystem->_setProjectionMatrix(mCamera->getProjectionMatrixRS());

		static Pass* clearPass = NULL;
		if (!clearPass)
		{
			MaterialPtr clearMat = MaterialManager::getSingleton().getByName("BaseWhite");
			clearPass = clearMat->getTechnique(0)->getPass(0);
		}
		//Set a clear pass to give the renderer a clear renderstate
		mSceneMgr->_setPass(clearPass, true, false);



	}


	virtual void PostRender()
	{

	}
public:
	D3D9RenderSystemCommandsRenderQueueListener(MovableObject* object, const Camera* camera, RenderWindow* window, SceneManager* sceneMgr) :
	  RenderSystemCommandsRenderQueueListener(object, camera, window, sceneMgr)
	  {

	  }

};


class CubeD3D9RenderSystemCommandsRenderQueueListener : public D3D9RenderSystemCommandsRenderQueueListener
{
protected:
	void Render()
	{

		LPDIRECT3DDEVICE9       pd3dDevice = NULL; // Our rendering device
		LPDIRECT3DVERTEXBUFFER9 pVB        = NULL; // Buffer to hold vertices

		RenderSystem* renderSystem = mObject->_getManager()->getDestinationRenderSystem();
	
		mWindow->getCustomAttribute( "D3DDEVICE", &pd3dDevice );


		pd3dDevice->SetRenderState(D3DRS_LIGHTING, false);
		pd3dDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, TVC_DIFFUSE);

		// A structure for our custom vertex type
		struct CUSTOMVERTEX
		{
			Vector3 pos;      // The untransformed, 3D position for the vertex
			Vector3 normal;      // The untransformed, 3D position for the vertex
			DWORD color;        // The vertex color
		};
		
		// Our custom FVF, which describes our custom vertex structure
		#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE)

		#define SCALE_FACTOR 30

		// Initialize three vertices for rendering a triangle
		static const CUSTOMVERTEX cubeVertices[] =
		{
			// Bottom Face.  
			{ Vector3(-1.0f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( 0.0f, -1.0f, 0.0f), 0xff000000, },
			{ Vector3( 1.0f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( 0.0f, -1.0f, 0.0f), 0xff000000, },
			{ Vector3( 1.0f, -1.0f,  1.0f) * SCALE_FACTOR, Vector3( 0.0f, -1.0f, 0.0f), 0xff000000, },
			{ Vector3( 1.0f, -1.0f,  1.0f) * SCALE_FACTOR, Vector3( 0.0f, -1.0f, 0.0f), 0xff000000, },
			{ Vector3(-1.0f, -1.0f,  1.0f) * SCALE_FACTOR, Vector3( 0.0f, -1.0f, 0.0f), 0xff000000, },
			{ Vector3(-1.0f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( 0.0f, -1.0f, 0.0f), 0xff000000, },

			// Top Face.  
			{ Vector3(-1.0f,  1.3f, -1.0f) * SCALE_FACTOR, Vector3( 0.0f, 1.0f, 0.0f), 0xffffff00, },
			{ Vector3(-1.0f,  1.3f,  1.0f) * SCALE_FACTOR, Vector3( 0.0f, 1.0f, 0.0f), 0xffffff00, },
			{ Vector3( 1.0f,  1.3f,  1.0f) * SCALE_FACTOR, Vector3( 0.0f, 1.0f, 0.0f), 0xffffff00, },
			{ Vector3( 1.0f,  1.3f,  1.0f) * SCALE_FACTOR, Vector3( 0.0f, 1.0f, 0.0f), 0xffffff00, },
			{ Vector3( 1.0f,  1.3f, -1.0f) * SCALE_FACTOR, Vector3( 0.0f, 1.0f, 0.0f), 0xffffff00, },
			{ Vector3(-1.0f,  1.3f, -1.0f) * SCALE_FACTOR, Vector3( 0.0f, 1.0f, 0.0f), 0xffffff00, },

			// Far Face.  
			{ Vector3(-1.0f, -1.0f, -1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f,-1.0f), 0x00ff0000, },
			{ Vector3(-1.0f,  1.0f, -1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f,-1.0f), 0x00ff0000, },
			{ Vector3( 1.0f,  1.0f, -1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f,-1.0f), 0x00ff0000, },
			{ Vector3( 1.0f,  1.0f, -1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f,-1.0f), 0x00ff0000, },
			{ Vector3( 1.0f, -1.0f, -1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f,-1.0f), 0x00ff0000, },
			{ Vector3(-1.0f, -1.0f, -1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f,-1.0f), 0x00ff0000, },

			// Right Face.  
			{ Vector3( 1.0f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( 1.0f, 0.0f, 0.0f), 0x0000ff00, },
			{ Vector3( 1.0f,  1.0f, -1.0f) * SCALE_FACTOR, Vector3( 1.0f, 0.0f, 0.0f), 0x0000ff00, },
			{ Vector3( 1.0f,  1.0f,  1.0f) * SCALE_FACTOR, Vector3( 1.0f, 0.0f, 0.0f), 0x0000ff00, },
			{ Vector3( 1.0f,  1.0f,  1.0f) * SCALE_FACTOR, Vector3( 1.0f, 0.0f, 0.0f), 0x0000ff00, },
			{ Vector3( 1.0f, -1.0f,  1.0f) * SCALE_FACTOR, Vector3( 1.0f, 0.0f, 0.0f), 0x0000ff00, },
			{ Vector3( 1.0f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( 1.0f, 0.0f, 0.0f), 0x0000ff00, },

			// Front Face.
			{ Vector3(-1.0f, -1.0f,  1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f, 1.0f), 0xff00ff00, },
			{ Vector3( 1.0f, -1.0f,  1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f, 1.0f), 0x00ffff00, },
			{ Vector3( 1.0f,  1.0f,  1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f, 1.0f), 0x0000ff00, },
			{ Vector3( 1.0f,  1.0f,  1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f, 1.0f), 0x0000ff00, },
			{ Vector3(-1.0f,  1.0f,  1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f, 1.0f), 0xffffff00, },
			{ Vector3(-1.0f, -1.0f,  1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f, 1.0f), 0xff00ff00, },

			// Left Face.  
			{ Vector3(-1.3f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( -1.0f, 0.0f, 0.0f), 0xffff0000, },
			{ Vector3(-1.3f, -1.0f,  1.0f) * SCALE_FACTOR, Vector3( -1.0f, 0.0f, 0.0f), 0xffff0000, },
			{ Vector3(-1.3f,  1.0f,  1.0f) * SCALE_FACTOR, Vector3( -1.0f, 0.0f, 0.0f), 0xffff0000, },
			{ Vector3(-1.3f,  1.0f,  1.0f) * SCALE_FACTOR, Vector3( -1.0f, 0.0f, 0.0f), 0xffff0000, },
			{ Vector3(-1.3f,  1.0f, -1.0f) * SCALE_FACTOR, Vector3( -1.0f, 0.0f, 0.0f), 0xffff0000, },
			{ Vector3(-1.3f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( -1.0f, 0.0f, 0.0f), 0xffff0000, },
		};

		
		UINT primitiveCount = sizeof(cubeVertices)  / sizeof(CUSTOMVERTEX) / 3;

		// Create the vertex buffer.
		if( FAILED( pd3dDevice->CreateVertexBuffer( sizeof(cubeVertices),
			0, D3DFVF_CUSTOMVERTEX,
			D3DPOOL_DEFAULT, &pVB, NULL ) ) )
		{
			return;//E_FAIL;
		}

		// Fill the vertex buffer.
		VOID* pVertices;
		if( FAILED( pVB->Lock( 0, sizeof(cubeVertices), (void**)&pVertices, 0 ) ) )
			return;// E_FAIL;
		memcpy( pVertices, cubeVertices, sizeof(cubeVertices) );
		pVB->Unlock();

	
		

		// Render the vertex buffer contents
		pd3dDevice->SetStreamSource( 0, pVB, 0, sizeof(CUSTOMVERTEX) );
		pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, primitiveCount );

		pVB->Release();

	}
public:
	CubeD3D9RenderSystemCommandsRenderQueueListener(MovableObject* object, const Camera* camera, RenderWindow* window, SceneManager* sceneMgr) :
	  D3D9RenderSystemCommandsRenderQueueListener(object, camera, window, sceneMgr)
	  {

	  }
};

/////////////////////////////////////////



class NativeRenderSystemCommandsApplication : public SkyDomeApplication
{
public:
    NativeRenderSystemCommandsApplication()
    {
    }

protected:
	RenderQueueListener * mRenderSystemCommandsRenderQueueListener;
    // Just override the mandatory create scene method
    void createScene(void)
    {
		SkyDomeApplication::createScene();

		ManualObject *manObj; // we will use this Manual Object as a reference point for the native rendering
        manObj = mSceneMgr->createManualObject("sampleArea");
		
        // Attach to child of root node, better for culling (otherwise bounds are the combination of the 2)
        mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(manObj);

		String RenderSystemName = mSceneMgr->getDestinationRenderSystem()->getName();
		mRenderSystemCommandsRenderQueueListener = NULL;
		if ("OpenGL Rendering Subsystem" == RenderSystemName)
		{
			mRenderSystemCommandsRenderQueueListener = new CubeOpenGLRenderSystemCommandsRenderQueueListener(
				manObj, mCamera, mWindow, mSceneMgr);
			mSceneMgr->addRenderQueueListener(mRenderSystemCommandsRenderQueueListener);
		}

		if ("Direct3D9 Rendering Subsystem" == RenderSystemName)
		{
			mRenderSystemCommandsRenderQueueListener = new CubeD3D9RenderSystemCommandsRenderQueueListener(
				manObj, mCamera, mWindow, mSceneMgr);
			mSceneMgr->addRenderQueueListener(mRenderSystemCommandsRenderQueueListener);
		}

			

		

    }
	void destroyScene()
	{
		if (mRenderSystemCommandsRenderQueueListener)
		{
			mSceneMgr->removeRenderQueueListener(mRenderSystemCommandsRenderQueueListener);
			delete mRenderSystemCommandsRenderQueueListener;
			mRenderSystemCommandsRenderQueueListener = NULL;
		}


		SkyDomeApplication::destroyScene();
	}

};

/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

You may use this sample code for anything you like, it is not covered by the
LGPL like the rest of the engine.
-----------------------------------------------------------------------------
*/

/**
    \file 
        NativeRenderSystemCommands.cpp
    \brief
   A sample demonstrating how to add render system specific native code to an existing scene.  
*/

#include "NativeRenderSystemCommands.h"

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char *argv[])
#endif
{

    // Create application object
    NativeRenderSystemCommandsApplication app;

    try {
        app.go();
    } catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
        std::cerr << "An exception has occured: " <<
            e.getFullDescription().c_str() << std::endl;
#endif
    }


    return 0;
}

#ifdef __cplusplus
}
#endif