Aktuelle Zeit: 07.01.2025, 03:45

Alle Zeiten sind UTC + 1 Stunde




Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Autor Nachricht
BeitragVerfasst: 19.12.2009, 16:20 
Offline

Registriert: 27.11.2009, 15:40
Beiträge: 5
Hiho Leute,
ich bin im moment langsam auf dem Weg mein erstes Projekt anzugehen. Allerdings bin ich noch recht Blöd was das Programmieren und Rechnen im 3 Dimensionalen Raum angeht.
Zur einfachheit wollte ich nun zuerst eine Kamera Programmieren die sich um ein Objekt herumbewegt.
Die Steuerung soll per Maus erfolgen und die Entfernung zwischen Kamera und Objekt sollte variabel sein. (zb. per Mausrad)

Die Kamera sollte sich also Quasi auf einer Kugel/Spähre um das Objekt herumbewegen und immer auf das Objekt ausgerichtet sein.

Meine fragen sind eher Mathematisch. Darin bin ich leider nicht so helle.
Ich fänds hilfreich und nett wenn mir jemand erklären könnte wie ich die Bewegung der Kamera berechnen kann. Ohne mich auf externe sachen zu verlinken (wikipedia usw.) also wirklich genau sagen warum ich wo welche Formel ansetze. Denn aus Mathebüchern etc. werd ich einfach nicht schlau.


Nach oben
 Profil  
 
BeitragVerfasst: 20.12.2009, 10:34 
Offline
Benutzeravatar

Registriert: 16.10.2007, 07:56
Beiträge: 229
Wohnort: Regensburg
Hallo,

ich hab den Code unten in meinem aktuellen Projekt "Marbles2". Es wäre auch möglich, die Kamera einfach als Child des Objekts, um das es sich bewegen soll, zu definieren, aber in meinem Fall ist das schlecht, das Objekt ist eine Kugel und die dreht sich sehr schnell, und wenn die Kamera Child ist dann dreht sie sich mit, also ist Die bei mir unabhängig.

Code:
  f32 fDist=5.0f; //Entfernung der Kamera zum Objekt

  //die Position der Kamera relativ zum Objekt
  //m_fAngleH: horizontaler Winkel
  //m_fAngleV: vertikaler Winkel
  f32 fCamX=(irr::f32)(fDist*sin(m_fAngleH*GRAD_PI2)*cos(m_fAngleV*GRAD_PI2)),
      fCamY=(irr::f32)(fDist*sin(m_fAngleV*GRAD_PI2)),
      fCamZ=(irr::f32)(fDist*cos(m_fAngleH*GRAD_PI2)*cos(m_fAngleV*GRAD_PI2));

  //die Kameraposition in World-Koordinaten
  m_vCamPos=m_pBody->getPosition()+vector3df(fCamX,fCamY,fCamZ);
  m_pNode->setPosition(m_vCamPos);
  m_pNode->setTarget(m_pBody->getPosition());

_________________
Bild


Nach oben
 Profil  
 
BeitragVerfasst: 21.01.2010, 12:36 
Offline

Registriert: 27.11.2009, 15:40
Beiträge: 5
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!


Nach oben
 Profil  
 
BeitragVerfasst: 21.01.2010, 15:07 
Offline
Benutzeravatar

Registriert: 16.10.2007, 07:56
Beiträge: 229
Wohnort: Regensburg
OK, mit der Erklärung kann sogar ich was anfangen (nicht die aus Wikipedia ... die von dir). Da ich nicht gerade gut in Mathe bin hab ich den Code im Netz gesucht, gefunden und benutzt. Mir persönlich ist es auch nicht besonders wichtig, zu verstehen, was dahinter steckt, ich will nur funktionierenden Code ;).

Vielleicht solltest du aus deinem Code einen Animator machen, damit kannst du einiges bei der Benutzung vereinfachen (imho).

Was ich bei meiner Erklärung gemeint hab ich recht einfach: wenn du die Kamera als Child des Objektes festlegst, dem sie folgen soll, dann wird die Position auch mitrotiert. Im Falle meines Projekts ist das Objekt, dem die Kamera folgen soll, eine Kugel, die über eine Rennstrecke rollt. Deswegen dreht sich die Kugel recht schnell, und wenn die Kamera immer in der selben relativen Position (Drehung inbegriffen) bleibt, dann ändert sich die Position sehr schnell, deswegen hab ich die Kamera frei gemacht, hat also keinen Parent.

P.S.: schau die mein Spielchen einfach mal an ... auf die Kamera bin ich besonders stolz. Die folgt der Kugel, ab einer gewissen Geschwindigkeit ist die Blickrichtung auch die Bewegungsrichtung, die Kamera dreht dabei aber immer schön weich hinterher. Natürlich gibt es auch einen "Free Cam" Modus, bei dem man die Kamera beliebig um die Kugel drehen kann (wenn man aber 2 Sekunden nicht mehr dreht beginnt die Kamera wieder, sich in Bewegungsrichtung auszurichten). Hat einiges an Zeit gekostet, bis es so schön funktioniert hat.

_________________
Bild


Nach oben
 Profil  
 
BeitragVerfasst: 21.01.2010, 15:51 
Offline
Benutzeravatar

Registriert: 16.10.2007, 07:56
Beiträge: 229
Wohnort: Regensburg
War gerade im englischen Forum, und da hab ich eine andere Methode gesehen, die einem die ganzen Untiefen der Mathematik erspart:

- füge zu dem Objekt, um das die Kamera rotieren soll, einen EmptySceneNode als Child hinzu (position (0,0,0))
- füge die Kamera als Child dieses EmptySceneNodes hinzu (position z.B. (10,0,0))
- jetzt einfach den EmptySceneNode rotieren und die Kamera rotiert im Abstand von 10 Einheiten um das Objekt, dem gefolgt werden soll.

Das ist eine schöne Methode. Würde mir bei meinem Spiel aber nichts bringen, denn das Child-Objekt rotiert ja zusammen mit dem Parent. Ich müsste also die Position trotzdem bei jeder Bewegung per "Hand" updaten, und da meine Kamera automatisch in Bewegungsrichtung schwenken soll müsste ich dafür auch noch in die Rotation des EmptySceneNodes eingreifen. Für 3rd Person Cameras, die z.B. für Rollenspiele oder ähnliches gedacht sind, sollte diese Methode aber gut (und einfach) funktionieren.

_________________
Bild


Nach oben
 Profil  
 
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 16 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de