Пример #1
0
        public void Move(CollisionObject item, Matrix4 transform)
        {
            var worldTransform = item.WorldTransform;
            var from           = worldTransform.ExtractTranslation( );
            var to             = transform.ExtractTranslation( );

            var closestConvexResultCallback = new ClosestNotMeConvexResultCallback(item, from, to)
            {
                CollisionFilterGroup = ( CollisionFilterGroups )(CollisionGroup.Objects | CollisionGroup.Level)
            };

            World.ConvexSweepTest(( ConvexShape )item.CollisionShape, worldTransform, transform, closestConvexResultCallback);
            if (closestConvexResultCallback.HasHit)
            {
                Vector3 linVel;
                Vector3 angVel;
                TransformUtil.CalculateVelocity(worldTransform, transform, 1.0f, out linVel, out angVel);
                Matrix4 T;
                TransformUtil.IntegrateTransform(worldTransform, linVel, angVel,
                                                 closestConvexResultCallback.ClosestHitFraction, out T);
                item.WorldTransform = T;
            }
            else
            {
                item.WorldTransform = transform;
            }
        }
Пример #2
0
        public void Draw(DebugDraw drawer)
        {
            int i;

            for (i = 0; i < NUMRAYS_IN_BAR; i++)
            {
                drawer.DrawLine(ref source[i], ref hit_com[i], ref green);
            }
            const float normalScale = 10.0f; // easier to see if this is big

            for (i = 0; i < NUMRAYS_IN_BAR; i++)
            {
                Vector3 to = hit_surface[i] + normalScale * normal[i];
                drawer.DrawLine(ref hit_surface[i], ref to, ref white);
            }
            Quaternion qFrom = Quaternion.RotationAxis(new Vector3(1.0f, 0.0f, 0.0f), 0.0f);
            Quaternion qTo   = Quaternion.RotationAxis(new Vector3(1.0f, 0.0f, 0.0f), 0.7f);

            for (i = 0; i < NUMRAYS_IN_BAR; i++)
            {
                Matrix  from = Matrix.RotationQuaternion(qFrom) * Matrix.Translation(source[i]);
                Matrix  to = Matrix.RotationQuaternion(qTo) * Matrix.Translation(dest[i]);
                Vector3 linVel, angVel;

                TransformUtil.CalculateVelocity(ref from, ref to, 1.0f, out linVel, out angVel);
                Matrix T;
                TransformUtil.IntegrateTransform(ref from, ref linVel, ref angVel, hit_fraction[i], out T);
                Vector3 box1 = boxShapeHalfExtents;
                Vector3 box2 = -boxShapeHalfExtents;
                drawer.DrawBox(ref box1, ref box2, ref T, ref cyan);
            }
        }
Пример #3
0
        public void ConvexSweepTest(ConvexShape castShape, ref IndexedMatrix convexFromWorld, ref IndexedMatrix convexToWorld, ConvexResultCallback resultCallback, float allowedCcdPenetration)
        {
            IndexedMatrix convexFromTrans = convexFromWorld;
            IndexedMatrix convexToTrans   = convexToWorld;

            IndexedVector3 castShapeAabbMin;
            IndexedVector3 castShapeAabbMax;
            /* Compute AABB that encompasses angular movement */
            IndexedVector3 linVel, angVel;

            TransformUtil.CalculateVelocity(ref convexFromTrans, ref convexToTrans, 1.0f, out linVel, out angVel);

            // FIXME MAN check this - should be a get/set rotation call, basis copy like this may break with scale?
            IndexedMatrix R = IndexedMatrix.Identity;

            R.SetRotation(convexFromTrans.GetRotation());


            castShape.CalculateTemporalAabb(ref R, ref linVel, ref angVel, 1.0f, out castShapeAabbMin, out castShapeAabbMax);

            /// go over all objects, and if the ray intersects their aabb + cast shape aabb,
            // do a ray-shape query using convexCaster (CCD)
            for (int i = 0; i < m_overlappingObjects.Count; i++)
            {
                CollisionObject collisionObject = m_overlappingObjects[i];
                //only perform raycast if filterMask matches
                if (resultCallback.NeedsCollision(collisionObject.GetBroadphaseHandle()))
                {
                    //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
                    IndexedVector3 collisionObjectAabbMin;
                    IndexedVector3 collisionObjectAabbMax;
                    IndexedMatrix  t = collisionObject.GetWorldTransform();
                    collisionObject.GetCollisionShape().GetAabb(ref t, out collisionObjectAabbMin, out collisionObjectAabbMax);
                    AabbUtil2.AabbExpand(ref collisionObjectAabbMin, ref collisionObjectAabbMax, ref castShapeAabbMin, ref castShapeAabbMax);
                    float          hitLambda = 1f; //could use resultCallback.m_closestHitFraction, but needs testing
                    IndexedVector3 hitNormal;

                    if (AabbUtil2.RayAabb(convexFromWorld._origin, convexToWorld._origin, ref collisionObjectAabbMin, ref collisionObjectAabbMax, ref hitLambda, out hitNormal))
                    {
                        IndexedMatrix wt = collisionObject.GetWorldTransform();
                        CollisionWorld.ObjectQuerySingle(castShape, ref convexFromTrans, ref convexToTrans,
                                                         collisionObject,
                                                         collisionObject.GetCollisionShape(),
                                                         ref wt,
                                                         resultCallback,
                                                         allowedCcdPenetration);
                    }
                }
            }
        }
Пример #4
0
        public void SaveKinematicState(float step)
        {
            //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
            if (step != 0)
            {
                //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform
                if (MotionState != null)
                {
                    MotionState.GetWorldTransform(out _worldTransform);
                }

                TransformUtil.CalculateVelocity(InterpolationWorldTransform, WorldTransform, step, ref _linearVelocity, ref _angularVelocity);
                InterpolationLinearVelocity  = _linearVelocity;
                InterpolationAngularVelocity = _angularVelocity;
                InterpolationWorldTransform  = WorldTransform;
            }
        }
        public void Draw(DebugDraw drawer)
        {
            foreach (var ray in _rays)
            {
                drawer.DrawLine(ref ray.Source, ref ray.HitCenterOfMass, ref _green);

                Vector3 to = ray.HitPoint + NormalScale * ray.Normal;
                drawer.DrawLine(ref ray.HitPoint, ref to, ref _white);

                Matrix  fromTransform = _fromRotation * Matrix.Translation(ray.Source);
                Matrix  toTransform = _toRotation * Matrix.Translation(ray.Destination);
                Vector3 linVel, angVel;
                TransformUtil.CalculateVelocity(ref fromTransform, ref toTransform, 1.0f, out linVel, out angVel);
                Matrix transform;
                TransformUtil.IntegrateTransform(ref fromTransform, ref linVel, ref angVel, ray.HitFraction, out transform);
                drawer.DrawBox(ref _boxBoundMin, ref _boxBoundMax, ref transform, ref _cyan);
            }
        }
Пример #6
0
        public void Draw(IDebugDraw drawer)
        {
            for (int i = 0; i < NumRays; i++)
            {
                drawer.DrawLine(ref _source[i], ref _hitCenterOfMass[i], Color.Lime);

                Vector3 to = _hitPoint[i] + NormalScale * _normal[i];
                drawer.DrawLine(ref _hitPoint[i], ref to, Color.White);

                Matrix  fromTransform = _fromRotation * Matrix.Translation(_source[i]);
                Matrix  toTransform = _toRotation * Matrix.Translation(_destination[i]);
                Vector3 linVel, angVel;
                TransformUtil.CalculateVelocity(fromTransform, toTransform, 1.0f, out linVel, out angVel);
                Matrix transform;
                TransformUtil.IntegrateTransform(fromTransform, linVel, angVel, _hitFraction[i], out transform);
                drawer.DrawBox(ref _boxBoundMin, ref _boxBoundMax, ref transform, Color.Aqua);
            }
        }
Пример #7
0
        public void OnMouseMove(CollisionManager CollisionManager, Camera ActiveCamera, System.Windows.Forms.MouseEventArgs e)
        {
            var mouse = new
            {
                Near = ActiveCamera.Project(new Vector2(e.X, e.Y), depth: -0.90f),
                Far  = ActiveCamera.Project(new Vector2(e.X, e.Y), depth: 1)
            };

            Matrix4 from = Matrix4.Translation(mouse.Near);
            Matrix4 to   = Matrix4.Translation(mouse.Far);

            var d = (mouse.Far - mouse.Near).Normalized();

            using (var callback = new CollisionWorld.ClosestConvexResultCallback(mouse.Near, mouse.Far))
            {
                callback.CollisionFilterGroup = CollisionFilterGroups.StaticFilter;
                callback.CollisionFilterMask  = CollisionFilterGroups.StaticFilter;

                CollisionManager.World.ConvexSweepTest((ConvexShape)CollisionObject.CollisionShape, from, to, callback);

                var lookingNormal = (callback.ConvexToWorld - callback.ConvexFromWorld).Normalized();
                var dot           = Vector3.Dot(callback.HitNormalWorld, lookingNormal);
                Console.WriteLine(callback.HitNormalWorld);
                if (callback.HasHit)
                {
                    if (!this.Selected)
                    {
                        return;
                    }
                    var matrix    = this.WorldMatrix.ClearTranslation();
                    var collMtrix = this.Model.RenderModel.compressionInfo[0].ToExtentsMatrix();

                    Vector3 linVel, angVel;
                    TransformUtil.CalculateVelocity(from, to, 1.0f, out linVel, out angVel);
                    Matrix4 T;
                    TransformUtil.IntegrateTransform(from, linVel, angVel, callback.ClosestHitFraction, out T);

                    this.WorldMatrix = T;
                }
            }
        }
Пример #8
0
        public void SaveKinematicState(float timeStep)
        {
            //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
            if (timeStep != 0f)
            {
                //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform
                if (GetMotionState() != null)
                {
                    GetMotionState().GetWorldTransform(out m_worldTransform);
                }
                IndexedVector3 linVel = IndexedVector3.Zero, angVel = IndexedVector3.Zero;

                // debug steps to track NaN's
                IndexedMatrix worldTransform = m_worldTransform;
                TransformUtil.CalculateVelocity(ref m_interpolationWorldTransform, ref worldTransform, timeStep, out m_linearVelocity, out m_angularVelocity);
                SetWorldTransform(ref worldTransform);

                m_interpolationLinearVelocity  = m_linearVelocity;
                m_interpolationAngularVelocity = m_angularVelocity;
                SetInterpolationWorldTransform(ref m_worldTransform);
                //printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ());
            }
        }
        public virtual bool CalcTimeOfImpact(ref IndexedMatrix fromA, ref IndexedMatrix toA, ref IndexedMatrix fromB, ref IndexedMatrix toB, CastResult result)
        {
            /// compute linear and angular velocity for this interval, to interpolate
            IndexedVector3 linVelA, angVelA, linVelB, angVelB;

            TransformUtil.CalculateVelocity(ref fromA, ref toA, 1f, out linVelA, out angVelA);
            TransformUtil.CalculateVelocity(ref fromB, ref toB, 1f, out linVelB, out angVelB);

            float boundingRadiusA = m_convexA.GetAngularMotionDisc();
            float boundingRadiusB = m_convexB1 != null?m_convexB1.GetAngularMotionDisc() : 0.0f;

            float          maxAngularProjectedVelocity = angVelA.Length() * boundingRadiusA + angVelB.Length() * boundingRadiusB;
            IndexedVector3 relLinVel = (linVelB - linVelA);

            float relLinVelocLength = relLinVel.Length();

            if (MathUtil.FuzzyZero(relLinVelocLength + maxAngularProjectedVelocity))
            {
                return(false);
            }


            float          lambda = 0f;
            IndexedVector3 v      = new IndexedVector3(1, 0, 0);

            int maxIter = MAX_ITERATIONS;

            IndexedVector3 n = IndexedVector3.Zero;

            bool           hasResult = false;
            IndexedVector3 c;

            float lastLambda = lambda;
            //float epsilon = float(0.001);

            int numIter = 0;
            //first solution, using GJK


            float radius = 0.001f;

            //	result.drawCoordSystem(sphereTr);

            PointCollector pointCollector1 = new PointCollector();

            {
                ComputeClosestPoints(ref fromA, ref fromB, pointCollector1);

                hasResult = pointCollector1.m_hasResult;
                c         = pointCollector1.m_pointInWorld;
            }

            if (hasResult)
            {
                float dist = pointCollector1.m_distance + result.m_allowedPenetration;

                n = pointCollector1.m_normalOnBInWorld;

                float projectedLinearVelocity = IndexedVector3.Dot(relLinVel, n);
                if ((projectedLinearVelocity + maxAngularProjectedVelocity) <= MathUtil.SIMD_EPSILON)
                {
                    return(false);
                }

                //not close enough
                while (dist > radius)
                {
                    if (result.m_debugDrawer != null)
                    {
                        IndexedVector3 colour = new IndexedVector3(1, 1, 1);
                        result.m_debugDrawer.DrawSphere(ref c, 0.2f, ref colour);
                    }
                    float dLambda = 0f;

                    projectedLinearVelocity = IndexedVector3.Dot(relLinVel, n);

                    //don't report time of impact for motion away from the contact normal (or causes minor penetration)
                    if ((projectedLinearVelocity + maxAngularProjectedVelocity) <= MathUtil.SIMD_EPSILON)
                    {
                        return(false);
                    }
                    dLambda = dist / (projectedLinearVelocity + maxAngularProjectedVelocity);

                    lambda = lambda + dLambda;

                    if (lambda > 1f || lambda < 0f)
                    {
                        return(false);
                    }


                    //todo: next check with relative epsilon
                    if (lambda <= lastLambda)
                    {
                        return(false);
                        //n.setValue(0,0,0);
                    }

                    lastLambda = lambda;

                    //interpolate to next lambda
                    IndexedMatrix interpolatedTransA = IndexedMatrix.Identity, interpolatedTransB = IndexedMatrix.Identity, relativeTrans = IndexedMatrix.Identity;

                    TransformUtil.IntegrateTransform(ref fromA, ref linVelA, ref angVelA, lambda, out interpolatedTransA);
                    TransformUtil.IntegrateTransform(ref fromB, ref linVelB, ref angVelB, lambda, out interpolatedTransB);
                    //relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA);
                    relativeTrans = interpolatedTransB.InverseTimes(ref interpolatedTransA);
                    if (result.m_debugDrawer != null)
                    {
                        result.m_debugDrawer.DrawSphere(interpolatedTransA._origin, 0.2f, new IndexedVector3(1, 0, 0));
                    }
                    result.DebugDraw(lambda);

                    PointCollector pointCollector = new PointCollector();
                    ComputeClosestPoints(ref interpolatedTransA, ref interpolatedTransB, pointCollector);
                    if (pointCollector.m_hasResult)
                    {
                        dist = pointCollector.m_distance + result.m_allowedPenetration;

                        c    = pointCollector.m_pointInWorld;
                        n    = pointCollector.m_normalOnBInWorld;
                        dist = pointCollector.m_distance;
                    }
                    else
                    {
                        result.ReportFailure(-1, numIter);
                        return(false);
                    }
                    numIter++;
                    if (numIter > maxIter)
                    {
                        result.ReportFailure(-2, numIter);
                        return(false);
                    }
                }

                result.m_fraction = lambda;
                result.m_normal   = n;
                result.m_hitPoint = c;
                return(true);
            }

            return(false);
        }
Пример #10
0
        public async void OnMouseMove(object sender, SceneMouseEventArgs e)
        {
            //var state = Mouse.GetState( );
            //if ( !state.IsButtonDown( MouseButton.Left ) ) return;

            var dynamicScene = sender as DynamicScene;

            if (dynamicScene == null)
            {
                return;
            }
            var collisionObject = selectedCollisionObject;
            var scenarioObject  = collisionObject?.UserObject as ObjectBlock;

            if (scenarioObject == null)
            {
                return;
            }

            var mouse = new
            {
                Close = e.Camera.UnProject(new Vector2(e.ScreenCoordinates.X, e.ScreenCoordinates.Y), -1),
                Far   = e.Camera.UnProject(new Vector2(e.ScreenCoordinates.X, e.ScreenCoordinates.Y), 1)
            };

            var rayCullCallback = new ClosestRayResultCullFaceCallback(mouse.Close, mouse.Far, false)
            {
                CollisionFilterGroup = CollisionFilterGroups.AllFilter,
                CollisionFilterMask  = CollisionFilterGroups.StaticFilter
            };

            dynamicScene.CollisionManager.World.RayTest(mouse.Close, mouse.Far, rayCullCallback);


            var rayCallback = new ClosestNotMeRayResultCallback(collisionObject, mouse.Close, mouse.Far)
            {
                CollisionFilterGroup = CollisionFilterGroups.AllFilter,
                CollisionFilterMask  = CollisionFilterGroups.StaticFilter
            };

            // GLDebug.Clear();

            dynamicScene.CollisionManager.World.RayTest(mouse.Close, mouse.Far, rayCallback);
            if (!rayCallback.HasHit)
            {
                return;
            }


            var splice = dynamicScene.Camera.Position;

            if (rayCullCallback.HasHit && rayCullCallback.ClosestHitFraction < rayCallback.ClosestHitFraction)
            {
                splice = rayCullCallback.HitPointWorld;
            }

            Ray     positionRay = new Ray(mouse.Close, mouse.Far);
            Vector3 center;
            float   radius;

            collisionObject.CollisionShape.GetBoundingSphere(out center, out radius);
            var origin = mouse.Close + (mouse.Far - mouse.Close) * (rayCallback.ClosestHitFraction - 0.01f);

            var surfaceNormal    = rayCallback.HitSurfaceNormal;
            var surfaceTangent   = Vector3.Cross(rayCallback.HitSurfaceTangent, rayCallback.HitNormalWorld);
            var surfaceBitangent = rayCallback.HitSurfaceTangent;


            var basisMatrix = new Matrix4(new Vector4(surfaceTangent), new Vector4(surfaceBitangent),
                                          new Vector4(rayCallback.HitSurfaceNormal), new Vector4(0, 0, 0, 1));


            GLDebug.QueuePointDraw(rayCallback.HitPointWorld);
            var destination = rayCallback.HitPointWorld;

            GLDebug.QueueLineDraw(destination, destination + surfaceNormal * 1.5f);
            GLDebug.QueueLineDraw(destination, destination + surfaceTangent * 0.5f);
            GLDebug.QueueLineDraw(destination, destination + surfaceBitangent * 0.5f);


            var convexCallback = new ClosestNotMeConvexResultCallback(collisionObject,
                                                                      collisionObject.WorldTransform.ExtractTranslation( ), destination)
            {
                CollisionFilterGroup = CollisionFilterGroups.DefaultFilter | CollisionFilterGroups.StaticFilter,
                CollisionFilterMask  = CollisionFilterGroups.StaticFilter
            };
            var convexShape = collisionObject.CollisionShape.IsConvex
                ? ( ConvexShape )collisionObject.CollisionShape
                : null;

            var extractRotation = Matrix4.CreateFromQuaternion(collisionObject.WorldTransform.ExtractRotation( ));
            var vector3         = destination + surfaceNormal * 1.5f;

            var extractTranslation = Matrix4.CreateTranslation(vector3);
            var from = basisMatrix * extractTranslation;
            var to   = basisMatrix * Matrix4.CreateTranslation(destination);

            GLDebug.QueueLineDraw(from.ExtractTranslation(  ), to.ExtractTranslation(  ), Color.Red.ToColorF(  ).RGBA.Xyz);

            await Task.Run(
                () => dynamicScene.CollisionManager.World.ConvexSweepTest(convexShape, from, to, convexCallback));

            if (convexCallback.HasHit)
            {
                Vector3 linVel;
                Vector3 angVel;
                TransformUtil.CalculateVelocity(from, to, 1.0f, out linVel, out angVel);
                Matrix4 T;
                TransformUtil.IntegrateTransform(from, linVel, angVel, convexCallback.ClosestHitFraction, out T);


                //.WorldTransform = basisMatrix * T;

                //var instanceBasis =
                //    scenarioObject.InstanceBasisMatrices[selectedCollisionObject.UserIndex];

                //scenarioObject.AssignInstanceBasisTransform(selectedCollisionObject.UserIndex, basisMatrix);

                //var upAxis = basisMatrix.Row2.Xyz.Normalized();

                //GLDebug.QueueLineDraw(0, selectedCollisionObject.WorldTransform.ExtractTranslation(),
                //    selectedCollisionObject.WorldTransform.ExtractTranslation() + upAxis);


                //var instanceRotation = scenarioObject.InstanceRotations[selectedCollisionObject.UserIndex];

                //////selectedScenarioObject.SetAxisAlignedRotation( selectedCollisionObject.UserIndex, rotation );

                //var R = Quaternion.FromAxisAngle(upAxis, _axisAlignedRotation);

                collisionObject.WorldTransform = T;

                //debugPoint2 = T.ExtractTranslation();
                //debugPoint3 = convexCallback.HitPointWorld + convexCallback.HitNormalWorld;

                //// selectedCollisionObject.WorldTransform = T;
                ////var localMatrix = scenarioObject.collisionSpaceMatrix.Inverted() * t.Inverted() * T;
                //// scenarioObject.InstanceRotations[selectedCollisionObject.UserIndex] = instanceRotation;
                //selectedScenarioObject.SetAxisAlignedRotation(selectedCollisionObject.UserIndex, _axisAlignedRotation);
                //scenarioObject.InstancePositions[selectedCollisionObject.UserIndex] = (scenarioObject.collisionSpaceMatrix.Inverted() * T).ExtractTranslation();
                //localMatrix.ExtractTranslation();
            }
        }