3rd person camera #3,267 (C&C needed for newbie)

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
ultramedia
Posts: 175
Joined: Wed Dec 20, 2006 12:04 pm

3rd person camera #3,267 (C&C needed for newbie)

Post by ultramedia »

Hey Everyone,

Ok, so I'm REAL new at C++ and Irrlicht, but not so new to programming in general (PHP, javascript, actionscript, maxscript). Anyways, I spent the whole day (17hrs) putting together this block of code to do a 3rd person camera the way I like them done. Could you guys who know what your doing and how things should be done have a look at it for me and see if you can see any nasty stupid mistakes? (It works for me here, I mean stuff like "you really shouldn't be doing that that way").

Controls are pretty easy :
right click and drag to orbit
mouse wheel to zoom
W key to move forward

Code: Select all

#include <iostream>
#include <Irrlicht.h> 

using namespace irr; 
using namespace core; 
using namespace scene; 
using namespace video; 
using namespace io; 
using namespace gui; 

#pragma comment(lib, "Irrlicht.lib") 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SETTINGS /////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// setup key engine objects
IrrlichtDevice* device = createDevice(EDT_OPENGL,dimension2d<s32>(800,600),32,false,false,false); 
IVideoDriver* driver = device->getVideoDriver(); 
ISceneManager* smgr = device->getSceneManager(); 
IGUIEnvironment* guienv = device->getGUIEnvironment(); 
ICursorControl* CursorControl;

// keyboard registry
bool keys[irr::KEY_KEY_CODES_COUNT];
	
// mouse registry
bool mouseDownL;
bool mouseDownM;
bool mouseDownR;
f32 lastWheelMovement;
position2d<f32> cursor;
position2d<f32> cursorOld;
position2d<f32> cursorDelta;

// camera registry
f32 cameraOrbit = 45;
f32 cameraAngle = 0;
f32 cameraDistance = 30;
f32 cameraOrbitOld = 0;
f32 cameraAngleOld = 0;

// player registry
f32 playerX = 0;
f32 playerY = 0;
f32 playerZ = 0;
f32 playerCompass = 30;
f32 playerTurnTo = 0;
f32 playerTurnSpeed = 1;
f32 playerMoveSpeed = 0.01;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CLASS : MyEventReceiver //////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	
class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(const SEvent& event)
	{
		if(event.EventType == irr::EET_KEY_INPUT_EVENT)
		{
			keys[event.KeyInput.Key] = event.KeyInput.PressedDown;
			return false;
		}

		if (event.EventType == EET_MOUSE_INPUT_EVENT) 
        { 
            // left mouse button state check
			if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)	mouseDownL = true;
			if(event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)		mouseDownL = false;

			// middle mouse button state check
			if(event.MouseInput.Event == EMIE_MMOUSE_PRESSED_DOWN)	mouseDownM = true;
			if(event.MouseInput.Event == EMIE_MMOUSE_LEFT_UP)		mouseDownM = false;

			if(event.MouseInput.Event == EMIE_MOUSE_WHEEL)
			{
				cameraDistance -= event.MouseInput.Wheel * (cameraDistance / 20) * 2;
				if(cameraDistance < 10) cameraDistance = 10;
				if(cameraDistance > 100) cameraDistance = 100;
			}

			// right mouse button state check
			if(event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN)
			{
				mouseDownR = true;
				cursorOld.X = event.MouseInput.X;
				cursorOld.Y = event.MouseInput.Y;
				cursorDelta.X = 0;
				cursorDelta.Y = 0;
				cameraOrbitOld = cameraOrbit;
				cameraAngleOld = cameraAngle;
			}
			if(event.MouseInput.Event == EMIE_RMOUSE_LEFT_UP)		mouseDownR = false;
			
			// mouse move check
			if(event.MouseInput.Event == EMIE_MOUSE_MOVED) 
            { 
				// add condition that right mouse button be down
				if(mouseDownR == true){
	                cursor.X = event.MouseInput.X; 
		            cursor.Y = event.MouseInput.Y; 
					cursorDelta.X = cursor.X - cursorOld.X;
					cursorDelta.Y = cursor.Y - cursorOld.Y;
					if(cursorDelta.Y > 100) cursorDelta.Y = 100;
					if(cursorDelta.Y < -100) cursorDelta.Y = -100;
					cameraOrbit = (int)(cameraOrbitOld + cursorDelta.X) % 360;
					cameraAngle = (int)(cameraAngleOld + cursorDelta.Y) % 360;
					if(cameraAngle > 88) cameraAngle = 88;
					if(cameraAngle < -88) cameraAngle = -88;
				}

            }
			return false;

        } 

		return false;
	}
};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CLASS : CMySampleSceneNode ///////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class CMySampleSceneNode : public ISceneNode 
{

	private: 
		static const s32 tileResolution = 32;	// how many segments to have down each edge of the tile
		static const s32 cellSize = 2;			// how many units square will each cell of the tile be?

		aabbox3d<f32> Box;     // [A]xis [A]ligned [B]ounding [B]ox in [3D] space
		S3DVertex Vertices[((tileResolution+1) * (tileResolution+1))]; // An array where each cell is of type S3DVertex
		u16 indices[(tileResolution * tileResolution) * 6];	// number of cells * 6 (each cell has two tris, each tri has 3 indices)
		SMaterial Material;    // A material object of type SMaterial
		IVideoDriver *driver;  // A link through to the driver object

	public: 

		/////////////////
		// constructor //
		/////////////////

		CMySampleSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id) : ISceneNode(parent, mgr, id) 
		{ 
			// put link to videoDriver into already prepared var of type IVideoDriver
			driver = SceneManager->getVideoDriver(); 
			
			// set material settings
			Material.Wireframe = true; 
			Material.Lighting = false; 
			Material.BackfaceCulling = false; 

			// create vertex objects in vertex array

			s32 vIndex = 0;
			for (f32 i=0; i<(tileResolution+1); i++){
				for (f32 j=0; j<(tileResolution+1); j++){
					Vertices[vIndex] = S3DVertex((j*cellSize),0,(i*cellSize), 0,0,1, SColor(255,0,255,255),j,i);
					// std :: cout << vIndex << ":" << j << "," << i << "\n";
					vIndex++;
				}
			}

			// reposition the bounding box to the first vertex
			Box.reset(Vertices[0].Pos); 

			// add the defined vertices to Box
			for (s32 i=0; i<vIndex; i++)
				Box.addInternalPoint(Vertices[i].Pos); 

			// setup indices
			s32	iIndex = 0;

			for (s32 i=0; i<tileResolution; i++){	
				for (s32 j=0; j<tileResolution; j++){

					s32 currentVertex = (i*(tileResolution+1)) + j;

					indices[iIndex + 0] = currentVertex;
					indices[iIndex + 1] = currentVertex+1;
					indices[iIndex + 2] = currentVertex+tileResolution+1;
					indices[iIndex + 3] = currentVertex+1;
					indices[iIndex + 4] = currentVertex+tileResolution+2;
					indices[iIndex + 5] = currentVertex+tileResolution+1;

					iIndex = iIndex + 6;

				}
			}

		}
		
		/////////////////////////
		// OnRegisterSceneNode //
		/////////////////////////

		virtual void OnRegisterSceneNode() 
		{ 
			if (IsVisible) 
				ISceneNode::OnRegisterSceneNode(); 
		}       
		
		///////////////
		// OnAnimate //
		///////////////

		virtual void OnAnimate(u32 timeMs) 
		{ 
			ISceneNode::OnAnimate(timeMs); 
		} 

		////////////
		// render //
		////////////

		virtual void render() 
		{ 
			driver->setMaterial(Material); 
			driver->setTransform(ETS_WORLD, AbsoluteTransformation); 

			driver->drawIndexedTriangleList(&Vertices[0],(tileResolution+1) * (tileResolution+1),&indices[0],((tileResolution*tileResolution)*2)); 
		} 

		////////////////////
		// getBoundingBox //
		////////////////////

		virtual const aabbox3d<f32>& getBoundingBox() const 
		{ 
			return Box; 
		} 
		
		//////////////////////
		// getMaterialCount //
		//////////////////////

		virtual u32 getMaterialCount() 
		{ 
			return 1; 
		} 

		/////////////////
		// getMaterial //
		/////////////////
		
		virtual SMaterial& getMaterial(s32 i) 
		{ 
			return Material; 
		} 
}; 


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTION : sphericalXYZ //////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

vector3df sphericalXYZ(f32 compassAngle, f32 elevationAngle, f32 radius){

	compassAngle = compassAngle * -1;
	elevationAngle = elevationAngle * -1;

	elevationAngle = elevationAngle + 90;

	f32 x = radius * cos(compassAngle * PI/180.0f ) * sin(elevationAngle * PI/180.0f );
	f32 z = radius * sin(compassAngle * PI/180.0f ) * sin(elevationAngle * PI/180.0f );
	f32 y = radius * cos(elevationAngle * PI/180.0f );

	vector3df result;
	result.X = x;
	result.Y = y;
	result.Z = z;
	return result;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTION : int2string ////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

stringw int2string(int intToConvert){
	char temp[50];
	sprintf(temp,"%d",intToConvert);
	return temp;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////        /////////////////////////////////////////////////////////////////////////////////////////////////////////////
////  MAIN  /////////////////////////////////////////////////////////////////////////////////////////////////////////////
////        /////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int main() 
{ 

	// setup event receiver
	MyEventReceiver rv;
	device->setEventReceiver(&rv);
	for(int x=0; x<irr::KEY_KEY_CODES_COUNT; x++) keys[x] = false;

	// setup screen display elements
	device->setWindowCaption(L"Irrlicht Custom Scene Node!"); 
	IGUIStaticText* debug_panel = guienv->addStaticText(L"Hello World",rect<s32>(5, 5, 200, 200),false,true,0,-1,false);

	// setup the "player"
	ISceneNode* cPivot1 = smgr->addCubeSceneNode(0.5,0,-1,vector3df(playerX,playerY,playerZ));
	cPivot1->setMaterialTexture(0,driver->getTexture("media/wall.bmp"));
	cPivot1->setMaterialFlag(video::EMF_LIGHTING, false);

	ISceneNode* cPivot2 = smgr->addCubeSceneNode(2,cPivot1,-1,vector3df(0,1,0));
	cPivot2->setMaterialTexture(0,driver->getTexture("media/wall.bmp"));
	cPivot2->setMaterialFlag(video::EMF_LIGHTING, false);

	ISceneNode* cPivot3 = smgr->addCubeSceneNode(1,cPivot2,-1,vector3df(0,0,2));
	cPivot3->setMaterialTexture(0,driver->getTexture("media/wall.bmp"));
	cPivot3->setMaterialFlag(video::EMF_LIGHTING, false);

	// setup the camera
	ICameraSceneNode* myCamera = smgr->addCameraSceneNode(cPivot1, sphericalXYZ(cameraOrbit,cameraAngle,cameraDistance), cPivot1->getPosition()); 

	// create references to our custom nodes
	CMySampleSceneNode* myNode = new CMySampleSceneNode(smgr->getRootSceneNode(),smgr,1); 
	myNode->setPosition(vector3df(0,0,0));

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// DEVICE : main loop ///////////////////////////////////////////////////////////////////////////////////////////////////
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	while(device->run() && device->isWindowActive()) { 
		
		/////////////////////////
		// keyboard management //
		/////////////////////////

		// system keys
		if(keys[KEY_ESCAPE]){
			device->closeDevice();
		}
		
		// player keys

		if(keys[KEY_KEY_W]){ 

			// player movement vector
			vector3df playerStep = sphericalXYZ(cameraOrbit,0,playerMoveSpeed);
			playerX -= playerStep.X;
			playerY -= playerStep.Y;
			playerZ -= playerStep.Z;

			// player rotation brain torture
			
			playerTurnTo = cameraOrbit - 90;
			if(playerTurnTo < 0) playerTurnTo += 360;
			if(playerTurnTo >= 360) playerTurnTo -= 360;
			
			if(playerCompass < 0) playerCompass = playerCompass + 360;
			if(playerCompass >= 360) playerCompass = playerCompass - 360;

			f32 playerTurnDir = 0;
			f32 playerTurnDelta = 0;

			if(playerCompass > playerTurnTo)
			{
				if(playerCompass - playerTurnTo < 180){
					playerTurnDir = -1;
					playerTurnDelta = playerCompass - playerTurnTo;
				} else {
					playerTurnDir = 1;
					playerTurnDelta = (360 - playerCompass) + playerTurnTo;
				}
			}

			if(playerCompass < playerTurnTo)
			{
				if(playerTurnTo - playerCompass < 180){
					playerTurnDir = 1;
					playerTurnDelta = playerTurnTo - playerCompass;
				} else {
					playerTurnDir = -1;
					playerTurnDelta = (360 - playerTurnTo) + playerCompass;
				}
			}

			f32 playerTurnAmount;

			if(playerTurnDelta < playerTurnSpeed){
				playerTurnAmount = playerTurnDelta;
			} else {
				playerTurnAmount = playerTurnSpeed;
			}
			playerCompass += (playerTurnAmount * playerTurnDir);


			cPivot1->setPosition(vector3df(playerX,playerY,playerZ));
			cPivot2->setRotation(vector3df(0,playerCompass,0));
			myCamera->setTarget(vector3df(playerX,playerY,playerZ));
		}
		
		// orient camera
		myCamera->setPosition(sphericalXYZ(cameraOrbit,cameraAngle,cameraDistance));

		// debug display
		stringw displayFPS    = (stringw)"FPS : " + int2string(driver->getFPS());
		stringw displayLmouse = (stringw)"left mouse button : " + mouseDownL;
		stringw displayMmouse = (stringw)"middle mouse button : " + mouseDownM;
		stringw displayRmouse = (stringw)"right mouse button : " + mouseDownR;
		stringw displayWmouse = (stringw)"last wheel movement : " + lastWheelMovement;
		stringw displayCursorX = (stringw)"cursor x : " + cursor.X;
		stringw displayCursorY = (stringw)"cursor y : " + cursor.Y;
		stringw displayCursorOldX = (stringw)"cursorOld x : " + cursorOld.X;
		stringw displayCursorOldY = (stringw)"cursorOld y : " + cursorOld.Y;
		stringw displayCursorDeltaX = (stringw)"cursorDelta x : " + cursorDelta.X;
		stringw displayCursorDeltaY = (stringw)"cursorDelta y : " + cursorDelta.Y;
		stringw displayCameraOrbit = (stringw)"camera orbit : " + cameraOrbit;
		stringw displayCameraAngle = (stringw)"camera angle : " + cameraAngle;
		stringw displayPlayerCompass = (stringw)"player compass : " + playerCompass;
		stringw displayPlayerTurnTo = (stringw)"player turn to : " + playerTurnTo;

		stringw displayDebug  = displayFPS + "\n" + 
								displayLmouse + "\n" +
								displayMmouse + "\n" +
								displayRmouse + "\n" +
								displayWmouse + "\n" +
								displayCursorX + "\n" +
								displayCursorY + "\n" +
								displayCursorOldX + "\n" +
								displayCursorOldY + "\n" +
								displayCursorDeltaX + "\n" +
								displayCursorDeltaY + "\n" +
								displayCameraOrbit + "\n" +
								displayCameraAngle + "\n" +
								displayPlayerCompass + "\n" + 
								displayPlayerTurnTo;

		debug_panel->setText(stringw(displayDebug).c_str());

		//////////////////
		// render scene //
		//////////////////

		driver->beginScene(true, true, SColor(0,120,120,120)); 

		myNode->render(); 
		smgr->drawAll(); 

		guienv->drawAll();
		 
		driver->endScene(); 
	} 
    
   device->drop(); 
   return 0; 
} 
shadowslair
Posts: 758
Joined: Mon Mar 31, 2008 3:32 pm
Location: Bulgaria

Post by shadowslair »

Haha!

I really like it! It reminds me of one DarkBasic Pro demo called: "smooth rotate towards point, or some other bla-bla-shitty stuff"... :D

This may become useful. Thanks e lot ultramedia! :wink:

Ah, and I like the way the code is arranged. It reminds me of... me... :shock:
"Although we walk on the ground and step in the mud... our dreams and endeavors reach the immense skies..."
hach-que
Posts: 33
Joined: Thu Apr 19, 2007 10:11 am
Location: Australia

Post by hach-que »

I'm gonna modify this so that the camera automatically focuses on direction the player is facing, instead of the other way round.
ultramedia
Posts: 175
Joined: Wed Dec 20, 2006 12:04 pm

Post by ultramedia »

Shouldn't be too hard.

My target is MMORPG type control, cos it lets you see more of your character. I also have some cool ideas (at least I think they're cool) for combat UI - more soon...
lymantok
Posts: 67
Joined: Mon Dec 31, 2007 6:13 am

Post by lymantok »

Hey Ultramedia, great example, and just what I was looking for.

FYI, I ran into some warn and errs (commented out the errs):

stringw displayLmouse = (stringw)"left mouse button : " + mouseDownL;

main.cpp(425) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'bool' (or there is no acceptable conversion)
:could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1> with
1> [
1> T=wchar_t
1> ]
1> while trying to match the argument list '(irr::core::string<T>, bool)'
1> with
1> [
1> T=wchar_t
1> ]

Bunch of warnings on lines like:

cursorOld.X = event.MouseInput.X;

main.cpp(105) : warning C4244: '=' : conversion from 'const irr::s32' to 'irr::f32', possible loss of data

cameraOrbit = (int)(cameraOrbitOld + cursorDelta.X) % 360;

main.cpp(126) : warning C4244: '=' : conversion from 'int' to 'irr::f32', possible loss of data
Likort
Posts: 8
Joined: Wed Mar 28, 2007 9:28 pm

Post by Likort »

lymantok wrote:stringw displayLmouse = (stringw)"left mouse button : " + mouseDownL;
I changed all those into something like

stringw displayLmouse = (stringw)"left mouse button : " + (stringw)mouseDownL;

i just added (stringw) to the variable then it compiled just fine and everything still got displayed, e.g. mousebuttons false/true as 0 and 1
Likort
Posts: 8
Joined: Wed Mar 28, 2007 9:28 pm

Post by Likort »

also, there is a little issue with cursorDelta.Y - you are allowing a camera angle between 88 and -88 (above and beneath the character), but when moving the camera the delta.y is restricted to 100. so if you are looking from above, then want to go down, you are stuck after 100 delta and have to let go of rmb, then click again and continue moving to get fully beneath the char.

changing lines 106 & 107 into

if(cursorDelta.Y > 176) cursorDelta.Y = 176;
if(cursorDelta.Y < -176) cursorDelta.Y = -176;

will fix this. 88 times 2 is 176 :wink:
lymantok
Posts: 67
Joined: Mon Dec 31, 2007 6:13 am

Post by lymantok »

Thx for the fixes Likort! I see what you mean on the restricted movement. Just curious, any idea why 88 was selected?
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

To avoid gimbal lock and because if the camera looks in the same direction or opposite to its up vector, i.e. 0,1,0) or (0,-1,0), then its rotation is undefined.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Katsankat
Posts: 178
Joined: Sun Mar 12, 2006 4:15 am
Contact:

Post by Katsankat »

:wink: This camera is how it should be in the mesh viewer, but without global variables.

Smaller code just before "render scene":

Code: Select all

      // debug display 
      stringw s(L"FPS : "); s+= int2string(driver->getFPS()); 
      s += L"\nleft mouse button : "; s+= mouseDownL; 
      s += L"\nmiddle mouse button : "; s+= mouseDownM; 
      s += L"\nright mouse button : "; s+= mouseDownR; 
      s += L"\nlast wheel movement : "; s+= lastWheelMovement; 
      s += L"\ncursor x : "; s+= cursor.X; 
      s += L"\ncursor y : "; s+= cursor.Y; 
      s += L"\ncursorOld x : "; s+= cursorOld.X; 
      s += L"\ncursorOld y : "; s+= cursorOld.Y; 
      s += L"\ncursorDelta x : "; s+= cursorDelta.X; 
      s += L"\ncursorDelta y : "; s+= cursorDelta.Y; 
      s += L"\ncamera orbit : "; s+= cameraOrbit; 
      s += L"\ncamera angle : "; s+= cameraAngle; 
      s += L"\nplayer compass : "; s+= playerCompass; 
      s += L"\nplayer turn to : "; s+= playerTurnTo; 
      debug_panel->setText(s.c_str()); 
Pyritie
Posts: 120
Joined: Fri Jan 16, 2009 12:59 pm
Contact:

Post by Pyritie »

Thanks for this! It's very helpful :D
FaTaL_N00B
Posts: 7
Joined: Wed Jul 15, 2009 8:19 am
Location: Pretoria, South-Africa
Contact:

Post by FaTaL_N00B »

Hey there! Sorry to bother you guys with this, I just started out using Irrlicht and I'm a huge n00b at it so far... I searched throughout the forums for a 3rd person camera example and this one seemed the best/neatest.

I realized that there was quite a large deal of coding hehe so I thought I'd just copy paste the code at first and try to learn it from there, but I received a whole bunch of errors. 14 to be precise and 8 warnings. :?:

Here is the error I receive:

Code: Select all

1>------ Build started: Project: camera angle stuff1, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(50) : warning C4305: 'initializing' : truncation from 'double' to 'irr::f32'
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(88) : warning C4244: '=' : conversion from 'const irr::s32' to 'irr::f32', possible loss of data
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(89) : warning C4244: '=' : conversion from 'const irr::s32' to 'irr::f32', possible loss of data
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(102) : warning C4244: '=' : conversion from 'const irr::s32' to 'irr::f32', possible loss of data
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(103) : warning C4244: '=' : conversion from 'const irr::s32' to 'irr::f32', possible loss of data
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(108) : warning C4244: '=' : conversion from 'int' to 'irr::f32', possible loss of data
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(109) : warning C4244: '=' : conversion from 'int' to 'irr::f32', possible loss of data
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(284) : warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>        c:\program files\microsoft visual studio 9.0\vc\include\stdio.h(366) : see declaration of 'sprintf'
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(407) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'bool' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, bool)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(408) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'bool' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, bool)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(409) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'bool' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, bool)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(410) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'irr::f32' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, irr::f32)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(411) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'irr::f32' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, irr::f32)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(412) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'irr::f32' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, irr::f32)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(413) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'irr::f32' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, irr::f32)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(414) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'irr::f32' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, irr::f32)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(415) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'irr::f32' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, irr::f32)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(416) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'irr::f32' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, irr::f32)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(417) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'irr::f32' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, irr::f32)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(418) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'irr::f32' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, irr::f32)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(419) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'irr::f32' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, irr::f32)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>c:\users\the enemy\documents\visual studio 2008\projects\camera angle stuff1\camera angle stuff1\main.cpp(420) : error C2679: binary '+' : no operator found which takes a right-hand operand of type 'irr::f32' (or there is no acceptable conversion)
1>        d:\stuff\t\vc\sdk\irrlicht-1.5\include\irrstring.h(264): could be 'irr::core::string<T> irr::core::string<T>::operator +(const irr::core::string<T> &) const'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>        while trying to match the argument list '(irr::core::string<T>, irr::f32)'
1>        with
1>        [
1>            T=wchar_t
1>        ]
1>Build log was saved at "file://c:\Users\The Enemy\Documents\Visual Studio 2008\Projects\camera angle stuff1\camera angle stuff1\Debug\BuildLog.htm"
1>camera angle stuff1 - 14 error(s), 8 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Once more sorry! :oops:
Ever stop to think... and forget to start again?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

When adding to a string (i.e. appending with +=) you have to wrap the numbers with core::stringc(...) with latest Irrlicht versions. This helps to rethink those situations and make really sure you want to append to a string, not just calculating something. But this is all very basic C++ and compiler message interpretation - maybe first learn the language and tools with some more basic stuff?!
Rei
Posts: 4
Joined: Mon Aug 17, 2009 1:51 pm

Post by Rei »

Hello

This camera is basically exactly what I need for my game. So thanks a lot to ultramedia for working on this. However I found it to be a little buggy, so I made a few changes.

Changes:
- I applied Katsankat's suggestion for the "debug display" part so theres no compiler errors with newer versions of Irrlicht (mentioned in the 2 posts above mine).

- With the bug with having to press right mouse again to move further after the CursorDelta reaches 100... I tried Likort's suggestion for changing the 88s to 176s (around line 120) however that seemed to cause other problems, like if you would move the camera all the way up to the top (looking straight down) then go forward more, the camera would flip around or something but it would still think it's facing the other way, and pressing W would cause the character to go in the backwards direction instead of forwards.

So I left the 88s as they were and the solution I used is this:

Code: Select all

			   if (cursorDelta.Y > (88 - cameraAngleOld)) {
				   cursorOld.Y += (cursorDelta.Y - cursorDeltaOld.Y);
				   cursorDelta.Y = 88 - cameraAngleOld;
			   }
			   if (cursorDelta.Y < (-88 - cameraAngleOld)) {
				   cursorOld.Y += (cursorDelta.Y - cursorDeltaOld.Y);
				   cursorDelta.Y = -88 - cameraAngleOld;
			   }
Basically instead of limiting the delta to 100, I changed the 100s to 88s and the delta limits are based on where the angle was when you started to hold down right mouse (not sure if I am explaining this right, but if you try it, it will make sense).

Also you can see I am changing the cursorOld.Y value in these parts too. This is to solve another sort of "bug", basically I added another variable called cursorDeltaOld which so that each frame it remembers the previous delta. If you hit the very top or very bottom view with the camera, instead of increasing the delta more like before as you drag more, it will move cursorOld accordingly. The effect this gives is that when you start to drag in the opposite direction again, the camera will start to move immediately, rather than having to move the mouse all the way back down to where it hit the limit before (the "tilt" of the camera will be frozen until you do). With this, that "bug/limitation" won't happen.

Again perhaps bad explanation but if you try both this code and the code in the opening post and compare the behaviour, you will see what I mean.

I also added the appropriate casts where needed and changed sprintf() to sprintf_s() (idk, the compiler said sprintf was depreciated and to use sprintf_s instead). So all the compiler warnings regarding "possible loss of data" won't appear any more either.

Notes for customizing it:

- For customizing the limits on how high/low the camera can tilt, simply change the 88s on line 109,111,113,115,121,122 to a smaller number to suit your needs, but don't put it higher than 88 since this already gives you the full camera range.

- You can customize the sensitivity of the camera by the multiplier (it's 1.0 in this sample) on line 107 and 108.


Here is the full updated code.

Code: Select all

#include <iostream>
#include <Irrlicht.h>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#pragma comment(lib, "Irrlicht.lib")

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SETTINGS /////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// setup key engine objects
IrrlichtDevice* device = createDevice(EDT_OPENGL,dimension2d<s32>(800,600),32,false,false,false);
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
ICursorControl* CursorControl;

// keyboard registry
bool keys[irr::KEY_KEY_CODES_COUNT];
   
// mouse registry
bool mouseDownL;
bool mouseDownM;
bool mouseDownR;
f32 lastWheelMovement;
position2d<f32> cursor;
position2d<f32> cursorOld;
position2d<f32> cursorDelta;
position2d<f32> cursorDeltaOld;

// camera registry
f32 cameraOrbit = 45;
f32 cameraAngle = 0;
f32 cameraDistance = 30;
f32 cameraOrbitOld = 0;
f32 cameraAngleOld = 0;

// player registry
f32 playerX = 0;
f32 playerY = 0;
f32 playerZ = 0;
f32 playerCompass = 30;
f32 playerTurnTo = 0;
f32 playerTurnSpeed = 1;
f32 playerMoveSpeed = 0.01f;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CLASS : MyEventReceiver //////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   
class MyEventReceiver : public IEventReceiver
{
public:
   virtual bool OnEvent(const SEvent& event)
   {
      if(event.EventType == irr::EET_KEY_INPUT_EVENT)
      {
         keys[event.KeyInput.Key] = event.KeyInput.PressedDown;
         return false;
      }

      if (event.EventType == EET_MOUSE_INPUT_EVENT)
        {
         // left mouse button state check
         if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)   mouseDownL = true;
         if(event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)      mouseDownL = false;

         // middle mouse button state check
         if(event.MouseInput.Event == EMIE_MMOUSE_PRESSED_DOWN)   mouseDownM = true;
         if(event.MouseInput.Event == EMIE_MMOUSE_LEFT_UP)      mouseDownM = false;

         if(event.MouseInput.Event == EMIE_MOUSE_WHEEL)
         {
            cameraDistance -= event.MouseInput.Wheel * (cameraDistance / 20) * 2;
            if(cameraDistance < 10) cameraDistance = 10;
            if(cameraDistance > 100) cameraDistance = 100;
         }

         // right mouse button state check
         if(event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN)
         {
            mouseDownR = true;
            cursorOld.X = (f32)event.MouseInput.X;
            cursorOld.Y = (f32)event.MouseInput.Y;
            cursorDelta.X = 0;
            cursorDelta.Y = 0;
            cursorDeltaOld.X = 0;
            cursorDeltaOld.Y = 0;
            cameraOrbitOld = cameraOrbit;
            cameraAngleOld = cameraAngle;
         }
         if(event.MouseInput.Event == EMIE_RMOUSE_LEFT_UP)      mouseDownR = false;
         
         // mouse move check
         if(event.MouseInput.Event == EMIE_MOUSE_MOVED)
            {
            // add condition that right mouse button be down
            if(mouseDownR == true){
               cursor.X = (f32)event.MouseInput.X;
               cursor.Y = (f32)event.MouseInput.Y;
               cursorDelta.X = (f32)((cursor.X - cursorOld.X) * 1.0);
               cursorDelta.Y = (f32)((cursor.Y - cursorOld.Y) * 1.0);
			   if (cursorDelta.Y > (88 - cameraAngleOld)) {
				   cursorOld.Y += (cursorDelta.Y - cursorDeltaOld.Y);
				   cursorDelta.Y = 88 - cameraAngleOld;
			   }
			   if (cursorDelta.Y < (-88 - cameraAngleOld)) {
				   cursorOld.Y += (cursorDelta.Y - cursorDeltaOld.Y);
				   cursorDelta.Y = -88 - cameraAngleOld;
			   }
			   cursorDeltaOld.X = cursorDelta.X;
			   cursorDeltaOld.Y = cursorDelta.Y;
               cameraOrbit = (f32)((int)(cameraOrbitOld + cursorDelta.X) % 360);
               cameraAngle = (f32)((int)(cameraAngleOld + cursorDelta.Y) % 360);
               if(cameraAngle > 88) cameraAngle = 88;
               if(cameraAngle < -88) cameraAngle = -88;
            }

            }
         return false;

        }

      return false;
   }
};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CLASS : CMySampleSceneNode ///////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class CMySampleSceneNode : public ISceneNode
{

   private:
      static const s32 tileResolution = 32;   // how many segments to have down each edge of the tile
      static const s32 cellSize = 2;         // how many units square will each cell of the tile be?

      aabbox3d<f32> Box;     // [A]xis [A]ligned [B]ounding [B]ox in [3D] space
      S3DVertex Vertices[((tileResolution+1) * (tileResolution+1))]; // An array where each cell is of type S3DVertex
      u16 indices[(tileResolution * tileResolution) * 6];   // number of cells * 6 (each cell has two tris, each tri has 3 indices)
      SMaterial Material;    // A material object of type SMaterial
      IVideoDriver *driver;  // A link through to the driver object

   public:

      /////////////////
      // constructor //
      /////////////////

      CMySampleSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id) : ISceneNode(parent, mgr, id)
      {
         // put link to videoDriver into already prepared var of type IVideoDriver
         driver = SceneManager->getVideoDriver();
         
         // set material settings
         Material.Wireframe = true;
         Material.Lighting = false;
         Material.BackfaceCulling = false;

         // create vertex objects in vertex array

         s32 vIndex = 0;
         for (f32 i=0; i<(tileResolution+1); i++){
            for (f32 j=0; j<(tileResolution+1); j++){
               Vertices[vIndex] = S3DVertex((j*cellSize),0,(i*cellSize), 0,0,1, SColor(255,0,255,255),j,i);
               // std :: cout << vIndex << ":" << j << "," << i << "\n";
               vIndex++;
            }
         }

         // reposition the bounding box to the first vertex
         Box.reset(Vertices[0].Pos);

         // add the defined vertices to Box
         for (s32 i=0; i<vIndex; i++)
            Box.addInternalPoint(Vertices[i].Pos);

         // setup indices
         s32   iIndex = 0;

         for (s32 i=0; i<tileResolution; i++){   
            for (s32 j=0; j<tileResolution; j++){

               s32 currentVertex = (i*(tileResolution+1)) + j;

               indices[iIndex + 0] = currentVertex;
               indices[iIndex + 1] = currentVertex+1;
               indices[iIndex + 2] = currentVertex+tileResolution+1;
               indices[iIndex + 3] = currentVertex+1;
               indices[iIndex + 4] = currentVertex+tileResolution+2;
               indices[iIndex + 5] = currentVertex+tileResolution+1;

               iIndex = iIndex + 6;

            }
         }

      }
      
      /////////////////////////
      // OnRegisterSceneNode //
      /////////////////////////

      virtual void OnRegisterSceneNode()
      {
         if (IsVisible)
            ISceneNode::OnRegisterSceneNode();
      }       
      
      ///////////////
      // OnAnimate //
      ///////////////

      virtual void OnAnimate(u32 timeMs)
      {
         ISceneNode::OnAnimate(timeMs);
      }

      ////////////
      // render //
      ////////////

      virtual void render()
      {
         driver->setMaterial(Material);
         driver->setTransform(ETS_WORLD, AbsoluteTransformation);

         driver->drawIndexedTriangleList(&Vertices[0],(tileResolution+1) * (tileResolution+1),&indices[0],((tileResolution*tileResolution)*2));
      }

      ////////////////////
      // getBoundingBox //
      ////////////////////

      virtual const aabbox3d<f32>& getBoundingBox() const
      {
         return Box;
      }
      
      //////////////////////
      // getMaterialCount //
      //////////////////////

      virtual u32 getMaterialCount()
      {
         return 1;
      }

      /////////////////
      // getMaterial //
      /////////////////
      
      virtual SMaterial& getMaterial(s32 i)
      {
         return Material;
      }
};


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTION : sphericalXYZ //////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

vector3df sphericalXYZ(f32 compassAngle, f32 elevationAngle, f32 radius){

   compassAngle = compassAngle * -1;
   elevationAngle = elevationAngle * -1;

   elevationAngle = elevationAngle + 90;

   f32 x = radius * cos(compassAngle * PI/180.0f ) * sin(elevationAngle * PI/180.0f );
   f32 z = radius * sin(compassAngle * PI/180.0f ) * sin(elevationAngle * PI/180.0f );
   f32 y = radius * cos(elevationAngle * PI/180.0f );

   vector3df result;
   result.X = x;
   result.Y = y;
   result.Z = z;
   return result;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTION : int2string ////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

stringw int2string(int intToConvert){
   char temp[50];
   sprintf_s(temp,"%d",intToConvert);
   return temp;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////        /////////////////////////////////////////////////////////////////////////////////////////////////////////////
////  MAIN  /////////////////////////////////////////////////////////////////////////////////////////////////////////////
////        /////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

int main()
{

   // setup event receiver
   MyEventReceiver rv;
   device->setEventReceiver(&rv);
   for(int x=0; x<irr::KEY_KEY_CODES_COUNT; x++) keys[x] = false;

   // setup screen display elements
   device->setWindowCaption(L"Irrlicht Custom Scene Node!");
   IGUIStaticText* debug_panel = guienv->addStaticText(L"Hello World",rect<s32>(5, 5, 200, 200),false,true,0,-1,false);

   // setup the "player"
   ISceneNode* cPivot1 = smgr->addCubeSceneNode(0.5,0,-1,vector3df(playerX,playerY,playerZ));
   cPivot1->setMaterialTexture(0,driver->getTexture("media/wall.bmp"));
   cPivot1->setMaterialFlag(video::EMF_LIGHTING, false);

   ISceneNode* cPivot2 = smgr->addCubeSceneNode(2,cPivot1,-1,vector3df(0,1,0));
   cPivot2->setMaterialTexture(0,driver->getTexture("media/wall.bmp"));
   cPivot2->setMaterialFlag(video::EMF_LIGHTING, false);

   ISceneNode* cPivot3 = smgr->addCubeSceneNode(1,cPivot2,-1,vector3df(0,0,2));
   cPivot3->setMaterialTexture(0,driver->getTexture("media/wall.bmp"));
   cPivot3->setMaterialFlag(video::EMF_LIGHTING, false);

   // setup the camera
   ICameraSceneNode* myCamera = smgr->addCameraSceneNode(cPivot1, sphericalXYZ(cameraOrbit,cameraAngle,cameraDistance), cPivot1->getPosition());

   // create references to our custom nodes
   CMySampleSceneNode* myNode = new CMySampleSceneNode(smgr->getRootSceneNode(),smgr,1);
   myNode->setPosition(vector3df(0,0,0));

   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   // DEVICE : main loop ///////////////////////////////////////////////////////////////////////////////////////////////////
   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   while(device->run()) {
      
      /////////////////////////
      // keyboard management //
      /////////////////////////

      // system keys
      if(keys[KEY_ESCAPE]){
         device->closeDevice();
      }
      
      // player keys

      if(keys[KEY_KEY_W]){

         // player movement vector
         vector3df playerStep = sphericalXYZ(cameraOrbit,0,playerMoveSpeed);
         playerX -= playerStep.X;
         playerY -= playerStep.Y;
         playerZ -= playerStep.Z;

         // player rotation brain torture
         
         playerTurnTo = cameraOrbit - 90;
         if(playerTurnTo < 0) playerTurnTo += 360;
         if(playerTurnTo >= 360) playerTurnTo -= 360;
         
         if(playerCompass < 0) playerCompass = playerCompass + 360;
         if(playerCompass >= 360) playerCompass = playerCompass - 360;

         f32 playerTurnDir = 0;
         f32 playerTurnDelta = 0;

         if(playerCompass > playerTurnTo)
         {
            if(playerCompass - playerTurnTo < 180){
               playerTurnDir = -1;
               playerTurnDelta = playerCompass - playerTurnTo;
            } else {
               playerTurnDir = 1;
               playerTurnDelta = (360 - playerCompass) + playerTurnTo;
            }
         }

         if(playerCompass < playerTurnTo)
         {
            if(playerTurnTo - playerCompass < 180){
               playerTurnDir = 1;
               playerTurnDelta = playerTurnTo - playerCompass;
            } else {
               playerTurnDir = -1;
               playerTurnDelta = (360 - playerTurnTo) + playerCompass;
            }
         }

         f32 playerTurnAmount;

         if(playerTurnDelta < playerTurnSpeed){
            playerTurnAmount = playerTurnDelta;
         } else {
            playerTurnAmount = playerTurnSpeed;
         }
         playerCompass += (playerTurnAmount * playerTurnDir);


         cPivot1->setPosition(vector3df(playerX,playerY,playerZ));
         cPivot2->setRotation(vector3df(0,playerCompass,0));
         myCamera->setTarget(vector3df(playerX,playerY,playerZ));
      }
      
      // orient camera
      myCamera->setPosition(sphericalXYZ(cameraOrbit,cameraAngle,cameraDistance));

      // debug display
      stringw s(L"FPS : "); s+= int2string(driver->getFPS());
      s += L"\nleft mouse button : "; s+= mouseDownL;
      s += L"\nmiddle mouse button : "; s+= mouseDownM;
      s += L"\nright mouse button : "; s+= mouseDownR;
      s += L"\nlast wheel movement : "; s+= lastWheelMovement;
      s += L"\ncursor x : "; s+= cursor.X;
      s += L"\ncursor y : "; s+= cursor.Y;
      s += L"\ncursorOld x : "; s+= cursorOld.X;
      s += L"\ncursorOld y : "; s+= cursorOld.Y;
      s += L"\ncursorDelta x : "; s+= cursorDelta.X;
      s += L"\ncursorDelta y : "; s+= cursorDelta.Y;
      s += L"\ncamera orbit : "; s+= cameraOrbit;
      s += L"\ncamera angle : "; s+= cameraAngle;
      s += L"\nplayer compass : "; s+= playerCompass;
      s += L"\nplayer turn to : "; s+= playerTurnTo;
      debug_panel->setText(s.c_str()); 

      //////////////////
      // render scene //
      //////////////////

      driver->beginScene(true, true, SColor(0,120,120,120));

      myNode->render();
      smgr->drawAll();

      guienv->drawAll();
      
      driver->endScene();
   }
   
   device->drop();
   return 0;
}
Hope it's useful to somebody.
6opoDuJIo
Posts: 7
Joined: Fri Aug 21, 2009 5:20 pm

Post by 6opoDuJIo »

I did create follow-camera but I had some problems
at motion of object which a camera is fastened on, on a sloping surface, a camera terribly trembles and even sometimes sharply rides up up
who that can advise?


sorry for my bad english :wink:
Post Reply