3rd person camera #3,267 (C&C needed for newbie)
Hey ultramedia. thanks for this. It's very useful.
But something error in it when I built it.
I'm sorry, I can't show my error message.
but I changed
IrrlichtDevice* device = createDevice(EDT_OPENGL,dimension2d<s32>(800,600),32,false,false,false);
to
IrrlichtDevice* device = createDevice(EDT_OPENGL,dimension2d<u32>(800,600),32,false,false,false);
But something error in it when I built it.
I'm sorry, I can't show my error message.
but I changed
IrrlichtDevice* device = createDevice(EDT_OPENGL,dimension2d<s32>(800,600),32,false,false,false);
to
IrrlichtDevice* device = createDevice(EDT_OPENGL,dimension2d<u32>(800,600),32,false,false,false);
Thanks for the camera, nice one.
However, I found a little issue. The camera "jumps" some pixels (in my case) if you rotate it with the mouse, so it doesn't feel smooth. That is because you lose the float precision by casting into an integer in order to do integer modulo ( % ). To fix that you just have to use float mod:
replace these lines
with
and you are all set
However, I found a little issue. The camera "jumps" some pixels (in my case) if you rotate it with the mouse, so it doesn't feel smooth. That is because you lose the float precision by casting into an integer in order to do integer modulo ( % ). To fix that you just have to use float mod:
replace these lines
Code: Select all
cameraOrbit = (f32)((int)(cameraOrbitOld + cursorDelta.X) % 360);
cameraAngle = (f32)((int)(cameraAngleOld + cursorDelta.Y) % 360);
Code: Select all
cameraOrbit = fmod( (cameraOrbitOld + cursorDelta.X), 360);
cameraAngle = fmod( (cameraAngleOld + cursorDelta.Y), 360);
-
- Posts: 13
- Joined: Fri Feb 19, 2010 5:07 pm
- Contact:
Good stuff.
Rei, I got your latest code to compile just fine under Linux and using the latest Irr libs.
One change...
I had to change
sprintf_s(temp,"%d",intToConvert);
to
sprintf(temp,"%d",intToConvert);
Apparently sprintf_s is a mickeysoft thing? Hmmm not sure.
Anyways, works like a charm! Thanks everyone for the info!
Rei, I got your latest code to compile just fine under Linux and using the latest Irr libs.
One change...
I had to change
sprintf_s(temp,"%d",intToConvert);
to
sprintf(temp,"%d",intToConvert);
Apparently sprintf_s is a mickeysoft thing? Hmmm not sure.
Anyways, works like a charm! Thanks everyone for the info!
wow that looks like some nice spagethicode....seriously make a class out of it and maybe even a ISceneNodeAnimator that can be attached to a camera. but that way the code is not ruseable for any real projects...
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
thanks !!!! nice camera, very useful to me !!
my first app with irrlicht http://youtube.com/watch?v=8OHUgciBT8E
Here is a update code :
What i update ?
I add rotation with W A S D but there are errors !!! it only works with W and S perfect but if you press A or D you move in that direction but the camera not! Anyone can help me ?
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<u32>(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 = 135;
f32 cameraAngle = 35;
f32 cameraDistance = 6;
f32 cameraOrbitOld = 0;
f32 cameraAngleOld = 0;
// player registry
f32 playerX = 12;
f32 playerY = 0;
f32 playerZ = 15;
f32 playerCompass = 0;
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 < 6) cameraDistance = 6;
if(cameraDistance > 12) cameraDistance = 12;
}
// 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 < 18) cameraAngle = 18;
}
}
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"First Game");
IGUIStaticText* debug_panel = guienv->addStaticText(L"Debug Panel",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->setMaterialFlag(video::EMF_LIGHTING, false);
ISceneNode* cPivot2 = smgr->addCubeSceneNode(2,cPivot1,-1,vector3df(0,1,0));
cPivot2->setMaterialTexture(0,driver->getTexture("wall.bmp"));
cPivot2->setMaterialFlag(video::EMF_LIGHTING, false);
ISceneNode* cPivot3 = smgr->addCubeSceneNode(1,cPivot2,-1,vector3df(0,1.5,0));
cPivot3->setMaterialTexture(0,driver->getTexture("wall.bmp"));
cPivot3->setMaterialFlag(video::EMF_LIGHTING, false);
ISceneNode* cPivot4 = smgr->addCubeSceneNode(1,cPivot2,-1,vector3df(0,0,1.5));
cPivot4->setMaterialTexture(0,driver->getTexture("wall.bmp"));
cPivot4->setMaterialFlag(video::EMF_LIGHTING, false);
ISceneNode* cPivot5 = smgr->addCubeSceneNode(0.5,cPivot2,-1,vector3df(0,0,2.2));
cPivot5->setMaterialTexture(0,driver->getTexture("wall.bmp"));
cPivot5->setMaterialFlag(video::EMF_LIGHTING, false);
ISceneNode* cPivot6 = smgr->addCubeSceneNode(0.5,cPivot2,-1,vector3df(1.25,0.7,0.7));
cPivot6->setMaterialTexture(0,driver->getTexture("wall.bmp"));
cPivot6->setMaterialFlag(video::EMF_LIGHTING, false);
ISceneNode* cPivot7 = smgr->addCubeSceneNode(0.5,cPivot2,-1,vector3df(1.25,-0.7,0.7));
cPivot7->setMaterialTexture(0,driver->getTexture("wall.bmp"));
cPivot7->setMaterialFlag(video::EMF_LIGHTING, false);
ISceneNode* cPivot8 = smgr->addCubeSceneNode(0.5,cPivot2,-1,vector3df(-1.25,0.7,0.7));
cPivot8->setMaterialTexture(0,driver->getTexture("wall.bmp"));
cPivot8->setMaterialFlag(video::EMF_LIGHTING, false);
ISceneNode* cPivot9 = smgr->addCubeSceneNode(0.5,cPivot2,-1,vector3df(-1.25,-0.7,0.7));
cPivot9->setMaterialTexture(0,driver->getTexture("wall.bmp"));
cPivot9->setMaterialFlag(video::EMF_LIGHTING, false);
ISceneNode* cPivot10 = smgr->addCubeSceneNode(0.7,cPivot2,-1,vector3df(0,-0.6,-1.25));
cPivot10->setMaterialTexture(0,driver->getTexture("wall.bmp"));
cPivot10->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 += 360;
if(playerCompass >= 360) 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));
}
if(keys[KEY_KEY_S]){
// 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 += 360;
if(playerCompass >= 360) 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));
}
if(keys[KEY_KEY_D]){
// player movement vector
vector3df playerStep = sphericalXYZ(cameraOrbit,0,playerMoveSpeed);
playerX -= playerStep.X;
playerY -= playerStep.Y;
playerZ += playerStep.Z;
// player rotation brain torture
playerTurnTo = cameraOrbit;
if(playerTurnTo < 0) playerTurnTo += 360;
if(playerTurnTo >= 360) playerTurnTo -= 360;
if(playerCompass < 0) playerCompass += 360;
if(playerCompass >= 360) 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));
}
if(keys[KEY_KEY_A]){
// player movement vector
vector3df playerStep = sphericalXYZ(cameraOrbit,0,playerMoveSpeed);
playerX += playerStep.X;
playerY -= playerStep.Y;
playerZ -= playerStep.Z;
// player rotation brain torture
playerTurnTo = cameraOrbit - 180;
if(playerTurnTo < 0) playerTurnTo += 360;
if(playerTurnTo >= 360) playerTurnTo -= 360;
if(playerCompass < 0) playerCompass += 360;
if(playerCompass >= 360) 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;
}
I add rotation with W A S D but there are errors !!! it only works with W and S perfect but if you press A or D you move in that direction but the camera not! Anyone can help me ?
Help with nodes
Hello, first of all sorry for my english, and second thanks to all people that write in this forum, it has alot of really interesting information.
I have a problem with this very cool camera style... i hope someone can helpme.
I think that i have a good implementation but i have a hard problem.
This screenshot show original code in action:
Aparently only have two cubes directed by mouse position... but really have 3 cubes, the first is inside of the second Cpivot1, Cpivot2, Cpivot3 and this first no have rotation.
After implement camera code in my proyect im load a .b3d model and dam! here is the problem:
player_node2 its a parent of player_node, he runs perfect, like cubes in the example. but i need kill player_node, or hide... but if i set player_node like SetVisible(false) all childs have visibility off and camera lost position.
How can i hide player_node? or some tip for search. code up and code down i invert many ours and i cant find the solution.
Thanks for your attention and your time.
I have a problem with this very cool camera style... i hope someone can helpme.
I think that i have a good implementation but i have a hard problem.
This screenshot show original code in action:
Aparently only have two cubes directed by mouse position... but really have 3 cubes, the first is inside of the second Cpivot1, Cpivot2, Cpivot3 and this first no have rotation.
After implement camera code in my proyect im load a .b3d model and dam! here is the problem:
Code: Select all
player = smgr->getMesh("Modelos/Soldado/meshes/soldier_lod0.b3d");
if (!player) { device->drop(); }
player_node = smgr->addAnimatedMeshSceneNode(player, 0, -1, core::vector3df(playerX,playerY,playerZ));
player_node2 = smgr->addAnimatedMeshSceneNode(player, player_node, 1, core::vector3df(0,1,0));
myCamera = smgr->addCameraSceneNode(player_node, sphericalXYZ(cameraOrbit,cameraAngle,cameraDistance), player_node->getPosition());
// ...
if(keys[KEY_KEY_W]){
/// ...
player_node->setPosition(core::vector3df(playerX,playerY,playerZ));
player_node2->setRotation(core::vector3df(0,playerCompass,0));
}
How can i hide player_node? or some tip for search. code up and code down i invert many ours and i cant find the solution.
Thanks for your attention and your time.
Re: 3rd person camera #3,267 (C&C needed for newbie)
Hi, i rewrote the code myself too to get rid of the globals ( reminded me too much of DarkBasic, that is a no go for C++ )
Also i get a strange behaviour when moving the window, the app simply closes the window, dont know why.
I use 1.8 svn on LinuxMint x64 (Ubuntu), does anybody have the same issue?
have fun
Also i get a strange behaviour when moving the window, the app simply closes the window, dont know why.
I use 1.8 svn on LinuxMint x64 (Ubuntu), does anybody have the same issue?
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")
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CLASS : MyEventReceiver //////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class MyEventReceiver : public IEventReceiver
{
private:
IrrlichtDevice* Device;
public:
// 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;
f32 cameraAngle;
f32 cameraDistance;
f32 cameraOrbitOld;
f32 cameraAngleOld;
// player registry
f32 playerX;
f32 playerY;
f32 playerZ;
f32 playerCompass;
f32 playerTurnTo;
f32 playerTurnSpeed;
f32 playerMoveSpeed;
public:
/// constructor
MyEventReceiver( IrrlichtDevice* device )
: Device(device), mouseDownL(false), mouseDownM(false), mouseDownR(false), lastWheelMovement(0.f)
, cursor(0.f,0.f), cursorOld(0.f,0.f), cursorDelta(0.f,0.f), cameraOrbit(45.f), cameraAngle(0.f)
, cameraDistance(30.f), cameraOrbitOld(0.f), cameraAngleOld(0.f), playerX(0.f), playerY(0.f), playerZ(0.f)
, playerCompass(30.f), playerTurnTo(0.f), playerTurnSpeed(1.f), playerMoveSpeed(0.01f)
{
for(u32 i=0; i<KEY_KEY_CODES_COUNT; i++)
keys[i] = false;
if (Device)
Device->setEventReceiver( this );
}
/// destructor
virtual ~MyEventReceiver()
{
// empty
}
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
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()
{
IVideoDriver * driver = SceneManager->getVideoDriver();
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;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// MAIN /////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// /////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
// setup key engine objects
IrrlichtDevice* device = createDevice(EDT_OPENGL,dimension2d<u32>(800,600),24,false,false,false);
if (!device)
{
return -1;
}
// setup event receiver
MyEventReceiver rv(device);
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
ICursorControl* CursorControl = device->getCursorControl();
// 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(rv.playerX,rv.playerY,rv.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(rv.cameraOrbit,rv.cameraAngle,rv.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(rv.keys[KEY_ESCAPE])
{
device->closeDevice();
}
// player keys
if(rv.keys[KEY_KEY_W])
{
// player movement vector
vector3df playerStep = sphericalXYZ(rv.cameraOrbit,0.f,rv.playerMoveSpeed);
rv.playerX -= playerStep.X;
rv.playerY -= playerStep.Y;
rv.playerZ -= playerStep.Z;
// player rotation brain torture
rv.playerTurnTo = rv.cameraOrbit - 90.f;
if(rv.playerTurnTo < 0.f) rv.playerTurnTo += 360.f;
if(rv.playerTurnTo >= 360.f) rv.playerTurnTo -= 360.f;
if(rv.playerCompass < 0.f) rv.playerCompass = rv.playerCompass + 360.f;
if(rv.playerCompass >= 360.f) rv.playerCompass = rv.playerCompass - 360.f;
f32 playerTurnDir = 0.f;
f32 playerTurnDelta = 0.f;
if(rv.playerCompass > rv.playerTurnTo)
{
if(rv.playerCompass - rv.playerTurnTo < 180.f)
{
playerTurnDir = -1.f;
playerTurnDelta = rv.playerCompass - rv.playerTurnTo;
}
else
{
playerTurnDir = 1.f;
playerTurnDelta = (360.f - rv.playerCompass) + rv.playerTurnTo;
}
}
if(rv.playerCompass < rv.playerTurnTo)
{
if(rv.playerTurnTo - rv.playerCompass < 180.f)
{
playerTurnDir = 1;
playerTurnDelta = rv.playerTurnTo - rv.playerCompass;
}
else
{
playerTurnDir = -1;
playerTurnDelta = (360.f - rv.playerTurnTo) + rv.playerCompass;
}
}
f32 playerTurnAmount;
if(playerTurnDelta < rv.playerTurnSpeed)
{
playerTurnAmount = playerTurnDelta;
}
else
{
playerTurnAmount = rv.playerTurnSpeed;
}
rv.playerCompass += (playerTurnAmount * playerTurnDir);
cPivot1->setPosition(vector3df(rv.playerX,rv.playerY,rv.playerZ));
cPivot2->setRotation(vector3df(0,rv.playerCompass,0));
myCamera->setTarget(vector3df(rv.playerX,rv.playerY,rv.playerZ));
}
// orient camera
myCamera->setPosition(sphericalXYZ(rv.cameraOrbit,rv.cameraAngle,rv.cameraDistance));
// debug display
stringw txt(L"FPS : ");
txt += driver->getFPS();
txt += L"\n";
txt += L"left mouse button : ";
txt += rv.mouseDownL;
txt += L"\n";
txt += L"middle mouse button : ";
txt += rv.mouseDownM;
txt += L"\n";
txt += L"right mouse button : ";
txt += rv.mouseDownR;
txt += L"\n";
txt += L"last wheel movement : ";
txt += rv.lastWheelMovement;
txt += L"\n";
txt += L"cursor x : ";
txt += rv.cursor.X;
txt += L"\n";
txt += L"cursor y : ";
txt += rv.cursor.Y;
txt += L"\n";
txt += L"cursorOld x : ";
txt += rv.cursorOld.X;
txt += L"\n";
txt += L"cursorOld y : ";
txt += rv.cursorOld.Y;
txt += L"\n";
txt += L"cursorDelta x : ";
txt += rv.cursorDelta.X;
txt += L"\n";
txt += L"cursorDelta y : ";
txt += rv.cursorDelta.Y;
txt += L"\n";
txt += L"camera orbit : ";
txt += rv.cameraOrbit;
txt += L"\n";
txt += L"camera angle : ";
txt += rv.cameraAngle;
txt += L"\n";
txt += L"player compass : ";
txt += rv.playerCompass;
txt += L"\n";
txt += L"player turn to : ";
txt += rv.playerTurnTo;
txt += L"\n";
debug_panel->setText( txt.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;
}
Re: 3rd person camera #3,267 (C&C needed for newbie)
hello, my complier is vc10, program window run fine when move... i don't know...
to show better the problem that i have:
if you change scale "0.5" to for example "2"... main cube cpivot1 no rotate.
do you know how i can make rotate it or hide...
thanks for your reply
to show better the problem that i have:
Code: Select all
// setup the "player"
ISceneNode* cPivot1 = smgr->addCubeSceneNode(0.5,0,-1,vector3df(rv.playerX,rv.playerY,rv.playerZ));
Code: Select all
ISceneNode* cPivot1 = smgr->addCubeSceneNode(2.0,0,-1,vector3df(rv.playerX,rv.playerY,rv.playerZ));
thanks for your reply
Re: 3rd person camera #3,267 (C&C needed for newbie)
solved, i was offuscated... smgr->addEmptySceneNode(); ftw!!!