Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

10.08.2008, 16:56

Irrlicht Kollision mit anderen meshes

Hi,

keine ahnung ob mir hier überhaupt jemand helfen kann, aber habe hier im forum schon von manchen leuten mal gelesen,dass sie auch die irrlicht engine für ihre 3d spiele benutzen.

hab mir jetzt diese woche (wenn ich mal zeit hatte:D) ein bischen in die ersten tutorials eingearbeitet und fand es bis jetzt nicht sonderlich kompliziert, die engine anzuwenden (habe auch theorie von den grundlagen der directx programmierung [das buch von david] und opengl programmierung [uni grafikprogrammierung]), aber folgendes problem:

Wenn ich mit irrlicht eine 3d welt lade (bei den tutorials ist das eine quake3map) und dann andere meshes und die dazugehörigen scenenodes erstelle (ich hab mich selbst, also den spieler als kamera mit kollision und eine fee hingestellt), wie schaffe ich es, dass ich nicht nur mit der 3d welt kollidiere, sondern auch mit anderen meshes (bei mir z.b. die fee).

Ich habe es schon probiert mit einem TriangleSelector für die fee zu erstellen und eine collision für sie zu erstellen (wie bei der kamera), aber egal, wie ich da herumschraube und herumprobiere, ich krigs nicht hin :(
dass die fee ne kollision mit der welt besitzt, das habe ich schon herausgefunden, weil ich so von oben auf ein eck herabfallen hab lassen (mit gravitation) und sie am eck hängen bleibt, also kollidiert sie mit der quake3 map.


vl hat das wer von euch schon rausgefunden, wie es funktioniert, das wäre natürlich toll.

hier kurz mein jetziger code

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// ...

mesh2 = smgr->getMesh( "20kdm2.bsp" );
        // start the collisiondetector by adding an octtree

        if( mesh2 )
            node2 = smgr->addOctTreeSceneNode( mesh2->getMesh(0) );
        if( node2 )
        {
            node2->setPosition( irr::core::vector3df( -1300, -144, -1249 ) );
            selector = smgr->createOctTreeTriangleSelector( mesh2->getMesh(0), node2, 128 );
            node2->setTriangleSelector( selector );
            selector->drop();
        }

        // add faerie

        irr::video::SMaterial material;
        material.setTexture( 0, driver->getTexture( "faerie2.bmp" ) );
        material.Lighting = true;
        irr::scene::IAnimatedMeshSceneNode *n2 = NULL;
        irr::scene::IAnimatedMesh *faerie = smgr->getMesh( "faerie.md2" );
        if( faerie )
        {           
            n2 = smgr->addAnimatedMeshSceneNode( faerie );
            n2->setPosition( irr::core::vector3df(-90,500,-150) );
            // n2->setMD2Animation( irr::scene::EMAT_SALUTE );

            n2->setFrameLoop( 160, 168 );
            n2->setAnimationSpeed( 30 );
            n2->getMaterial(0) = material;
            
            irr::scene::ISceneNodeAnimator *a2 = smgr->createFlyStraightAnimator( irr::core::vector3df(-130,100,-150),
                irr::core::vector3df(250,100,-150),2500,true);
            irr::scene::ISceneNodeAnimator *coll2 = smgr->createCollisionResponseAnimator( selector, n2, irr::core::vector3df(100,100,100),
                irr::core::vector3df(0,-1,0), irr::core::vector3df(0,50,0) );
            // n2->setScale( irr::core::vector3df(2,2,2) );

            n2->addAnimator( coll2 );
            coll2->drop();
            // n2->addAnimator(a2);

            a2->drop();
        }
        material.Lighting = false;

        // set the collsiion ellipsoid - the camera

        irr::scene::ICameraSceneNode *camera = smgr->addCameraSceneNodeFPS( 0, 100, 250 );
        camera->setPosition( irr::core::vector3df( -90, 150, -150 ) );
        irr::scene::ISceneNodeAnimator *a = smgr->createCollisionResponseAnimator( selector, camera, irr::core::vector3df(30,50,30),
            irr::core::vector3df( 0,0,0 ), irr::core::vector3df(0,50,0) );
        camera->addAnimator( a );
        a->drop();
        device->getCursorControl()->setVisible( false );

// ...

2

11.08.2008, 21:04

falls es was weiterhilft, ich habs jetzt so hinbekommen, dass die fee auch irgendwie ne eigene kollsiion hat, nur wenn ich mich ihr nähere, bleib ich in ihr stecken.

das muss irgendwas komisches mit den TriangleSelectoren sein.

es wundert mich nämlich, dass man oben bei der q3 map, den selector sofort "dropped" aber unten, bei der camera verwendet man ihn als übergabeparameter, was ja iwie sinnlos zu schein seint (ist es aber nicht laut den tests).

hier der jetzige code, wieder bischen herumprobiert :(

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Variables

    MyEventReceiver receiver;
    device = irr::createDevice( irr::video::EDT_DIRECT3D9, irr::core::dimension2d<irr::s32>( 640, 480 ),
                                32, false, false, false, &receiver );
    irr::video::IVideoDriver *driver = NULL;
    irr::scene::ISceneManager *smgr = NULL;
    irr::gui::IGUIEnvironment *guienv = NULL;
    irr::scene::IAnimatedMesh *mesh = NULL;
    irr::scene::IAnimatedMeshSceneNode *node = NULL;
    irr::scene::IAnimatedMesh *mesh2 = NULL;
    irr::scene::ISceneNode *node2 = NULL;
    irr::scene::ITriangleSelector *selector = NULL;
    irr::scene::ITriangleSelector *selector2 = NULL;



// ...




/* **************************************************************
         * !!! KOLLISIONSPART START - HIER MUSS ETWAS GEÄNDERT WERDEN !!!
         * *************************************************************/


        if( mesh2 )
            node2 = smgr->addOctTreeSceneNode( mesh2->getMesh(0) );
        if( node2 )
        {
            node2->setPosition( irr::core::vector3df( -1300, -144, -1249 ) );
            selector = smgr->createOctTreeTriangleSelector( mesh2->getMesh(0), node2, 128 );
            node2->setTriangleSelector( selector );
            selector->drop();
        }

        // testface laden

        irr::scene::IAnimatedMesh *face = smgr->getMesh( "face.x" );
        irr::scene::ISceneNode *facenode = smgr->addAnimatedMeshSceneNode( face );
        facenode->setMaterialFlag( irr::video::EMF_LIGHTING, false );
        facenode->setPosition( irr::core::vector3df( -90, 150, -150 ) );
        facenode->setRotation( irr::core::vector3df( 0, 0, 180 ) );
        facenode->setRotation( irr::core::vector3df( 90, 0, 0 ) );
        facenode->setScale( irr::core::vector3df( 3, 3, 3 ) );

        // add faerie

        irr::video::SMaterial material;
        material.setTexture( 0, driver->getTexture( "faerie2.bmp" ) );
        material.Lighting = true;
        irr::scene::IAnimatedMeshSceneNode *n2 = NULL;
        irr::scene::IAnimatedMesh *faerie = smgr->getMesh( "faerie.md2" );
        if( faerie )
        {           
            n2 = smgr->addAnimatedMeshSceneNode( faerie );
            n2->setPosition( irr::core::vector3df(0,300,-250) );
            n2->setFrameLoop( 1, 250 );
            n2->setAnimationSpeed( 30 );
            n2->getMaterial(0) = material;
            
            selector2 = smgr->createOctTreeTriangleSelector( faerie, n2, 128 );
            n2->setTriangleSelector( selector2 );
            selector2->drop();
            irr::scene::ISceneNodeAnimator *a2 = smgr->createFlyStraightAnimator( irr::core::vector3df(-130,100,-150),
                irr::core::vector3df(250,100,-150),2500,true);
            irr::scene::ISceneNodeAnimator *coll2 = smgr->createCollisionResponseAnimator( selector, n2, irr::core::vector3df(30,50,30),
                irr::core::vector3df(0,-3,0), irr::core::vector3df(0,25,0) );
            // n2->setScale( irr::core::vector3df(2,2,2) );

            n2->addAnimator( coll2 );
            coll2->drop();
            // n2->addAnimator(a2);

            a2->drop();
        }
        material.Lighting = false;

        // set the collsiion ellipsoid - the camera

        irr::scene::ICameraSceneNode *camera = smgr->addCameraSceneNodeFPS( 0, 100, 250 );
        camera->setPosition( irr::core::vector3df( 25, 0, 30 ) );
        irr::scene::ISceneNodeAnimator *a = smgr->createCollisionResponseAnimator( selector, camera, irr::core::vector3df(30,50,30),
            irr::core::vector3df( 0,-3,0 ), irr::core::vector3df(0,50,0) );
        irr::scene::ISceneNodeAnimator *a2 = smgr->createCollisionResponseAnimator( selector2, camera, irr::core::vector3df(30,50,30),
            irr::core::vector3df( 0,0,0 ), irr::core::vector3df(0,50,0) );
        camera->addAnimator( a );
        camera->addAnimator( a2 );
        a->drop();
        device->getCursorControl()->setVisible( false );


        /* *************************************************************
         * !!! KOLLISIONSPART ENDE - HIER MUSS ETWAS GEÄNDERT WERDEN !!!
         * ************************************************************/



// ...

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

3

12.08.2008, 08:01

Drop nicht gleich delete. setTriangleSelector grabbed sich den Selektor. Nutz mal für die Fee keinen OctTree sondern createTriangleSelectorFromBoundingBox. Damit dürftest du dann nicht mehr hängen bleiben. Und wie du schon herausgefunden hast, muss man glaube ich für Objekten, die kollidieren können ein createCollisionResponseAnimator. Sprich jeweils einmal pro Pärchen.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

4

12.08.2008, 22:38

thx, geht jetzt schon besser, aber man kann trotzdem noch teils durch die fee durchlaufen.

hab aber bischen im irrlicht forum gelesen, da haben mehrere das problem gepostet, weil das tutorial eben zu wenig erklärt.

wird anscheinend ab irrlicht 1.5 erklärt oder so, aber ich werd im forum schon irgendwas finden.

sonst muss ich es halt selbst umsetzen (wüsste ja aus der mathematik, wie man die distanz zwischen 2 3d objekten bestimmt), was dann aber sicherlich nicht performant sein wird^^

danke trotzdem, besser als nichts :)


edit: hier mein ansatz

C-/C++-Quelltext

1
2
3
4
5
6
bool collision(ISceneNode* one, ISceneNode* two, int DistanceMinimum ) { 
   if(one->getAbsolutePosition().getDistanceFrom(two->getAbsolutePosition()) < DistanceMinimum ) 
    return true; 

   return false; 
}


ist sicherlich nicht exakt, aber dürfte genügen.

je nachdem, was man jetzt mit der kollision machen will (z.b. bei kollision mit einer falle stirbt man, oder bei kollision mit einem händler wird man auf die minimumdistanz zurückgedrückt (das ist das, was man wohl häufiger braucht? ), würde das dann so aussehen im code

C-/C++-Quelltext

1
2
3
4
5
6
7
8
if( collision( node1, node2, range )
{
  vector3df position = node1->getAbsolutePositition(); 
  float angle = AngleBetweenPoints( position, node2->getAbsolutePosition() );
   position.X = position.X + range * Cos( angle )
   position.Z = position.Z + range * Sin( angle ) // bin mir nicht mehr sicher, wie es mit Z ging, das jetzige wäre für Y (Punkt auf Kreis rotieren lassen)

  node1->setPosition( position )
}


werds am abend mal probieren :)

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

5

13.08.2008, 08:38

Wie du den Winkel zwischen zwei Punkten bestimmst, will ich sehen :lol: . Außerdem kann man über das Skalarprodukt (Winkel zwischen 2 Vektoren) nur eine Aussage über den kleinstmöglichen Winkel machen. Sprich bei 2D fällt es schon schwerer zu entscheiden, ob sich ein Objekt "nach links oder nach rechts" ausgerichtet ist.
Wenn du einfach nur zurückgesetzt werden willst geht das über die direkte Verbindung zwischen den beiden Punkten, diese normalisiert und dann mal der Distanz. Oder einfacher:
neu_Punkt1 := alt_Punkt2 + (alt_Punkt1 - alt_Punkt2).normalisiert * Minimumdistanz
(ob stimmt kann ich dir nicht garantieren, da ich atm ein wenig gehandikapt bin)
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

6

13.08.2008, 19:29

kann sein,dass ich mich irre, aber im warcraft3 editor verwende ich immer folgende berechnung um den winkel zwischen 2 locations (koordianten sozusagen) zu krigen:


function AngleBetweenPoints takes location locA, location locB returns real
return bj_RADTODEG * Atan2(GetLocationY(locB) - GetLocationY(locA), GetLocationX(locB) - GetLocationX(locA))
endfunction


locA ist dabei der startpunkt und locB der endpunkt, also zu dem punkt, zu dem man den winkel haben will.
zurückgegeben wird der winkel in grad (wenn man bj_RADTODEG weglässt eben in radiant) zwischen den 2 punkten.

warum sollte das nicht so funktionieren? ich brauch doch keine orientierung um den winkel zwischen 2 punkten zu krigen?

ich probiers als (stur wie ich bin:D) zuerst mit meiner idee, danach mit deiner.

mfg ;)


edit:

ah ich glaub, warum du glaubst, dass es nicht geht.

also den vector3df hätt ich jetzt in eine 2d koordinate aufgespaltet (x, z im 3d raum) und die y koordinate als höhe sozusagen extra verglichen, also ob die beiden objekte annähernd auf derselben höhe sind (-> kollision) oder, wenn z.b. ein kühlschrank eine etage im haus ober mir ist dann ist unsere höhe zu sehr verschieden somit (-> keine kollision) somit kann auf die kollisionsberechnung verzichtet werden.

7

13.08.2008, 19:33

Zwischen zwei Punkten gibt es meines Wissens nach doch nur eine Linie und ein Winkel besteht normalerweise aus zwei.

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

8

13.08.2008, 21:08

:lol: Deine "Winkelfunktion" rechnet anscheinend folgendes:

dir = LocB - LocA
Winkel = arctan(dir.y / dir.x)

Somit rechnet diese Funktion, wenn ich sie richtig verstehe, schon einen Winkel zwischen zwei Punkten aus, allerdings relativ zum Nullpunkt. Sprich das ganze funktioniert nur im Bezug auf den NullPunkt UND für 2D. Außerdem kann diese Funktion wahrscheinlich folgende zwei Koordinatensätze nicht unterscheiden:
(x,y),(-x,-y)
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

9

14.08.2008, 07:00

dass es 2d ist, wusste ich bereits und hab deswegen das oben mit der höhe noch geschrieben.

aber kannst du mir erklären wo das problem ist? ich verstehs iwie ned ganz^^

die funktion liefert mir (egal in welchem quadranten des 2D systems ich bin), den richtigen winkel zwischen 0 und 360 grad zwischen 2 punkten. das ist doch das, was ich haben will? und ob der winkel im bezug zum ursprung ist, ist doch trotzdem nebensächlich?
wo liegt denn nun also das problem?

nochmal zusammengefasst:
ich vereinfache die 3D koordinaten auf 2D indem ich die Höhe (Y Koordinate) weglasse.
dann überprüfe ich zuerst, ob objekte ungefähr in der gleichen höhe liegen mit Hilfe der Y Koordinate:
-wenn ja, dann berechne ich den winkel zwischen den 2 objekten mit ihrer X und Z Koordinate und verschiebe Objekt1 von Objekt2 weg
- wenn nein, tue nichts


edit: btw ist das nicht MEINE winkelfunktion, sondern die gibt es ganz normal^^ schau mal auf wikipedia oder im google. Findet zum Beispiel Verwendung um zwischen 2 Punkten auf der Erde die Orientierung von PunktA zu PunktB zu krigen (afaik).


edit2:

meins hat nicht funktioniert :(
das von nox geht ;)

danke nochmal

Werbeanzeige