Browse Source

Schnittpunktberechnung mit 2D Polygonen berichtigt und impuls Funktion zur Welt2D hinzugefügt

kolja 6 years ago
parent
commit
36e48bc88a
6 changed files with 120 additions and 22 deletions
  1. 5 0
      Kamera2D.cpp
  2. 1 0
      Kamera2D.h
  3. 59 19
      Model2D.cpp
  4. 6 1
      Model2D.h
  5. 39 2
      Welt2D.cpp
  6. 10 0
      Welt2D.h

+ 5 - 0
Kamera2D.cpp

@@ -98,6 +98,11 @@ Vertex Kamera2D::getWorldCoordinates( Punkt screenPos )
     return ( Mat3< float >::translation( wPos ) * Mat3< float >::scaling( 1 / zoom ) * Mat3< float >::rotation( -rotation ) * Mat3< float >::translation( (Vertex)gr / -2 ) ) * (Vertex)screenPos;
 }
 
+Vertex Kamera2D::getWorldDirection( Vertex dir )
+{
+    return Vertex( dir.x, dir.y ).rotation( -rotation ) * ( 1 / zoom );
+}
+
 Kamera2D *Kamera2D::getThis()
 {
     ref++;

+ 1 - 0
Kamera2D.h

@@ -26,6 +26,7 @@ namespace Framework
         __declspec( dllexport ) bool tick( double time );
         __declspec( dllexport ) void render( Bild &zRObj );
         __declspec( dllexport ) Vertex getWorldCoordinates( Punkt screenPos );
+        __declspec( dllexport ) Vertex getWorldDirection( Vertex dir );
         __declspec( dllexport ) Kamera2D *getThis();
         __declspec( dllexport ) Kamera2D *release();
     };

+ 59 - 19
Model2D.cpp

@@ -422,28 +422,17 @@ bool Model2DData::calcHitPoint( Vertex pos, Vertex dir, const char *polygonName,
                 Vertex point = a + ( b * offset );
                 if( offset >= 0 && offset <= 1 )
                 {
-                    if( !ret || ( hitpoint - pos ).getLengthSq() > ( point - pos ).getLengthSq() )
+                    float f = ( point.x - pos.x ) / dir.x;
+                    if( !dir.x )
+                        f = ( point.y - pos.y ) / dir.y;
+                    if( !ret || ( hitpoint - pos ).getLengthSq() > ( point - pos ).getLengthSq() && f > 0 )
                     {
                         Vertex normal = b.CW90().normalize();
                         Vertex kNorm = Vertex( dir ).normalize();
                         moveSpeed = normal * ( normal * kNorm ) * dir.getLengthSq();
                         normal = ( point - *polygon->var.schwerpunkt ).CW90().normalize();
                         Vertex rotKraft = normal * ( normal * kNorm ) * dir.getLength();
-                        rotSpeed = ( ( rotKraft.getLength() * ( point - *polygon->var.schwerpunkt ).getLength() ) / 180.f ) * 3.14f;
-                        if( point.x >= polygon->var.schwerpunkt->x )
-                        {
-                            if( point.y >= polygon->var.schwerpunkt->y && rotKraft.x > 0 && rotKraft.y < 0 )
-                                rotSpeed = -rotSpeed;
-                            if( point.y < polygon->var.schwerpunkt->y && rotKraft.x < 0 && rotKraft.y < 0 )
-                                rotSpeed = -rotSpeed;
-                        }
-                        else
-                        {
-                            if( point.y >= polygon->var.schwerpunkt->y && rotKraft.x > 0 && rotKraft.y > 0 )
-                                rotSpeed = -rotSpeed;
-                            if( point.y < polygon->var.schwerpunkt->y && rotKraft.x < 0 && rotKraft.y > 0 )
-                                rotSpeed = -rotSpeed;
-                        }
+                        rotSpeed = ( ( rotKraft.getLength() * ( point - *polygon->var.schwerpunkt ).getLength() ) / 180.f ) * 3.14f * ( normal * kNorm );
                         hitpoint = point;
                     }
                     ret = 1;
@@ -699,15 +688,36 @@ void Model2DObject::setTextur( Textur2D *t )
 
 void Model2DObject::impuls( Vertex start, Vertex speed )
 {
+    start = getObjectPos( start );
+    speed = getObjectDir( speed );
     if( rData )
     {
+        Vertex resSpeed;
+        float resRotSpeed;
         Vertex hp;
         Vertex mSpeed;
         float rSpeed;
-        if( rData->calcHitPoint( start, speed, "", hp, mSpeed, rSpeed ) )
+        float dist = INFINITY;
+        for( auto p = rData->polygons->getArray(); p.set; p++ )
         {
-            this->speed += mSpeed;
-            this->rSpeed += rSpeed;
+            if( rData->calcHitPoint( start, speed, p.var.name->getText(), hp, mSpeed, rSpeed ) )
+            {
+                float f = ( hp.x - start.x ) / speed.x;
+                if( !speed.x )
+                    f = ( hp.y - start.y ) / speed.y;
+                if( ( hp - start ).getLengthSq() < dist && f > 0 )
+                {
+                    resSpeed = mSpeed.rotation( rotation );
+                    resRotSpeed = rSpeed;
+                    dist = ( hp - start ).getLengthSq();
+                }
+            }
+        }
+        // TODO schleife über alle polygone und translation von start und speed in Object koordinaten
+        if( dist < INFINITY )
+        {
+            this->speed += resSpeed;
+            this->rSpeed += resRotSpeed;
         }
     }
 }
@@ -862,6 +872,36 @@ Rect< float > Model2DObject::getBoundingBox() const
     return Rect< float >();
 }
 
+bool Model2DObject::calcHitPoint( Vertex pos, Vertex dir, Vertex &hitpoint ) const
+{
+    pos = getObjectPos( pos );
+    dir = getObjectDir( dir );
+    Vertex ms;
+    Vertex hp;
+    float rs;
+    float dist = INFINITY;
+    if( rData )
+    {
+        for( auto p = rData->polygons->getArray(); p.set; p++ )
+        {
+            if( rData->calcHitPoint( pos, dir, p.var.name->getText(), hp, ms, rs ) )
+            {
+                float f = ( hp.x - pos.x ) / dir.x;
+                if( !speed.x )
+                    f = ( hp.y - pos.y ) / dir.y;
+                if( ( hp - pos ).getLengthSq() < dist && f > 0 )
+                {
+                    hitpoint = getObjectMatrix() * hp;
+                    dist = ( hp - pos ).getLengthSq();
+                }
+            }
+        }
+        if( dist < INFINITY )
+            return 1;
+    }
+    return 0;
+}
+
 Model2DData *Model2DObject::getModel() const
 {
     return rData ? rData->getThis() : 0;

+ 6 - 1
Model2D.h

@@ -118,8 +118,13 @@ namespace Framework
         //  zMdl: Ein Zeiger auf das andere Model ohne erhöhten Reference Counter
         //  end: 0, falls alle Ecken beider Modele überprüft werdden sollen. 1, falls nur die Punkte dieses Models im anderen gesucht werden sollen
         __declspec( dllexport ) bool istModelInnen( const Model2DObject *zMdl, bool end = 0 ) const;
-
         __declspec( dllexport ) Rect< float > getBoundingBox() const override;
+        // Bestimmt den Aufschlagspunkt eines Strahls, der von pos ausgehend in Richtung dir abgegeben wird.
+        //  pos: Der Stützvektor der Linie
+        //  dir: Der richtungsvektor der Linie
+        //  hitPoint: eine referenz auf die variable in dem der schnittpunkt gespeichert werden soll
+        //  return: 1, fals ein Schnittpunkt existiert
+        __declspec( dllexport ) virtual bool calcHitPoint( Vertex pos, Vertex dir, Vertex &hitpoint ) const override;
         // Gibt die Model Daten zurück
         __declspec( dllexport ) Model2DData *getModel() const;
         // Gibt die Model Daten ohne erhöhten Reference Counter zurück

+ 39 - 2
Welt2D.cpp

@@ -73,6 +73,21 @@ Mat3< float > Object2D::getObjectMatrix() const
     return Mat3<float>::translation( position ) * Mat3<float>::rotation( rotation ) * Mat3<float>::scaling( size );
 }
 
+Mat3< float > Object2D::getInverseObjectMatrix() const
+{
+    return Mat3<float>::scaling( 1 / size ) * Mat3<float>::rotation( -rotation ) * Mat3<float>::translation( -position );
+}
+
+Vertex Object2D::getObjectPos( Vertex worldPos ) const
+{
+    return ( worldPos - position ).rotation( -rotation ) * ( 1 / size );
+}
+
+Vertex Object2D::getObjectDir( Vertex worldDir ) const
+{
+    return Vertex( worldDir.x, worldDir.y ).rotation( -rotation ) * ( 1 / size );
+}
+
 Vertex Object2D::getPosition() const
 {
     return position;
@@ -88,6 +103,11 @@ float Object2D::getSize() const
     return size;
 }
 
+bool Object2D::calcHitPoint( Vertex pos, Vertex dir, Vertex &hitpoint ) const
+{
+    return 0;
+}
+
 Object2D *Object2D::getThis()
 {
     ref++;
@@ -128,8 +148,25 @@ void Welt2D::explosion( Vertex worldPos, float intensity, float maxRad )
     }
 }
 
-void impuls( Vertex start, Vertex speed )
-{}
+void Welt2D::impuls( Vertex worldPos, Vertex worldDir )
+{
+    Vertex hitPoint;
+    float dist = INFINITY;
+    Object2D *o = 0;
+    for( auto obj = objects->getArray(); obj.set; obj++ )
+    {
+        if( obj.var->calcHitPoint( worldPos, worldDir, hitPoint ) )
+        {
+            if( ( hitPoint - worldPos ).getLengthSq() < dist )
+            {
+                dist = ( hitPoint - worldPos ).getLengthSq();
+                o = obj.var;
+            }
+        }
+    }
+    if( o )
+        o->impuls( worldPos, worldDir );
+}
 
 bool Welt2D::tick( double zeit )
 {

+ 10 - 0
Welt2D.h

@@ -48,6 +48,9 @@ namespace Framework
         __declspec( dllexport ) virtual bool tick( double zeit );
         virtual void render( Mat3< float > &kamMat, Bild &zRObj ) = 0;
         __declspec( dllexport ) Mat3< float > getObjectMatrix() const;
+        __declspec( dllexport ) Mat3< float > getInverseObjectMatrix() const;
+        __declspec( dllexport ) Vertex getObjectPos( Vertex worldPos ) const;
+        __declspec( dllexport ) Vertex getObjectDir( Vertex worldDir ) const;
         // gibt die Position des Models zurück
         __declspec( dllexport ) Vertex getPosition() const;
         // gibt die Drehung des Models zurück
@@ -55,6 +58,12 @@ namespace Framework
         // gibt den Skallierungs Faktor zurück
         __declspec( dllexport ) float getSize() const;
         __declspec( dllexport ) virtual Rect< float > getBoundingBox() const = 0;
+        // Bestimmt den Aufschlagspunkt eines Strahls, der von pos ausgehend in Richtung dir abgegeben wird.
+        //  pos: Der Stützvektor der Linie
+        //  dir: Der richtungsvektor der Linie
+        //  hitPoint: eine referenz auf die variable in dem der schnittpunkt gespeichert werden soll
+        //  return: 1, fals ein Schnittpunkt existiert
+        __declspec( dllexport ) virtual bool calcHitPoint( Vertex pos, Vertex dir, Vertex &hitpoint ) const;
         __declspec( dllexport ) Object2D *getThis();
         __declspec( dllexport ) Object2D *release();
     };
@@ -72,6 +81,7 @@ namespace Framework
         __declspec( dllexport ) ~Welt2D();
         __declspec( dllexport ) void addObject( Object2D *obj );
         __declspec( dllexport ) void explosion( Vertex worldPos, float intensity, float maxRad );
+        __declspec( dllexport ) void impuls( Vertex worldPos, Vertex worldDir );
         __declspec( dllexport ) bool tick( double zeit );
         __declspec( dllexport ) void render( Mat3< float > &kamMat, Punkt size, Bild &zRObj );
         __declspec( dllexport ) Welt2D *getThis();