public void ReceiveObject(MapObject obj, Teleporter source)
        {
            if (!string.IsNullOrEmpty(Type.ReceiveParticleName))
            {
                Map.Instance.CreateAutoDeleteParticleSystem(Type.ReceiveParticleName, Position);
            }

            if (source == null)
            {
                float offset = obj.Position.Z - obj.PhysicsModel.GetGlobalBounds().Minimum.Z;
                obj.Position = Position + new Vec3(0, 0, offset);
                obj.Rotation = Rotation;
                obj.SetOldTransform(obj.Position, obj.Rotation, obj.Scale);
            }
            else
            {
                Quat destRotation = Rotation * Mat3.FromRotateByZ(new Degree(180).InRadians()).ToQuat();

                foreach (Body body in obj.PhysicsModel.Bodies)
                {
                    body.Rotation = body.Rotation * source.Rotation.GetInverse() * destRotation;
                    Vec3 localPosOffset = (body.Position - source.Position) * source.Rotation.GetInverse();
                    body.Position    = Position + localPosOffset * destRotation;
                    body.OldPosition = body.Position;
                    body.OldRotation = body.Rotation;

                    body.LinearVelocity  = body.LinearVelocity * source.Rotation.GetInverse() * destRotation;
                    body.AngularVelocity = body.AngularVelocity * source.Rotation.GetInverse() * destRotation;
                }

                obj.UpdatePositionAndRotationByPhysics(true);
                obj.SetOldTransform(obj.Position, obj.Rotation, obj.Scale);

                Unit unit = obj as Unit;
                if (unit != null)
                {
                    PlayerIntellect playerIntellect = unit.Intellect as PlayerIntellect;
                    if (playerIntellect != null)
                    {
                        Vec3 vec = playerIntellect.LookDirection.GetVector();
                        Vec3 v   = vec * source.Rotation.GetInverse() * destRotation;
                        playerIntellect.LookDirection = SphereDir.FromVector(v);
                    }
                }
            }

            //add object to the list of processed objects. object can't activate teleportation.
            processedObjectsInActiveArea.AddWithCheckAlreadyContained(obj);

            //skip ticks to wait for update physics body of transfered object after teleportation.
            skipTicks += 2;
        }
Beispiel #2
0
        void CreateDecalForStaticObject(ShapeTriangleID startTriangle, Vec3 pos, Vec3 normal,
                                        MapObject parentMapObject)
        {
            Shape currentShape   = null;
            Mat4  shapeTransform = Mat4.Zero;

            Vec3[] shapeVertices = null;
            int[]  shapeIndices  = null;

            bool existsNormalsMore45Degrees = false;

            //find near triangles
            //Set<ShapeTriangleID> triangleIDs = new Set<ShapeTriangleID>();
            {
                Sphere checkSphere = new Sphere(pos, Type.Size * .5f * 1.41f);                  //Sqrt(2)

                //Set<ShapeTriangleID> checkedTriangles = new Set<ShapeTriangleID>();

                //Stack<ShapeTriangleID> trianglesForCheck = new Stack<ShapeTriangleID>( 16 );
                trianglesForCheck.Push(startTriangle);

                while (trianglesForCheck.Count != 0)
                {
                    ShapeTriangleID triangle = trianglesForCheck.Pop();

                    //add to checked triangles
                    if (!checkedTriangles.AddWithCheckAlreadyContained(triangle))
                    {
                        //ignore already checked triangles
                        continue;
                    }

                    //get triangle points
                    Vec3 p0, p1, p2;
                    {
                        if (currentShape != triangle.shape)
                        {
                            currentShape = triangle.shape;

                            if (currentShape.ShapeType == Shape.Type.Mesh)
                            {
                                ((MeshShape)currentShape).GetData(out shapeVertices, out shapeIndices);
                            }
                            else if (currentShape.ShapeType == Shape.Type.HeightField)
                            {
                                ((HeightFieldShape)currentShape).GetVerticesAndIndices(true,
                                                                                       out shapeVertices, out shapeIndices);
                            }
                            else
                            {
                                Log.Fatal("DecalCreator: Not supported shape type ({0}).",
                                          currentShape.ShapeType.ToString());
                            }

                            shapeTransform = currentShape.Body.GetTransform();
                            if (!currentShape.IsIdentityTransform)
                            {
                                shapeTransform *= currentShape.GetTransform();
                            }
                        }

                        int index = triangle.triangleID * 3;
                        p0 = shapeTransform * shapeVertices[shapeIndices[index + 0]];
                        p1 = shapeTransform * shapeVertices[shapeIndices[index + 1]];
                        p2 = shapeTransform * shapeVertices[shapeIndices[index + 2]];
                    }

                    //cull by checkBounds
                    if (!checkSphere.TriangleIntersection(p0, p1, p2))
                    {
                        continue;
                    }

                    //check normal
                    bool correctNormal = false;

                    if (Type.SpreadType != DecalCreatorType.SpreadTypes.Directional)
                    {
                        Plane plane = Plane.FromPoints(p0, p1, p2);
                        if (plane.GetSide(pos + normal) == Plane.Side.Positive)
                        {
                            Radian angle = MathFunctions.ACos(Vec3.Dot(normal, plane.Normal));

                            if (angle <= new Degree(70.0f).InRadians())
                            {
                                if (!existsNormalsMore45Degrees && angle >= new Degree(45.0f).InRadians())
                                {
                                    existsNormalsMore45Degrees = true;
                                }

                                correctNormal = true;
                            }
                        }
                    }
                    else
                    {
                        correctNormal = true;
                    }

                    if (correctNormal)
                    {
                        //add triangle to result list
                        triangleIDs.Add(triangle);
                    }

                    //add near triangles to check list
                    {
                        //expand vertices
                        const float border = .001f;
                        Vec3        center = (p0 + p1 + p2) * (1.0f / 3.0f);

                        Vec3 diff0 = p0 - center;
                        Vec3 diff1 = p1 - center;
                        Vec3 diff2 = p2 - center;

                        if (diff0 != Vec3.Zero && diff1 != Vec3.Zero && diff2 != Vec3.Zero)
                        {
                            p0 += diff0.GetNormalize() * border;
                            p1 += diff1.GetNormalize() * border;
                            p2 += diff2.GetNormalize() * border;

                            Vec3 p01 = (p0 + p1) * .5f;
                            Vec3 p12 = (p1 + p2) * .5f;
                            Vec3 p20 = (p2 + p0) * .5f;

                            //find triangles
                            for (int n = 0; n < 3; n++)
                            {
                                Vec3 p = Vec3.Zero;
                                switch (n)
                                {
                                case 0: p = p01; break;

                                case 1: p = p12; break;

                                case 2: p = p20; break;
                                }

                                RayCastResult[] piercingResult =
                                    PhysicsWorld.Instance.RayCastPiercing(new Ray(
                                                                              p + normal * .025f, -normal * .05f), (int)ContactGroup.CastOnlyCollision);
                                foreach (RayCastResult result in piercingResult)
                                {
                                    if (result.Shape != null)
                                    {
                                        trianglesForCheck.Push(new ShapeTriangleID(
                                                                   result.Shape, result.TriangleID));
                                    }
                                }
                            }
                        }
                    }
                }

                checkedTriangles.Clear();
            }

            if (triangleIDs.Count == 0)
            {
                return;
            }

            //calculate perpendiculars to normal
            Vec3 side1Normal;
            Vec3 side2Normal;

            {
                if (Math.Abs(normal.X) > .001f || Math.Abs(normal.Y) > .001f)
                {
                    side1Normal = Mat3.FromRotateByZ(MathFunctions.PI / 2) *
                                  new Vec3(normal.X, normal.Y, 0);
                    side1Normal.Normalize();
                }
                else
                {
                    side1Normal = new Vec3(1, 0, 0);
                }

                side2Normal = Vec3.Cross(normal, side1Normal);
            }

            //generate clip planes
            Plane[] clipPlanes = new Plane[6];
            {
                float halfSize = Type.Size * .5f;

                if (existsNormalsMore45Degrees)
                {
                    halfSize *= 1.41f;
                }

                Plane p;
                p             = Plane.FromVectors(normal, -side2Normal, Position);
                clipPlanes[0] = new Plane(p.Normal, p.Distance + halfSize);
                p             = Plane.FromVectors(normal, side2Normal, Position);
                clipPlanes[1] = new Plane(p.Normal, p.Distance + halfSize);
                p             = Plane.FromVectors(normal, -side1Normal, Position);
                clipPlanes[2] = new Plane(p.Normal, p.Distance + halfSize);
                p             = Plane.FromVectors(normal, side1Normal, Position);
                clipPlanes[3] = new Plane(p.Normal, p.Distance + halfSize);
                p             = Plane.FromVectors(side1Normal, side2Normal, Position);
                clipPlanes[4] = new Plane(p.Normal, p.Distance + halfSize);
                //clipPlanes[ 4 ] = new Plane( p.Normal, p.Distance + halfSize * .5f );
                p             = Plane.FromVectors(side1Normal, -side2Normal, Position);
                clipPlanes[5] = new Plane(p.Normal, p.Distance + halfSize);
                //clipPlanes[ 5 ] = new Plane( p.Normal, p.Distance + halfSize * .5f );
            }

            //generate vertices and indices by triangles
            //List<Decal.Vertex> vertices = new List<Decal.Vertex>( triangleIDs.Count * 3 );
            //List<int> indices = new List<int>( triangleIDs.Count * 3 );
            List <Decal.Vertex> vertices = tempVertices;
            List <int>          indices  = tempIndices;

            vertices.Clear();
            indices.Clear();
            {
                foreach (ShapeTriangleID triangle in triangleIDs)
                {
                    Vec3 p0, p1, p2;
                    {
                        if (currentShape != triangle.shape)
                        {
                            currentShape = triangle.shape;

                            if (currentShape.ShapeType == Shape.Type.Mesh)
                            {
                                ((MeshShape)currentShape).GetData(out shapeVertices, out shapeIndices);
                            }
                            else if (currentShape.ShapeType == Shape.Type.HeightField)
                            {
                                ((HeightFieldShape)currentShape).GetVerticesAndIndices(true,
                                                                                       out shapeVertices, out shapeIndices);
                            }
                            else
                            {
                                Log.Fatal("DecalCreator: Not supported shape type ({0}).",
                                          currentShape.ShapeType.ToString());
                            }

                            shapeTransform = currentShape.Body.GetTransform();
                            if (!currentShape.IsIdentityTransform)
                            {
                                shapeTransform *= currentShape.GetTransform();
                            }
                        }

                        int index = triangle.triangleID * 3;
                        p0 = shapeTransform * shapeVertices[shapeIndices[index + 0]];
                        p1 = shapeTransform * shapeVertices[shapeIndices[index + 1]];
                        p2 = shapeTransform * shapeVertices[shapeIndices[index + 2]];
                    }

                    List <Vec3> list = new List <Vec3>();
                    list.Add(p0);
                    list.Add(p1);
                    list.Add(p2);

                    //clip by planes
                    foreach (Plane plane in clipPlanes)
                    {
                        list = CutConvexPlanePolygonByPlane(list, plane);
                        if (list == null)
                        {
                            break;
                        }
                    }

                    //add to vertices and indices lists
                    if (list != null)
                    {
                        int vertexCount = vertices.Count;

                        Vec3 norm = Plane.FromPoints(p0, p1, p2).Normal;
                        foreach (Vec3 p in list)
                        {
                            vertices.Add(new Decal.Vertex(p, norm, Vec2.Zero, Vec3.Zero));
                        }

                        for (int n = 1; n < list.Count - 1; n++)
                        {
                            indices.Add(vertexCount);
                            indices.Add(vertexCount + n);
                            indices.Add(vertexCount + n + 1);
                        }
                    }
                }
            }

            triangleIDs.Clear();

            if (indices.Count == 0)
            {
                return;
            }

            //calculate texCoord and Type.DepthRenderOffset
            {
                Plane planeSide1 = Plane.FromVectors(normal, side1Normal, Position);
                Plane planeSide2 = Plane.FromVectors(normal, side2Normal, Position);
                float invSize    = 1.0f / Type.Size;

                for (int n = 0; n < vertices.Count; n++)
                {
                    Decal.Vertex vertex = vertices[n];

                    //calculate texCoord
                    float distance1 = planeSide1.GetDistance(vertex.position);
                    float distance2 = planeSide2.GetDistance(vertex.position);
                    vertex.texCoord = new Vec2(distance1 * invSize + .5f, distance2 * invSize + .5f);

                    //add Type.DepthRenderOffset
                    vertex.position = vertex.position + normal * Type.DepthRenderOffset;

                    vertices[n] = vertex;
                }
            }

            //calculate tangent vectors
            {
                int triangleCount = indices.Count / 3;
                for (int nTriangle = 0; nTriangle < triangleCount; nTriangle++)
                {
                    int index0 = indices[nTriangle * 3 + 0];
                    int index1 = indices[nTriangle * 3 + 1];
                    int index2 = indices[nTriangle * 3 + 2];

                    Decal.Vertex vertex0 = vertices[index0];
                    Decal.Vertex vertex1 = vertices[index1];
                    Decal.Vertex vertex2 = vertices[index2];

                    Vec3 tangent = MathUtils.CalculateTangentSpaceVector(
                        vertex0.position, vertex0.texCoord,
                        vertex1.position, vertex1.texCoord,
                        vertex2.position, vertex2.texCoord);

                    vertex0.tangent += tangent;
                    vertex1.tangent += tangent;
                    vertex2.tangent += tangent;

                    vertices[index0] = vertex0;
                    vertices[index1] = vertex1;
                    vertices[index2] = vertex2;
                }

                for (int n = 0; n < vertices.Count; n++)
                {
                    Decal.Vertex vertex = vertices[n];
                    if (vertex.tangent != Vec3.Zero)
                    {
                        vertex.tangent.Normalize();
                    }
                    vertices[n] = vertex;
                }
            }

            //subtract decal position (make local vertices coordinates)
            {
                for (int n = 0; n < vertices.Count; n++)
                {
                    Decal.Vertex vertex = vertices[n];
                    vertex.position -= Position;
                    vertices[n]      = vertex;
                }
            }

            //get material
            string materialName = null;
            {
                string physicsMaterialName = startTriangle.shape.MaterialName;
                string defaultMaterialName = "";

                foreach (DecalCreatorType.MaterialItem item in Type.Materials)
                {
                    if (item.PhysicsMaterialName == physicsMaterialName)
                    {
                        materialName = item.MaterialName;
                    }

                    if (string.IsNullOrEmpty(item.PhysicsMaterialName))
                    {
                        defaultMaterialName = item.MaterialName;
                    }
                }

                if (materialName == null)
                {
                    materialName = defaultMaterialName;
                }
            }

            //create Decal
            Decal decal = (Decal)Entities.Instance.Create("Decal", Map.Instance);

            decal.Position = Position;
            decal.Init(this, vertices.ToArray(), indices.ToArray(), materialName, parentMapObject);
            decal.PostCreate();
            Type.AddDecalToCreatedList(decal);
            decals.Add(decal);
        }
Beispiel #3
0
        protected virtual void CreateBullet(Mode mode)
        {
            Bullet obj = (Bullet)Entities.Instance.Create(mode.typeMode.BulletType, Parent);

            obj.SourceUnit = GetParentUnitHavingIntellect();
            obj.Position   = GetFirePosition(mode.typeMode);

            //Correcting position at a shot in very near object (when the point of a shot inside object).
            {
                Vec3 startPos = Position;
                if (AttachedMapObjectParent != null)
                {
                    startPos = AttachedMapObjectParent.Position;
                }

                Ray ray = new Ray(startPos, obj.Position - startPos);
                if (ray.Direction != Vec3.Zero)
                {
                    RayCastResult[] piercingResult = PhysicsWorld.Instance.RayCastPiercing(
                        ray, (int)ContactGroup.CastOnlyContact);

                    foreach (RayCastResult result in piercingResult)
                    {
                        MapObject mapObject = MapSystemWorld.GetMapObjectByBody(result.Shape.Body);

                        if (mapObject != null)
                        {
                            if (mapObject == this)
                            {
                                continue;
                            }
                            if (mapObject == this.AttachedMapObjectParent)
                            {
                                continue;
                            }
                        }

                        obj.Position = result.Position - ray.Direction * .01f;
                        break;
                    }
                }
            }

            Quat   rot             = GetFireRotation(mode.typeMode);
            Radian dispersionAngle = mode.typeMode.DispersionAngle;

            if (dispersionAngle != 0)
            {
                EngineRandom random = World.Instance.Random;

                Mat3 matrix;
                matrix  = Mat3.FromRotateByX(random.NextFloat() * MathFunctions.PI * 2);
                matrix *= Mat3.FromRotateByZ(random.NextFloat() * dispersionAngle);

                rot *= matrix.ToQuat();
            }
            obj.Rotation = rot;

            obj.PostCreate();

            //set damage coefficient
            float coef = obj.DamageCoefficient;
            Unit  unit = GetParentUnitHavingIntellect();

            if (unit != null && unit.BigDamageInfluence != null)
            {
                coef *= unit.BigDamageInfluence.Type.Coefficient;
            }
            obj.DamageCoefficient = coef;
        }
        void UpdatePhysXJoint()
        {
            bool needCreate = PushedToWorld && !Broken;
            bool created    = nativeJoint != IntPtr.Zero;

            if (needCreate == created)
            {
                return;
            }

            if (needCreate)
            {
                if (Math.Abs(Vec3.Dot(axis1.Direction, axis2.Direction)) > .095f)
                {
                    Log.Warning("UniversalJoint: Invalid axes.");
                    return;
                }
                //if( Axis1.LimitsEnabled && Axis1.LimitLow > Axis1.LimitHigh )
                //{
                //   Log.Warning( "UniversalJoint: Invalid axis1 limits (low > high)." );
                //   return;
                //}
                //if( Axis2.LimitsEnabled && Axis2.LimitLow > Axis2.LimitHigh )
                //{
                //   Log.Warning( "UniversalJoint: Invalid axis2 limits (low > high)." );
                //   return;
                //}

                PhysXBody physXBody0 = (PhysXBody)Body1;
                PhysXBody physXBody1 = (PhysXBody)Body2;

                if ((!physXBody0.Static || !physXBody1.Static) &&
                    (physXBody0.nativeBody != IntPtr.Zero && physXBody1.nativeBody != IntPtr.Zero))
                {
                    axis1LocalAxis = Body1.Rotation.GetInverse() * axis1.Direction;
                    axis2LocalAxis = Body1.Rotation.GetInverse() * axis2.Direction;

                    Mat3 axisMatrix = new Mat3(axis1.Direction, -Vec3.Cross(axis1.Direction, axis2.Direction), axis2.Direction) *
                                      Mat3.FromRotateByZ(MathFunctions.PI / 2);
                    Quat globalAxisRotation = axisMatrix.ToQuat().GetNormalize();
                    //Quat globalAxisRotation = new Mat3( axis1.Direction, -Vec3.Cross( axis1.Direction, axis2.Direction ),
                    //   axis2.Direction ).ToQuat().GetNormalize();

                    Vec3 localPosition0 = physXBody0.Rotation.GetInverse() * (Anchor - physXBody0.Position);
                    Quat localRotation0 = (physXBody0.Rotation.GetInverse() * globalAxisRotation).GetNormalize();
                    Vec3 localPosition1 = physXBody1.Rotation.GetInverse() * (Anchor - physXBody1.Position);
                    Quat localRotation1 = (physXBody1.Rotation.GetInverse() * globalAxisRotation).GetNormalize();

                    nativeJoint = PhysXNativeWrapper.PhysXNativeD6Joint.Create(
                        physXBody0.nativeBody, ref localPosition0, ref localRotation0,
                        physXBody1.nativeBody, ref localPosition1, ref localRotation1);

                    PhysXNativeD6Joint.SetMotion(nativeJoint, PhysXD6Axis.X, PhysXD6Motion.Locked);
                    PhysXNativeD6Joint.SetMotion(nativeJoint, PhysXD6Axis.Y, PhysXD6Motion.Locked);
                    PhysXNativeD6Joint.SetMotion(nativeJoint, PhysXD6Axis.Z, PhysXD6Motion.Locked);

                    UpdateLimits();

                    if (ContactsEnabled)
                    {
                        PhysXNativeWrapper.PhysXJoint.SetCollisionEnable(nativeJoint, true);
                    }
                    UpdatePhysXBreakData();
                    if (Scene._EnableDebugVisualization)
                    {
                        SetVisualizationEnable(true);
                    }

                    //PhysXNativeD6Joint.SetProjectionTolerances( nativeJoint, .2f, MathFunctions.PI );
                    //PhysXNativeWrapper.PhysXJoint.SetProjectionEnable( nativeJoint, true );
                }
            }
            else
            {
                DestroyPhysXJoint();
            }
        }