Ejemplo n.º 1
0
        internal void CheckMaxCount()
        {
            if (MaxCount == 0)
            {
                return;
            }

            float time = EngineApp.Instance.Time;

            if (time == checkMaxCountTime)
            {
                return;
            }
            checkMaxCountTime = time;

            while (createdDecals.Count > MaxCount)
            {
                Decal decal = createdDecals.First.Value;
                createdDecals.Remove(decal);
                decal.SetForDeletion(true);
            }
        }
Ejemplo n.º 2
0
        private void CreateDecalForStaticObject(ShapeTriangleID startTriangle, Vec3 pos, Vec3 normal,
                                                MapObject parentMapObject)
        {
            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;
                    {
                        switch (triangle.shape.ShapeType)
                        {
                        case Shape.Type.Mesh:
                            MeshShape meshShape = (MeshShape)triangle.shape;
                            meshShape.GetTriangle(triangle.triangleID, true, out p0, out p1, out p2);
                            break;

                        case Shape.Type.HeightField:
                            HeightFieldShape heightFieldShape = (HeightFieldShape)triangle.shape;
                            heightFieldShape.GetTriangle(triangle.triangleID, true, out p0, out p1, out p2);
                            break;

                        default:
                            Log.Fatal("DecalCreator: CreateDecalForStaticObject: Not supported shape type ({0}).",
                                      triangle.shape.ShapeType);
                            return;
                        }
                    }

                    //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;
                    {
                        switch (triangle.shape.ShapeType)
                        {
                        case Shape.Type.Mesh:
                            MeshShape meshShape = (MeshShape)triangle.shape;
                            meshShape.GetTriangle(triangle.triangleID, true, out p0, out p1, out p2);
                            break;

                        case Shape.Type.HeightField:
                            HeightFieldShape heightFieldShape = (HeightFieldShape)triangle.shape;
                            heightFieldShape.GetTriangle(triangle.triangleID, true, out p0, out p1, out p2);
                            break;

                        default:
                            Log.Fatal("DecalCreator: CreateDecalForStaticObject: Not supported shape type ({0}).",
                                      triangle.shape.ShapeType);
                            return;
                        }
                    }

                    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 perpendicular to normal offset.
                    //Alternative way: for shader based rendering use DepthOffset property of decal material.
                    //if( !RenderSystem.Instance.HasShaderModel3() )
                    {
                        //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);
        }
Ejemplo n.º 3
0
 internal void RemoveDecal(Decal decal)
 {
     Type.RemoveDecalFromCreatedList(decal);
     decals.Remove(decal);
 }
Ejemplo n.º 4
0
 internal void RemoveDecalFromCreatedList(Decal decal)
 {
     createdDecals.Remove(decal);
 }
Ejemplo n.º 5
0
 internal void AddDecalToCreatedList(Decal decal)
 {
     createdDecals.AddLast(decal);
 }