Example #1
0
        public override MeshDraw CreateDebugPrimitive(GraphicsDevice device)
        {
            var verts = new VertexPositionNormalTexture[pointsList.Count];

            for (var i = 0; i < pointsList.Count; i++)
            {
                verts[i].Position          = pointsList[i];
                verts[i].TextureCoordinate = Vector2.Zero;
                verts[i].Normal            = Vector3.Zero;
            }

            var intIndices = indicesList.Select(x => (int)x).ToArray();

            ////calculate basic normals
            ////todo verify, winding order might be wrong?
            for (var i = 0; i < indicesList.Count; i += 3)
            {
                var i1 = intIndices[i];
                var i2 = intIndices[i + 1];
                var i3 = intIndices[i + 2];
                var a  = verts[i1];
                var b  = verts[i2];
                var c  = verts[i3];
                var n  = Vector3.Cross((b.Position - a.Position), (c.Position - a.Position));
                n.Normalize();
                verts[i1].Normal = verts[i2].Normal = verts[i3].Normal = n;
            }

            var meshData = new GeometricMeshData <VertexPositionNormalTexture>(verts, intIndices, false);

            return(new GeometricPrimitive(device, meshData).ToMeshDraw());
        }
Example #2
0
        public ConvexHullColliderShape(IReadOnlyList <Vector3> points, IEnumerable <uint> indices)
        {
            Type = ColliderShapeTypes.ConvexHull;
            Is2D = false;

            InternalShape = new BulletSharp.ConvexHullShape(points);

            if (!PhysicsEngine.Singleton.CreateDebugPrimitives)
            {
                return;
            }

            var verts = new VertexPositionNormalTexture[points.Count];

            for (var i = 0; i < points.Count; i++)
            {
                verts[i].Position          = points[i];
                verts[i].TextureCoordinate = Vector2.Zero;
                verts[i].Normal            = Vector3.Zero;
            }

            var intIndices = indices.Select(x => (int)x).ToArray();
            var meshData   = new GeometricMeshData <VertexPositionNormalTexture>(verts, intIndices, false);

            DebugPrimitive        = new GeometricPrimitive(PhysicsEngine.Singleton.DebugGraphicsDevice, meshData);
            DebugPrimitiveScaling = Matrix.Scaling(new Vector3(1, 1, 1) * 1.01f);
        }
        /// <summary>
        /// Generates triangles for an infinite plane that will completely intersect the given bounding box
        /// </summary>
        private NavigationMeshInputBuilder BuildPlaneGeometry(Plane plane, BoundingBox boundingBox)
        {
            Vector3 maxSize     = boundingBox.Maximum - boundingBox.Minimum;
            float   maxDiagonal = Math.Max(maxSize.X, Math.Max(maxSize.Y, maxSize.Z));

            // Generate source plane triangles
            Vector3[] planePoints;
            int[]     planeInds;
            NavigationMeshBuildUtils.BuildPlanePoints(ref plane, maxDiagonal, out planePoints, out planeInds);

            Vector3 tangent, bitangent;

            NavigationMeshBuildUtils.GenerateTangentBinormal(plane.Normal, out tangent, out bitangent);
            // Calculate plane offset so that the plane always covers the whole range of the bounding box
            Vector3 planeOffset = Vector3.Dot(boundingBox.Center, tangent) * tangent;

            planeOffset += Vector3.Dot(boundingBox.Center, bitangent) * bitangent;

            VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[planePoints.Length];
            for (int i = 0; i < planePoints.Length; i++)
            {
                vertices[i] = new VertexPositionNormalTexture(planePoints[i] + planeOffset, Vector3.UnitY, Vector2.Zero);
            }

            GeometricMeshData <VertexPositionNormalTexture> meshData = new GeometricMeshData <VertexPositionNormalTexture>(vertices, planeInds, true);

            NavigationMeshInputBuilder inputBuilder = new NavigationMeshInputBuilder();

            inputBuilder.AppendMeshData(meshData, Matrix.Identity);
            return(inputBuilder);
        }
Example #4
0
        /// <summary>
        /// Appends local mesh data transformed with and object transform
        /// </summary>
        /// <param name="meshData"></param>
        /// <param name="objectTransform"></param>
        public void AppendMeshData(GeometricMeshData <VertexPositionNormalTexture> meshData, Matrix objectTransform)
        {
            // Transform box points
            int vbase = Points.Count;

            for (int i = 0; i < meshData.Vertices.Length; i++)
            {
                VertexPositionNormalTexture point = meshData.Vertices[i];
                point.Position = Vector3.Transform(point.Position, objectTransform).XYZ();
                Points.Add(point.Position);
                BoundingBox.Merge(ref BoundingBox, ref point.Position, out BoundingBox);
            }

            if (meshData.IsLeftHanded)
            {
                // Copy indices with offset applied
                for (int i = 0; i < meshData.Indices.Length; i += 3)
                {
                    Indices.Add(meshData.Indices[i] + vbase);
                    Indices.Add(meshData.Indices[i + 2] + vbase);
                    Indices.Add(meshData.Indices[i + 1] + vbase);
                }
            }
            else
            {
                // Copy indices with offset applied
                for (int i = 0; i < meshData.Indices.Length; i++)
                {
                    Indices.Add(meshData.Indices[i] + vbase);
                }
            }
        }
        public override MeshDraw CreateDebugPrimitive(GraphicsDevice device)
        {
            if (cachedDebugPrimitive != null) return cachedDebugPrimitive;

            var verts = new VertexPositionNormalTexture[pointsList.Count];
            for (var i = 0; i < pointsList.Count; i++)
            {
                verts[i].Position = pointsList[i];
                verts[i].TextureCoordinate = Vector2.Zero;
                verts[i].Normal = Vector3.Zero;
            }

            var intIndices = indicesList.Select(x => (int)x).ToArray();

            ////calculate basic normals
            ////todo verify, winding order might be wrong?
            for (var i = 0; i < indicesList.Count; i += 3)
            {
                var i1 = intIndices[i];
                var i2 = intIndices[i + 1];
                var i3 = intIndices[i + 2];
                var a = verts[i1];
                var b = verts[i2];
                var c = verts[i3];
                var n = Vector3.Cross((b.Position - a.Position), (c.Position - a.Position));
                n.Normalize();
                verts[i1].Normal = verts[i2].Normal = verts[i3].Normal = n;
            }

            var meshData = new GeometricMeshData<VertexPositionNormalTexture>(verts, intIndices, false);

            cachedDebugPrimitive = new GeometricPrimitive(device, meshData).ToMeshDraw();

            return cachedDebugPrimitive;
        }
Example #6
0
 public GeometryData(float size, float tessellationX, float tessellationY, VertexPositionNormalTexture[] vertices, int[] indices, bool isLeftHanded) : base(vertices, indices, isLeftHanded)
 {
     Data          = new GeometricMeshData <VertexPositionNormalTexture>(vertices, indices, isLeftHanded);
     Size          = size;
     TessellationX = tessellationX;
     TessellationY = tessellationY;
 }
Example #7
0
        public override MeshDraw CreateDebugPrimitive(GraphicsDevice device)
        {
            var verts = new VertexPositionNormalTexture[vertices.Length];

            for (int i = 0; i < vertices.Length; i++)
            {
                verts[i].Position = vertices[i];
            }
            var meshData = new GeometricMeshData <VertexPositionNormalTexture>(verts, indices, false);

            return(new GeometricPrimitive(device, meshData).ToMeshDraw());
        }
Example #8
0
        public static void CopyFromGeometricPrimitive(GeometricMeshData <VertexPositionNormalTexture> primitiveData, ref VertexPositionTexture[] vertices, ref int[] indices)
        {
            for (int i = 0; i < vertices.Length; ++i)
            {
                vertices[i].Position          = primitiveData.Vertices[i].Position;
                vertices[i].TextureCoordinate = primitiveData.Vertices[i].TextureCoordinate;
            }

            for (int i = 0; i < indices.Length; ++i)
            {
                indices[i] = primitiveData.Indices[i];
            }
        }
Example #9
0
        public static Model FromGeometricMeshData(GraphicsDevice graphicsDevice, GeometricMeshData <VertexPositionNormalTangentMultiTexture> geometryMesh, string effectName = "Default")
        {
            var vertices = geometryMesh.Vertices;

            // compute the bounding box of the primitive
            var boundingBox = BoundingBox.Empty;

            for (int i = 0; i < vertices.Length; i++)
            {
                BoundingBox.Merge(ref boundingBox, ref vertices[i].Position, out boundingBox);
            }

            return(FromGeometricMeshData(graphicsDevice, geometryMesh, boundingBox, VertexPositionNormalTangentMultiTexture.Layout, effectName));
        }
Example #10
0
        public static Model FromGeometricMeshData <T>(GraphicsDevice graphicsDevice, GeometricMeshData <T> geometryMesh, BoundingBox boundingBox, VertexDeclaration layout, string effectName = "Default") where T : struct, IVertex
        {
            var meshDraw = new MeshDraw();

            var vertices = geometryMesh.Vertices;
            var indices  = geometryMesh.Indices;

            if (indices.Length < 0xFFFF)
            {
                var indicesShort = new ushort[indices.Length];
                for (int i = 0; i < indicesShort.Length; i++)
                {
                    indicesShort[i] = (ushort)indices[i];
                }
                meshDraw.IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indicesShort).RecreateWith(indicesShort), false, indices.Length);
            }
            else
            {
                if (graphicsDevice.Features.Profile <= GraphicsProfile.Level_9_3)
                {
                    throw new InvalidOperationException("Cannot generate more than 65535 indices on feature level HW <= 9.3");
                }

                meshDraw.IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices).RecreateWith(indices), true, indices.Length);
            }

            meshDraw.VertexBuffers = new[] { new VertexBufferBinding(Buffer.Vertex.New(graphicsDevice, vertices).RecreateWith(vertices), layout, vertices.Length) };

            meshDraw.DrawCount     = indices.Length;
            meshDraw.PrimitiveType = PrimitiveType.TriangleList;

            var mesh = new Mesh {
                Draw = meshDraw, BoundingBox = boundingBox
            };

            mesh.Parameters.Set(RenderingParameters.RenderLayer, RenderLayers.RenderLayerAll);

            var model = new Model {
                BoundingBox = boundingBox
            };

            model.Add(mesh);

            return(model);
        }
        /// <summary>
        /// Appends local mesh data transformed with and object transform
        /// </summary>
        /// <param name="meshData"></param>
        /// <param name="objectTransform"></param>
        public void AppendMeshData(GeometricMeshData<VertexPositionNormalTexture> meshData, Matrix objectTransform)
        {
            // Transform box points
            int vbase = Points.Count;
            for (int i = 0; i < meshData.Vertices.Length; i++)
            {
                VertexPositionNormalTexture point = meshData.Vertices[i];
                point.Position = Vector3.Transform(point.Position, objectTransform).XYZ();
                Points.Add(point.Position);
                BoundingBox.Merge(ref BoundingBox, ref point.Position, out BoundingBox);
            }

            // Copy indices with offset applied
            for (int i = 0; i < meshData.Indices.Length; i++)
            {
                Indices.Add(meshData.Indices[i] + vbase);
            }
        }
Example #12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="GeometricPrimitive{T}"/> class.
        /// </summary>
        /// <param name="graphicsDevice">The graphics device.</param>
        /// <param name="geometryMesh">The geometry mesh.</param>
        /// <exception cref="System.InvalidOperationException">Cannot generate more than 65535 indices on feature level HW <= 9.3</exception>
        public GeometricPrimitive(GraphicsDevice graphicsDevice, GeometricMeshData <T> geometryMesh)
        {
            GraphicsDevice = graphicsDevice;
            PipelineState  = new MutablePipelineState(graphicsDevice);

            var vertices = geometryMesh.Vertices;
            var indices  = geometryMesh.Indices;

            if (geometryMesh.IsLeftHanded)
            {
                ReverseWinding(vertices, indices);
            }

            if (indices.Length < 0xFFFF)
            {
                var indicesShort = new ushort[indices.Length];
                for (int i = 0; i < indicesShort.Length; i++)
                {
                    indicesShort[i] = (ushort)indices[i];
                }
                IndexBuffer = Buffer.Index.New(graphicsDevice, indicesShort).RecreateWith(indicesShort).DisposeBy(this);
            }
            else
            {
                if (graphicsDevice.Features.CurrentProfile <= GraphicsProfile.Level_9_3)
                {
                    throw new InvalidOperationException("Cannot generate more than 65535 indices on feature level HW <= 9.3");
                }

                IndexBuffer   = Buffer.Index.New(graphicsDevice, indices).RecreateWith(indices).DisposeBy(this);
                IsIndex32Bits = true;
            }

            // For now it will keep buffers for recreation.
            // TODO: A better alternative would be to store recreation parameters so that we can reuse procedural code.
            VertexBuffer        = Buffer.Vertex.New(graphicsDevice, vertices).RecreateWith(vertices).DisposeBy(this);
            VertexBufferBinding = new VertexBufferBinding(VertexBuffer, new T().GetLayout(), vertices.Length);

            PipelineState.State.SetDefaults();
            PipelineState.State.InputElements = VertexBufferBinding.Declaration.CreateInputElements();
            PipelineState.State.PrimitiveType = PrimitiveQuad.PrimitiveType;
        }
Example #13
0
        private NavigationMeshDebugVisual CreateDebugVisual(NavigationMesh navigationMesh, NavigationMesh previousNavigationMesh)
        {
            NavigationMeshDebugVisual ret = new NavigationMeshDebugVisual();

            ret.DebugEntity = new Entity($"Debug entity for navigation mesh");

            // Create a visual for every layer with a separate color
            using (var layers = navigationMesh.Layers.GetEnumerator())
            {
                while (layers.MoveNext())
                {
                    Model model = new Model();

                    var currentLayer = layers.Current.Value;
                    var currentId    = layers.Current.Key;

                    NavigationMeshDisplayGroup displayGroup;
                    if (!groupDisplaySettings.TryGetValue(currentId, out displayGroup))
                    {
                        continue; // No display settings for this group
                    }
                    model.Add(displayGroup.Material);
                    model.Add(displayGroup.HighlightMaterial);

                    foreach (var p in currentLayer.Tiles)
                    {
                        bool updated = true;

                        NavigationMeshTile tile = p.Value;

                        // Extract vertex data
                        List <Vector3> tileVertexList = new List <Vector3>();
                        List <int>     tileIndexList  = new List <int>();
                        if (!tile.GetTileVertices(tileVertexList, tileIndexList))
                        {
                            continue;
                        }

                        // Check if updated
                        NavigationMeshLayer sourceLayer;
                        if (previousNavigationMesh != null && previousNavigationMesh.Layers.TryGetValue(currentId, out sourceLayer))
                        {
                            NavigationMeshTile oldTile = sourceLayer.FindTile(p.Key);
                            if (oldTile != null && oldTile.Data.SequenceEqual(tile.Data))
                            {
                                updated = false;
                            }
                        }

                        // Stack layers vertically
                        Vector3 offset = new Vector3(0.0f, LayerHeightMultiplier * displayGroup.Index, 0.0f);

                        // Calculate mesh bounding box from navigation mesh points
                        BoundingBox bb = BoundingBox.Empty;

                        List <VertexPositionNormalTexture> meshVertices = new List <VertexPositionNormalTexture>();
                        for (int i = 0; i < tileVertexList.Count; i++)
                        {
                            Vector3 position = tileVertexList[i] + offset;
                            BoundingBox.Merge(ref bb, ref position, out bb);

                            VertexPositionNormalTexture vert = new VertexPositionNormalTexture();
                            vert.Position          = position;
                            vert.Normal            = Vector3.UnitY;
                            vert.TextureCoordinate = new Vector2(0.5f, 0.5f);
                            meshVertices.Add(vert);
                        }

                        MeshDraw draw;
                        using (var meshData = new GeometricMeshData <VertexPositionNormalTexture>(meshVertices.ToArray(), tileIndexList.ToArray(), true))
                        {
                            GeometricPrimitive primitive = new GeometricPrimitive(game.GraphicsDevice, meshData);
                            ret.GeneratedDynamicPrimitives.Add(primitive);
                            draw = primitive.ToMeshDraw();
                        }

                        Mesh mesh = new Mesh
                        {
                            Draw          = draw,
                            MaterialIndex = updated ? 1 : 0,
                            BoundingBox   = bb
                        };
                        model.Add(mesh);
                    }

                    // Create an entity per layer
                    var layerEntity = new Entity($"Navigation group {currentId}");

                    // Add a new model component
                    var modelComponent = new ModelComponent(model);
                    layerEntity.Add(modelComponent);
                    modelComponent.Enabled = displayGroup.IsVisible;
                    ret.ModelComponents.Add(currentId, modelComponent);

                    ret.DebugEntity.AddChild(layerEntity);
                }
            }

            return(ret);
        }
            private void CollectInputGeometry()
            {
                // Reset state
                fullRebuild = false;
                updatedAreas.Clear();
                fullRebuild = oldBuild == null;

                sceneNavigationMeshInputBuilder = new NavigationMeshInputBuilder();

                foreach (var entity in sceneEntities)
                {
                    StaticColliderComponent collider = entity.Get <StaticColliderComponent>();

                    bool colliderEnabled = collider != null && ((CollisionFilterGroupFlags)collider.CollisionGroup & asset.IncludedCollisionGroups) != 0 && collider.Enabled;
                    if (colliderEnabled)
                    {
                        // Compose collider shape, mark as disabled if it failed so the respective area gets updated
                        collider.ComposeShape();
                        if (collider.ColliderShape == null)
                        {
                            colliderEnabled = false;
                        }
                    }

                    if (!colliderEnabled) // Removed or disabled
                    {
                        // Check for old object
                        NavigationMeshCachedBuildObject oldObject = null;
                        if (oldBuild?.Objects.TryGetValue(entity.Id, out oldObject) ?? false)
                        {
                            // This object has been disabled, update the area because it was removed and continue to the next object
                            updatedAreas.Add(oldObject.Data.BoundingBox);
                        }
                    }
                    else if (oldBuild?.IsUpdatedOrNew(entity) ?? true) // Is the entity updated?
                    {
                        TransformComponent entityTransform   = entity.Transform;
                        Matrix             entityWorldMatrix = entityTransform.WorldMatrix;

                        NavigationMeshInputBuilder entityNavigationMeshInputBuilder = new NavigationMeshInputBuilder();

                        bool isDeferred = false;

                        // Interate through all the colliders shapes while queueing all shapes in compound shapes to process those as well
                        Queue <ColliderShape> shapesToProcess = new Queue <ColliderShape>();
                        shapesToProcess.Enqueue(collider.ColliderShape);
                        while (shapesToProcess.Count > 0)
                        {
                            var shape     = shapesToProcess.Dequeue();
                            var shapeType = shape.GetType();
                            if (shapeType == typeof(BoxColliderShape))
                            {
                                var    box       = (BoxColliderShape)shape;
                                var    boxDesc   = (BoxColliderShapeDesc)box.Description;
                                Matrix transform = box.PositiveCenterMatrix * entityWorldMatrix;

                                var meshData = GeometricPrimitive.Cube.New(boxDesc.Size);
                                entityNavigationMeshInputBuilder.AppendMeshData(meshData, transform);
                            }
                            else if (shapeType == typeof(SphereColliderShape))
                            {
                                var    sphere     = (SphereColliderShape)shape;
                                var    sphereDesc = (SphereColliderShapeDesc)sphere.Description;
                                Matrix transform  = sphere.PositiveCenterMatrix * entityWorldMatrix;

                                var meshData = GeometricPrimitive.Sphere.New(sphereDesc.Radius);
                                entityNavigationMeshInputBuilder.AppendMeshData(meshData, transform);
                            }
                            else if (shapeType == typeof(CylinderColliderShape))
                            {
                                var    cylinder     = (CylinderColliderShape)shape;
                                var    cylinderDesc = (CylinderColliderShapeDesc)cylinder.Description;
                                Matrix transform    = cylinder.PositiveCenterMatrix * entityWorldMatrix;

                                var meshData = GeometricPrimitive.Cylinder.New(cylinderDesc.Height, cylinderDesc.Radius);
                                entityNavigationMeshInputBuilder.AppendMeshData(meshData, transform);
                            }
                            else if (shapeType == typeof(CapsuleColliderShape))
                            {
                                var    capsule     = (CapsuleColliderShape)shape;
                                var    capsuleDesc = (CapsuleColliderShapeDesc)capsule.Description;
                                Matrix transform   = capsule.PositiveCenterMatrix * entityWorldMatrix;

                                var meshData = GeometricPrimitive.Capsule.New(capsuleDesc.Length, capsuleDesc.Radius);
                                entityNavigationMeshInputBuilder.AppendMeshData(meshData, transform);
                            }
                            else if (shapeType == typeof(ConeColliderShape))
                            {
                                var    cone      = (ConeColliderShape)shape;
                                var    coneDesc  = (ConeColliderShapeDesc)cone.Description;
                                Matrix transform = cone.PositiveCenterMatrix * entityWorldMatrix;

                                var meshData = GeometricPrimitive.Cone.New(coneDesc.Radius, coneDesc.Height);
                                entityNavigationMeshInputBuilder.AppendMeshData(meshData, transform);
                            }
                            else if (shapeType == typeof(StaticPlaneColliderShape))
                            {
                                var    plane     = (StaticPlaneColliderShape)shape;
                                var    planeDesc = (StaticPlaneColliderShapeDesc)plane.Description;
                                Matrix transform = plane.PositiveCenterMatrix * entityWorldMatrix;

                                // Defer infinite planes because their size is not defined yet
                                deferredShapes.Add(new DeferredShape
                                {
                                    Description = planeDesc,
                                    Transform   = transform,
                                    Entity      = entity,
                                    NavigationMeshInputBuilder = entityNavigationMeshInputBuilder
                                });
                                isDeferred = true;
                            }
                            else if (shapeType == typeof(ConvexHullColliderShape))
                            {
                                var    hull      = (ConvexHullColliderShape)shape;
                                Matrix transform = hull.PositiveCenterMatrix * entityWorldMatrix;

                                // Convert hull indices to int
                                int[] indices = new int[hull.Indices.Count];
                                if (hull.Indices.Count % 3 != 0)
                                {
                                    throw new InvalidOperationException("Physics hull does not consist of triangles");
                                }
                                for (int i = 0; i < hull.Indices.Count; i += 3)
                                {
                                    indices[i]     = (int)hull.Indices[i];
                                    indices[i + 1] = (int)hull.Indices[i + 1];
                                    indices[i + 2] = (int)hull.Indices[i + 2];
                                }

                                entityNavigationMeshInputBuilder.AppendArrays(hull.Points.ToArray(), indices, transform);
                            }
                            else if (shapeType == typeof(CompoundColliderShape))
                            {
                                // Unroll compound collider shapes
                                var compound = (CompoundColliderShape)shape;
                                for (int i = 0; i < compound.Count; i++)
                                {
                                    shapesToProcess.Enqueue(compound[i]);
                                }
                            }
                        }

                        if (!isDeferred)
                        {
                            // Store current entity in build cache
                            currentBuild.Add(entity, entityNavigationMeshInputBuilder);

                            // Add (?old) and new bounding box to modified areas
                            sceneNavigationMeshInputBuilder.AppendOther(entityNavigationMeshInputBuilder);
                            NavigationMeshCachedBuildObject oldObject = null;
                            if (oldBuild?.Objects.TryGetValue(entity.Id, out oldObject) ?? false)
                            {
                                updatedAreas.Add(oldObject.Data.BoundingBox);
                            }
                            updatedAreas.Add(entityNavigationMeshInputBuilder.BoundingBox);
                        }
                    }
                    else // Not updated
                    {
                        // Copy old data into vertex buffer
                        NavigationMeshCachedBuildObject oldObject = oldBuild.Objects[entity.Id];
                        sceneNavigationMeshInputBuilder.AppendOther(oldObject.Data);
                        currentBuild.Add(entity, oldObject.Data);
                    }
                }

                // Unload loaded collider shapes
                foreach (var pair in loadedColliderShapes)
                {
                    contentManager.Unload(pair.Key);
                }

                // Store calculated bounding box
                if (generateBoundingBox)
                {
                    globalBoundingBox = sceneNavigationMeshInputBuilder.BoundingBox;
                }

                // Process deferred shapes
                Vector3 maxSize     = globalBoundingBox.Maximum - globalBoundingBox.Minimum;
                float   maxDiagonal = Math.Max(maxSize.X, Math.Max(maxSize.Y, maxSize.Z));

                foreach (DeferredShape shape in deferredShapes)
                {
                    StaticPlaneColliderShapeDesc planeDesc = (StaticPlaneColliderShapeDesc)shape.Description;
                    Plane plane = new Plane(planeDesc.Normal, planeDesc.Offset);

                    // Pre-Transform plane parameters
                    plane.Normal = Vector3.TransformNormal(plane.Normal, shape.Transform);
                    float offset = Vector3.Dot(shape.Transform.TranslationVector, plane.Normal);
                    plane.D += offset;

                    // Generate source plane triangles
                    Vector3[] planePoints;
                    int[]     planeInds;
                    NavigationMeshBuildUtils.BuildPlanePoints(ref plane, maxDiagonal, out planePoints, out planeInds);

                    Vector3 tangent, bitangent;
                    NavigationMeshBuildUtils.GenerateTangentBinormal(plane.Normal, out tangent, out bitangent);
                    // Calculate plane offset so that the plane always covers the whole range of the bounding box
                    Vector3 planeOffset = Vector3.Dot(globalBoundingBox.Center, tangent) * tangent;
                    planeOffset += Vector3.Dot(globalBoundingBox.Center, bitangent) * bitangent;

                    VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[planePoints.Length];
                    for (int i = 0; i < planePoints.Length; i++)
                    {
                        vertices[i] = new VertexPositionNormalTexture(planePoints[i] + planeOffset, Vector3.UnitY, Vector2.Zero);
                    }

                    GeometricMeshData <VertexPositionNormalTexture> meshData = new GeometricMeshData <VertexPositionNormalTexture>(vertices, planeInds, false);
                    shape.NavigationMeshInputBuilder.AppendMeshData(meshData, Matrix.Identity);
                    sceneNavigationMeshInputBuilder.AppendMeshData(meshData, Matrix.Identity);
                    // Update bounding box after plane generation
                    if (generateBoundingBox)
                    {
                        globalBoundingBox = sceneNavigationMeshInputBuilder.BoundingBox;
                    }

                    // Store deferred shape in build cahce just like normal onesdddd
                    currentBuild.Add(shape.Entity, shape.NavigationMeshInputBuilder);

                    // NOTE: Force a full rebuild when moving unbound shapes such as ininite planes
                    // the alternative is to intersect the old and new plane with the tiles to see which ones changed
                    // although in most cases it will be a horizontal plane and all tiles will be affected anyways
                    fullRebuild = true;
                }
            }
Example #15
0
        public GeometricPrimitive(GraphicsDevice graphicsDevice, GeometricMeshData<VertexPositionNormalTexture> geometryMesh) : base(graphicsDevice, geometryMesh)
        {

        }
 public GeometricMultiTexcoordPrimitive(GraphicsDevice graphicsDevice, GeometricMeshData <VertexPositionNormalTangentMultiTexture> geometryMesh)
     : base(graphicsDevice, geometryMesh)
 {
 }