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; }
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); }
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(); } }