Historique des modifications - Message

Message #5036

Sujet: Test Frustum


Type Date Auteur Contenu
Création du message 25-11-2008 20:46:59 tmyke
Bon, j'ai donc pris le temps ce soir de re-coder ma fonction DM3D qui était basée sur du code DX9c pour pouvoir tourner avec
Irrlicht. Cela semble bien fonctionner, je vais l'éprouver pour pouvoir l'intégrer dans mon moteur de terrain.

Le code se décompose en 4 parties:
1- une petite classe Plane, pour me faciliter les choses, quelques lignes pas bien sorcier.
2- UpdateCullInfo: partie qui permet d'établir les 6 plans du cube de polygone de vue.
3- _isVisible: fonction d'interogation pour savoir si un mesh (ou plutot son boundingBox) est visible ou non.
4- corps du programme de test (identique au code ci-dessus du message initial.


Voilà, voici donc le code complet, fonctions et corps de test.

#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
#ifdef _IRR_WINDOWS_
	#pragma comment(lib, "Irrlicht.lib")
#endif

//	données globales
bool _bExit = false;
ISceneManager* scenegraph;



//-----------------------------------------------------------------------------
// Name: Plane class
// Desc: petite classe plane personnalisée pour pour ce codage.
//-----------------------------------------------------------------------------
class Plane
{
public:
	float a;
	float b;
	float c;
	float d;

	Plane():  a(0),b(0),c(0),d(0) {}
	Plane(float aa, float bb, float cc, float dd): a(aa), b(bb), c(cc), d(dd){}
	Plane operator-(const Plane& other) const { return Plane(a - other.a, b - other.b, c - other.c, d - other.d); }
	Plane operator+(const Plane& other) const { return Plane(a + other.a, b + other.b, c + other.c, d + other.d); }
	float operator[](unsigned i) const 	{ switch(i)	{case 0: return a; case 1: return b; case 2: return c; case 3: return d;default: return 0;	}	}
	void Normalize() { float m;	m = sqrt( a*a + b*b + c*c + d*d );	a = a / m;	b = b / m;	c = c/ m;	d = d /m;	}
	float DotCoord(float *V) {	return (a * V[0] + b * V[1] + c * V[2] + d);	}
};
// donnée globale, ou autre en fonction des besoins
Plane	mFrustumPlane[6];
//-----------------------------------------------------------------------------
// Name: UpdateCullInfo()
// Desc: Update Cull Info, attention  avec la camera courante
//-----------------------------------------------------------------------------
void UpdateCullInfo()
{
	scene::ICameraSceneNode* cam = scenegraph->getActiveCamera();
	core::matrix4 pMatProj, pMatView;
	pMatProj = cam->getProjectionMatrix();
	pMatView = cam->getViewMatrix();
	core::matrix4 VPI = pMatProj * pMatView;

	Plane col0(VPI(0,0), VPI(1,0), VPI(2,0), VPI(3,0));
	Plane col1(VPI(0,1), VPI(1,1), VPI(2,1), VPI(3,1));
	Plane col2(VPI(0,2), VPI(1,2), VPI(2,2), VPI(3,2));
	Plane col3(VPI(0,3), VPI(1,3), VPI(2,3), VPI(3,3));
	// construit les 6 plane du Frustum view
	mFrustumPlane[0] = col2;          // near
	mFrustumPlane[1] = (col3 - col2); // far
	mFrustumPlane[2] = (col3 + col0); // left
	mFrustumPlane[3] = (col3 - col0); // right
	mFrustumPlane[4] = (col3 - col1); // top
	mFrustumPlane[5] = (col3 + col1); // bottom
	for(int i = 0; i < 6; i++)		
	{
		mFrustumPlane[i].Normalize();
	}
}
//-----------------------------------------------------------------------------
// Name: _isVisible()
// Desc: test de visibilité d'un mesh
//-----------------------------------------------------------------------------
int _isVisible(const core::aabbox3d<f32>& box)
{
	float P[3];
	float Q[3];
	// la classe vector3d ne possédant pas d'opérateur de surcharge []....
	float Min[3];	memcpy( Min, &box.MinEdge.X, sizeof(float)*3);
	float Max[3];	memcpy( Max, &box.MaxEdge.X, sizeof(float)*3);
	for(int i = 0; i < 6; ++i)
	{
		// pour chaque coordonnées x, y, z...
		for(int j = 0; j < 3; ++j)
		{
			// etabli le poiont PQ dans la même direction que le plan normal sur l'axe.
			if( mFrustumPlane[i][j] >= 0.0f )
			{
				P[j] = Min[j];
				Q[j] = Max[j];
			}
			else 
			{
				P[j] = Max[j];
				Q[j] = Min[j];
			}
		}
		if( mFrustumPlane[i].DotCoord(Q) < 0.0f  ) // en dehor, exit procedure
			return false;
	}
	return true;
}




int main()
{
	// choix driver
	video::E_DRIVER_TYPE driverType;
	
	printf("Please select the driver you want for this example:\
"\\
		" (a) Direct3D 9.0c\
 (b) Direct3D 8.1\
 (c) OpenGL 1.5\
"\\
		" (d) Software Renderer\
 (e) Burning's Software Renderer\
"\\
		" (f) NullDevice\
 (otherKey) exit\
\
");
		
	char i;
	std::cin >> i;

	switch(i)
	{
		case 'a': driverType = video::EDT_DIRECT3D9;break;
		case 'b': driverType = video::EDT_DIRECT3D8;break;
		case 'c': driverType = video::EDT_OPENGL;   break;
		case 'd': driverType = video::EDT_SOFTWARE; break;
		case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
		case 'f': driverType = video::EDT_NULL;     break;
		default: return 0;
	}
	IrrlichtDevice *device = createDevice( driverType, 
											dimension2d<s32>(640, 480), 
											32,
											false, 
											false, 
											true, 
											NULL);
	
	IVideoDriver* driver	= device->getVideoDriver();
	scenegraph				= device->getSceneManager();

		
	// cube 1
	ISceneNode* cube1 = scenegraph->addCubeSceneNode(2.0f, scenegraph->getRootSceneNode());
	cube1->setPosition( vector3df(10,0,0) );


	// définition camera.
	SKeyMap keyMap[4] = 
	{
		{EKA_MOVE_FORWARD,	KEY_UP},
		{EKA_MOVE_BACKWARD,	KEY_DOWN},
		{EKA_STRAFE_LEFT,	KEY_LEFT},
		{EKA_STRAFE_RIGHT,	KEY_RIGHT},
	};
	ICameraSceneNode* cam = scenegraph->addCameraSceneNodeFPS( scenegraph->getRootSceneNode() , 100.0f, 50.0f, -1, keyMap, 4);
	cam->setPosition(core::vector3df(0,1,-10));


	// boucle principale
	int lastFPS = -1;

	while(device->run() & !_bExit)
	{
		driver->beginScene(true, true, SColor(255,100,101,140));
			scenegraph->drawAll();
		driver->endScene();
		//============================
		// mise a jour frustum
		//============================
		UpdateCullInfo();
		//============================
		// frustum test
		//============================
		// récupération du boundingBox, puis transformation pour faire le test
		core::aabbox3d<f32> box = cube1->getBoundingBox();
		core::matrix4 matMesh = cube1->getAbsoluteTransformation();
		matMesh.transformBoxEx(box);
		int FrustumCode = _isVisible(box);


		// des information temps réél
		int fps = driver->getFPS();
		core::stringw str = L"Test visibilité: ";
		str += FrustumCode;
		device->setWindowCaption(str.c_str());
		lastFPS = fps;
	}
	device->drop();
	return 0;
}

Retour

Options Liens officiels Caractéristiques Statistiques Communauté
Préférences cookies
Corrections
irrlicht
irrklang
irredit
irrxml
Propulsé par Django
xhtml 1.0
css 2.1
884 membres
1440 sujets
11337 messages
Dernier membre inscrit: Saidov17
150 invités en ligne
membre en ligne: -
RSS Feed