NWN style camera

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
NightBird
Posts: 12
Joined: Tue May 25, 2004 6:47 pm

NWN style camera

Post by NightBird »

Ok, I've been asking so many questions, I figure it's time to donate something back to the community. I've made a Never Winter Nights style camera(where you move the mouse to the edge of the screen for it to rotate around an object, and if you scroll the middle mouse button, it will zoom in and out. There is also if you hold the middle mouse button, it's a free roam around the object, but I haven't put that in yet. I'll probably post that when I'm done with that as well.)

Here is the code, which I hope is fairly clear.
class cFollowCamera: public IEventReceiver
{
public:
ISceneNode *Target() {
return m_target;
}
void Target(ISceneNode *value) {
m_target = value;
m_lastTargetPos = value->getPosition();
m_target->grab();
}
void Update() {
if (!m_Cam || !m_target) return;
if (MouseX <= cData::Get().Width()*.05f) {
m_updated = true;
m_yRotationAngle += cData::Get().CameraSpeed();
while (m_yRotationAngle > 2*PI)
m_yRotationAngle -= 2*PI;
}
else if (MouseX >= cData::Get().Width()*.95f) {
m_updated = true;
m_yRotationAngle -= cData::Get().CameraSpeed();
while (m_yRotationAngle < 2*PI)
m_yRotationAngle += 2*PI;
}

if (m_lastTargetPos != m_target->getPosition()) {
m_updated = true;
m_lastTargetPos = m_target->getPosition();
}
if (m_updated) {
m_updated = false;
vector3df m_Camerapos = m_lastTargetPos;
m_Camerapos.X += distance*sin(m_yRotationAngle);
m_Camerapos.Z += distance*cos(m_yRotationAngle);
m_Camerapos.Y += distance;
m_Cam->setPosition(m_Camerapos);
m_Cam->setTarget(m_lastTargetPos);
}
}

void Zoom(float amount) {
distance *= amount;
if (distance == 0) distance = 2; //there should be more elaborate capping of things here..
m_updated = true;
}
bool OnEvent(SEvent event) {
if (event.EventType == EET_MOUSE_INPUT_EVENT) {
switch (event.MouseInput.Event) {
case EMIE_MOUSE_WHEEL:
Zoom(((-event.MouseInput.Wheel)+1)/2+.5f); //make it be from .5 to 1.5
return true;
break;
case EMIE_MOUSE_MOVED:
MouseX = event.MouseInput.X;
return true;
break;
}
}
return false;
}

cFollowCamera(ISceneNode *target) {
Target(target);
m_Cam = cData::Get().Device().getSceneManager()->addCameraSceneNode(0,m_lastTargetPos + vector3df(0,20,20),m_lastTargetPos);
m_yRotationAngle = 0.0f;
distance = 20;
}
~cFollowCamera(void) {
m_target->drop();
}
private:
ISceneNode* m_target;
ICameraSceneNode* m_Cam;

vector3df m_lastTargetPos;

bool m_updated;
int MouseX;
float distance;

float m_yRotationAngle; //the angle about the Y axis
};
some stuff for you to know. the cData class is a singleton accessed through the get function, and that stores most of the global data, like the device, resolution of the screen, and a few other things. You could modify the code so that you can get to them from elsewhere (cData::Get().Device() returns a refrence to the current device, while cData::Get().CameraSpeed() returns .01f as of right now.) The zooming system could probably do with a bit of an improvement(mainly, it's too fast zooming at closer levels, but slower at higher levels)

If you have any questions about the code, feel free to ask me. :D

Edit: I inverted the Wheel input, so that moving the wheel forward will zoom you in instead of out. oh, and I removed the random end quote thing at the end.
nitroman

Post by nitroman »

interesting! :D
NightBird
Posts: 12
Joined: Tue May 25, 2004 6:47 pm

Post by NightBird »

I was looking over what I posted, and I noticed I didn't put in any instructions for useing it in personal code. so I thought I would post instructions. woo

Ok, so you create a new camera passing to the constructor the Target ISceneNode. in the event manager for your system you will call the cameras OnEvent function, or if you arn't using a personal event manager, you can set the camera as it's own event manager, whatever.

Then, once a frame, you will need to have the camera update itself, which you do by calling it's update function. Then you just have to delete the camera when you are done.

Oh, a bit of an update to the code(I'll probably zip up what I have and put it up somewhere), in the Target function, m_updated needs to be set to true, because otherwise, the update function won't try to view the new target until it's moved, or the camera is to be rotated around the target. it also will just jump to the new target.

Oh, bother. I realised another potential problem with switching targets.

if you target something, you grab it, but you don't let anything you had go, so I added
if (m_target) m_target->drop();
to the Target function, and in the constructor, I had m_target be set to NULL
MasterGod
Posts: 2061
Joined: Fri May 25, 2007 8:06 pm
Location: Israel
Contact:

Post by MasterGod »

So is it finished, ready for use?
Image
Dev State: Abandoned (For now..)
Requirements Analysis Doc: ~87%
UML: ~0.5%
mcbart
Posts: 19
Joined: Thu Aug 07, 2008 11:36 am

Post by mcbart »

Can you write an example where you show how to use it? I was compiling program with use this code but while compiling i had many errors.
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

You may want to go back in time 4 years if you want an answer to that question.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
MarcinS
Posts: 25
Joined: Tue Feb 17, 2009 3:14 pm
Location: Poland

Post by MarcinS »

Hi to Everyone (As you can see i am new here) :)

If mcbart or anyone still need it i can post working "more or less" (cleaning still in progres) :) version of this code packed in to object c++.
Post Reply