Ersteinmal Danke Brainsaw, obwohl ich deine Erklärung leider nicht auf anhieb begriffen hatte war das die Lösung die ich gesucht habe.
Da ich mich erst in C++ und 3D-Mathe Berechnungen einarbeiten muss und es vielleicht andere Personen gibt die das gleiche durchmachen möchte ich hier eben eine art 3D Rpg-Kamera Tutorial zusammenbauen.
Bisher bin ich soweit das ich die Sphären/Kugelkamera erfolgreich eingebaut habe und es auch geschafft habe mit der Maussteuerung gleichzeitig die Figur zu drehen. ( je nach vorhaben kann das ja nützlich sein)
Also mein Amateur 3rd Person Kamera Tutorial:
Kümmern wir uns erst einmal um die Theorie. Wie funktioniert und verhält sich eine 3rd Person Kamera?
Im grunde haben wir ein Objekt ( camera ) das in einem bestimmten Abstand (camera_distance) um ein anderes Objekt ( player ) kreist.
Dabei bewegen wir die Kamera mit der Maus ( cursor ) um den Spieler herum.
Da die Kameraposition ( cameraPos ) in diesem Fall immer von der Spielerposition ( playerPos ) abhängig ist, ist diese unser Ursprung.
Um der Kamera nun zb. zu sagen das sie bei einer Mausbewegung nach links oder rechts (Maus X-Achse = cursorPos.X ) mit dem Abstand 200 um den Spieler Kreisen soll brauchen wir eine Berechnung für den 3D Raum.
In diesem Fall ist das Polarkoordinaten-System sehr hilfreich.
Ausführliche Informationen dazu findet ihr in der Wikipedia:
http://de.wikipedia.org/wiki/Polarkoordinaten (Allgemein)
http://de.wikipedia.org/wiki/Kugelkoordinaten (Speziell für unseren Fall)
Im grunde ist die Berechnung ganz simpel wir bestimmen unsere Kameraposition immer anhand von 2 Winkeln.
Der erste Winkel ist der Azimutwinkel. Er bestimmt die Position unserer Kamera auf der X und Z achse. Also lediglich wo die Kamera aufliegt. ( Ohne zu wissen wie hoch im Raum sie steht)
Der Azimutwinkel kann zwischen 0°-360° betragen wird jedoch mit 0-2*Pi angegeben.
Der zweite Wiknkel lautet Polarwinkel. Er bestimmt die Position unserer Kamera zwischen der X/Z und der Y Achse. Sprich er bestimmt den Winkel vom Boden aus in die Höhe.
Der Polarwinkel kann zwischen 0°-180° betagen und wird mit 0-Pi angegeben.
Die Formel zur Berechnung der relativen Kamera Position vom Spieler lautet:
Code:
cameraPos.X = camera_distance * sin(polar_winkel) * cos(azimut_winkel);
cameraPos.Y = camera_distance * cos(polar_winkel);
cameraPos.Z = camera_distance * sin(polar_winkel) * sin(azimut_winkel);
Damit sollte alles für uns, in diesem Fall, notwendige gegeben sein.
Dann also zum vollständigen Code:
Code:
#include <irrlicht.h>
#include <iostream>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
int main()
{
video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;
printf( "Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Burning's Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");
char i;
std::cin >> i;
switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 0;
}
IrrlichtDevice* device = createDevice(driverType,core::dimension2d<u32>(640, 480), 16, false, false, false);
if (device == 0)
return 1;
device->setWindowCaption(L"Hello World! - Irrlicht 3rd Person Camera Demo");
device->getFileSystem()->addZipFileArchive("C:/irrlicht/media/map-20kdm2.pk3");
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();
IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp");
ISceneNode* node = 0;
if (mesh)
node = smgr->addOctTreeSceneNode(mesh->getMesh(0), 0, -1, 1024);
if (node)
node->setPosition(core::vector3df(-1300,-144,-1249));
ISceneNode* player = smgr->addAnimatedMeshSceneNode(smgr->getMesh("C:/irrlicht/media/faerie.md2"));
if (!player)
{
device->drop();
return 1;
}
if (player)
{
player->setMaterialFlag(EMF_LIGHTING, false);
player->setMaterialTexture( 0, driver->getTexture("C:/irrlicht/media/sydney.bmp") );
player->setPosition(vector3df(100,-55,100));
}
ICameraSceneNode* camera = smgr->addCameraSceneNode();
ICursorControl *cursor = device->getCursorControl();
cursor->setVisible(false);
vector3df playerPos;
vector3df cameraPos;
float camera_distance = 200;
float azimut_winkel = PI;
float polar_winkel = PI/3;
float cursor_x;
float cursor_y;
int camera_speed = 5;
cameraPos.X = camera_distance * sin(polar_winkel) * cos(azimut_winkel);
cameraPos.Y = camera_distance * cos(polar_winkel);
cameraPos.Z = camera_distance * sin(polar_winkel) * sin(azimut_winkel);
camera->setPosition(player->getPosition()+cameraPos);
position2d<irr::f32> cursorPos;
cursorPos.X = 0.5f;
cursorPos.Y = 0.5f;
const position2d<irr::f32> cursorPosBack = cursorPos ;
int lastFPS = -1;
u32 then = device->getTimer()->getTime();
while(device->run())
{
const u32 now = device->getTimer()->getTime();
then = now;
cursorPos = cursor->getRelativePosition();
cameraPos = camera->getPosition();
playerPos = player->getPosition();
cursor_x = cursorPos.X-0.5f;
cursor_y = cursorPos.Y-0.5f;
azimut_winkel += (cursor_x*camera_speed);
if (azimut_winkel > (2*PI))
azimut_winkel -= (2*PI);
if (azimut_winkel < 0)
azimut_winkel += (2*PI);
polar_winkel -=(cursor_y*camera_speed);
if ( polar_winkel < 0 || polar_winkel > PI )
polar_winkel +=(cursor_y*camera_speed);
cameraPos.X = camera_distance * sin(polar_winkel) * cos(azimut_winkel);
cameraPos.Y = camera_distance * cos(polar_winkel);
cameraPos.Z = camera_distance * sin(polar_winkel) * sin(azimut_winkel);
player->setPosition(playerPos);
camera->setPosition(playerPos+cameraPos);
camera->setTarget(player->getPosition());
cursor->setPosition(cursorPosBack);
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
int fps = driver->getFPS();
if (lastFPS != fps)
{
stringw tmp(L"Movement Example - Irrlicht Engine [");
tmp += driver->getName();
tmp += L"] fps: ";
tmp += fps;
device->setWindowCaption(tmp.c_str());
lastFPS = fps;
}
}
device->drop();
return 0;
}
Vielleicht kann ja jemand was damit anfangen. Und zumindest auch _verstehen_ wie die Kameraposition berechnet wird.
Anbei hätte ich auch gleich eine frage: Wie kann ich die Animationen der Figur stoppen damit sie nur ruhig dasteht?
Danke nochmal an Brainsaw!