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

FlyingDragon

Frischling

  • »FlyingDragon« ist der Autor dieses Themas

Beiträge: 38

Wohnort: Sachsen

Beruf: Consultant / Software Architekt

  • Private Nachricht senden

1

22.02.2007, 22:50

ODE: Würfel fällt durch Ebene

Hallo, ich möchte mich etwas in ODE einarbeiten. Leider komme ich irgendwie nicht richtig weiter. Ich habe eine Plane erstellt und eine Box. Die Box soll aus einer Höhe auf die Ebene fallen und dort etwas hin-und herspringen. Leider fällt die Box einfach durch. Als Grafikengine verwende ich Ogre. Meine IDE ist VS2003.

Hier mein 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
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// ode-test.cpp


#include <windows.h>
#include <ode/ode.h>
#include <ogre.h>
#include <exampleapplication.h>

#pragma comment (lib, "ogremain_d.lib")
#pragma comment (lib, "ode.lib")

void NearCallback (void *data, dGeomID o1, dGeomID o2);

class OdeApplication : 
    public ExampleApplication, 
    public FrameListener
{
protected:
    dWorldID    mWorldId;
    dSpaceID    mSpaceId;
    dGeomID     mPlane;

    dGeomID     mBoxGeom;
    dBodyID     mBoxBody;
    dMass       mBoxMass;

    dJointGroupID   mContactGroup;

    Ogre::SceneNode*    mSceneNode;
    Ogre::SceneNode*    mPlaneNode;

public:
    friend void NearCallback (void *data, dGeomID o1, dGeomID o2);

    OdeApplication()
    {
        mWorldId = dWorldCreate();
        mSpaceId = dHashSpaceCreate(0);
        mContactGroup = dJointGroupCreate(0);

        mPlane = dCreatePlane(mSpaceId, 0, 1, 0, 0);

        dWorldSetGravity(mWorldId, 0, -9.81, 0);
        dWorldSetCFM(mWorldId, 1e-5);
        dWorldSetERP(mWorldId, 0.2);
        dWorldSetContactMaxCorrectingVel(mWorldId, 0.9);
        dWorldSetContactSurfaceLayer(mWorldId, 0);
        dWorldSetAutoDisableFlag(mWorldId, 0);
    }

    ~OdeApplication()
    {
        // ODE aufräumen

        dJointGroupDestroy(mContactGroup);
        dSpaceDestroy(mSpaceId);
        dWorldDestroy(mWorldId);
        dCloseODE();
    }

    void createCamera()
    {
        mCamera = mSceneMgr->createCamera("Spielerkamera");
        mCamera->setPosition(0, 100,-150);
        mCamera->lookAt(0, 100, 0);
    }

    void createScene()
    {
        Plane plane;
        plane.normal = Ogre::Vector3::UNIT_Y;
        plane.d = 0;

        Ogre::MeshManager::getSingleton().createPlane(
            "Untergrund", 
            Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
            plane, 
            150, 150, 20, 20, true, 1, 5, 5, Ogre::Vector3::UNIT_Z); 

        // den Untergrund erstellen

        Entity* entPlane;
        entPlane = mSceneMgr->createEntity("Boden", "Untergrund");
        entPlane->setMaterialName("Examples/RustySteel");
        mPlaneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
        mPlaneNode->attachObject(entPlane);

        // Eine Box erstellen

        Entity* entBox;
        entBox = mSceneMgr->createEntity("Cube", "cube.mesh");
        entBox->setMaterialName("Examples/BumpyMetal");
        mSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
        mSceneNode->attachObject(entBox);
        mSceneNode->scale(0.1, 0.1, 0.1);

        mBoxBody = dBodyCreate(mWorldId);
        dBodySetPosition(mBoxBody, 0, 15, 0);       
        dMassSetBox(&mBoxMass, 1, 10, 10, 10);
        mBoxGeom = dCreateBox(mSpaceId, 10, 10, 10);
        dGeomSetBody(mBoxGeom, mBoxBody);
        dBodySetMass(mBoxBody, &mBoxMass);  

        mCamera->setAutoTracking(true, mSceneNode);
    }

    void createFrameListener()
    {
        mRoot->addFrameListener(this);
    }

    bool frameStarted(const FrameEvent& evt)
    {

        dReal stepSize = evt.timeSinceLastFrame;

        if(stepSize > 0.0)
        {
            dSpaceCollide(mSpaceId, this, NearCallback);
            dWorldQuickStep(mWorldId, stepSize);
            dJointGroupEmpty(mContactGroup);
        }

        const dReal* pos;
        
        pos = dBodyGetPosition(mBoxBody);
        mSceneNode->setPosition(pos[0], pos[1], pos[2]);

        if(mWindow->isClosed())
            return false;

        return true;
    }

};

const int MAX_CONTACTS = 10;

void NearCallback (void *data, dGeomID o1, dGeomID o2)
{
    OdeApplication* app = reinterpret_cast<OdeApplication*>(data);

    dContact contact[MAX_CONTACTS];

    dBodyID b1 = dGeomGetBody(o1);
    dBodyID b2 = dGeomGetBody(o2);

    for(int i=0; i<MAX_CONTACTS; ++i)
    {
        contact[i].surface.mode = dContactBounce | dContactSoftCFM;
        contact[i].surface.mu = dInfinity;
        contact[i].surface.mu2 = 0;
        contact[i].surface.bounce = 0.01;
        contact[i].surface.bounce_vel = 0.1;
        contact[i].surface.soft_cfm = 0.01;
    }

    if(int numc = dCollide( o1, o2, MAX_CONTACTS, &contact[0].geom, sizeof(dContact)))
    {
        for(int i=0; i<numc; ++i)
        {
            dJointID c = dJointCreateContact(app->mWorldId, app->mContactGroup, contact + i);
            dJointAttach(c, b1, b2);
        }
    }
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    OdeApplication app;

    try 
    {
        app.go();
    } 
    catch( Exception& e ) 
    {
        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
    }
    return 0;
} 
Achtung! Das Lesen dieses Beitrags kann Ihnen und den Menschen in ihrer Umgebung erheblichen Schaden zufügen.
___________
Mein Leben, Freunde und die Spieleentwicklung

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

2

22.02.2007, 23:30

Re: ODE: Würfel fällt durch Ebene

Zitat von »"FlyingDragon"«

Als Grafikengine verwende ich Ogre.

http://www.ogre3d.org/wiki/index.php/Ogreode

Sehe ich das falsch oder erstellst du bloß eine grafische, keine physikalische Ebene?

FlyingDragon

Frischling

  • »FlyingDragon« ist der Autor dieses Themas

Beiträge: 38

Wohnort: Sachsen

Beruf: Consultant / Software Architekt

  • Private Nachricht senden

3

23.02.2007, 00:42

Re: ODE: Würfel fällt durch Ebene

Zitat von »"rewb0rn"«

Zitat von »"FlyingDragon"«

Als Grafikengine verwende ich Ogre.

http://www.ogre3d.org/wiki/index.php/Ogreode

Sehe ich das falsch oder erstellst du bloß eine grafische, keine physikalische Ebene?

Danke für den Link. Leider sind die meisten Seiten leer. Eigentlich erstelle ich eine Ebene mit dem hier:

C-/C++-Quelltext

1
mPlane = dCreatePlane(mSpaceId, 0, 1, 0, 0);

Das steht im Konstruktor.
Achtung! Das Lesen dieses Beitrags kann Ihnen und den Menschen in ihrer Umgebung erheblichen Schaden zufügen.
___________
Mein Leben, Freunde und die Spieleentwicklung

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

4

23.02.2007, 07:40

Wird denn NearCallback ausgeführt? Wahrscheinlich nicht oder?

Ich würde übrigens trotzdem mal bei OgreOde reinschaun, es gibt ein kleines aber feines Forum, eine Beispielanwendung die eigentlich das wichtigste erklärt und wenn man es einmal benutzt spart man sich jede Menge Feinarbeit mit dem ode code. Einziges Manko ist, dass die aktuelle Version nicht richtig funzt und der Autor zur Zeit nicht antwortet lol.
Im Notfall könnte ich dir aber eine veraltete funktionierende Version geben.

FlyingDragon

Frischling

  • »FlyingDragon« ist der Autor dieses Themas

Beiträge: 38

Wohnort: Sachsen

Beruf: Consultant / Software Architekt

  • Private Nachricht senden

5

23.02.2007, 12:43

Zitat von »"rewb0rn"«

Wird denn NearCallback ausgeführt? Wahrscheinlich nicht oder?

Doch, es wird ausgeführt. Anfangs dachte cih auch es läge daran.

Zitat

Ich würde übrigens trotzdem mal bei OgreOde reinschaun, es gibt ein kleines aber feines Forum, eine Beispielanwendung die eigentlich das wichtigste erklärt und wenn man es einmal benutzt spart man sich jede Menge Feinarbeit mit dem ode code. Einziges Manko ist, dass die aktuelle Version nicht richtig funzt und der Autor zur Zeit nicht antwortet lol.
Im Notfall könnte ich dir aber eine veraltete funktionierende Version geben.

Naja, mal reinschauen schon, aber nutzen will ich das nicht. Ich möchte schon meine eigenen Klassen dafür schreiben. Trotzdem Danke für den Tipp.
Achtung! Das Lesen dieses Beitrags kann Ihnen und den Menschen in ihrer Umgebung erheblichen Schaden zufügen.
___________
Mein Leben, Freunde und die Spieleentwicklung

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

6

23.02.2007, 13:19

Zitat

dJointID c = dJointCreateContact(app->mWorldId, app->mContactGroup, contact + i);


contact + i ist ziemlich unschön und das gleiche wie &contact wenn mich nicht alles täuscht, das würde ich ändern. ansonsten kann ich im mom keinen fehler entdecken, aber wie gesagt ich arbeite weniger mit ode direkt, daher kanns gut sein dass mir was entgeht.

edit: setz mal mu2 auf -1

FlyingDragon

Frischling

  • »FlyingDragon« ist der Autor dieses Themas

Beiträge: 38

Wohnort: Sachsen

Beruf: Consultant / Software Architekt

  • Private Nachricht senden

7

23.02.2007, 16:19

Ich hab einfach mal die Würfel die 1x1x1 gesetzt und schon geht es. Sobald ich den Würfel wieder auf 10x10x10 setze, geht es nicht. Naja, ich bin erstmal zu frieden. Vielen Dank an rewb0rn.
Achtung! Das Lesen dieses Beitrags kann Ihnen und den Menschen in ihrer Umgebung erheblichen Schaden zufügen.
___________
Mein Leben, Freunde und die Spieleentwicklung

8

30.05.2007, 18:13

Also,

wenn deine Box 10*10*10 groß ist hat sie bei dir eine Masse von 1000kg, da du dMassSetBox benutzt und als Parameter die Dicht von 1 übergibst.

Bei einem soft_cfm-Wert von 0,01 und einem lambda von(1000kg*9.81) ca. 9810 ergibt dies eine Geschwindigkeit von 98.1 m/s (lambda*cfm) mit der deine Box durch die Ebene fällt.

Eine erp von 0.2 wird bei 10m Durchdringtiefe nicht genug Korrekturgeschwindigkeit gegenrechnen, sondern nur 0.2*fps*10m = schätzungsweise 100 bei 50 fps. Diese Geschwindigkeit sollte die Errorreduction aber schon bei weniger als 100% Durchdringung zustandebringen, und dann würde deine Box wie nichts gutes in die Höhe schießen obwohl sie vorher auf der Ebene stand bzw. rumfedern als wäre sie ein Gummitank gefüllt mit Wasser(was passiert hängt von cfm und erp Kombination ab). Du begrenzt die Korrekturgeschwindigkeit auch noch mit dWorldSetContactMaxCorrectingVel auf 0.9, was auch sinnvoll ist, NUR deine Werte für erp und soft_cfm sind es NICHT (ERP auf keinen Fall mit 0.2). Du solltest soft_cfm auf jeden Fall runtersetzen auch wenn deine Box jetzt keine Tonne mehr wiegt und erp rauf.


PS... große Masse sorgen auch für Intgrationsfehler, besonders bei Rotationen. ;)

Gruss Wally

Werbeanzeige