/// <summary>
        /// Checks if a ray intersects the bounding sphere of a model.
        /// </summary>
        private bool RayIntersectsModel(Ray ray, Meteor.Resources.Model instancedModel,
                                        out Matrix instanceMatrix, out BoundingSphere bSphere)
        {
            foreach (MeshInstanceGroup instanceGroup in instancedModel.MeshInstanceGroups.Values)
            {
                foreach (MeshInstance meshInstance in instanceGroup.visibleInstances)
                {
                    if (meshInstance == null)
                    {
                        continue;
                    }

                    // Sphere collision test in world space.
                    if (meshInstance.boundingSphere.Intersects(ray) != null)
                    {
                        instanceMatrix = meshInstance.Transform;
                        bSphere        = meshInstance.boundingSphere;
                        return(true);
                    }
                }
            }

            // No collision was found
            instanceMatrix = Matrix.Identity;
            bSphere        = new BoundingSphere();
            return(false);
        }
Example #2
0
        /// <summary>
        /// Draw instanced model with a custom effect without camera parameters
        /// </summary>

        private int DrawModel(Meteor.Resources.Model model, Effect effect, String technique)
        {
            if (model.animationPlayer != null)
            {
                String animatedTechnique = technique += "Animated";
                UseTechnique(animatedTechnique);
                TrimBoneTransforms(model);

                // Set bones if the model is animated
                currentEffect.Parameters["bones"].SetValue(tempBones);
            }
            else
            {
                UseTechnique(technique);
            }

            int meshIndex        = 0;
            int visibleInstances = 0;

            foreach (MeshInstanceGroup instanceGroup in model.MeshInstanceGroups.Values)
            {
                // Create vertex buffer if necessary
                model.BuildMeshData(graphicsDevice, instanceGroup);

                // Retrieve the current mesh from the mesh list
                ModelMesh mesh  = model.modelMeshes[meshIndex];
                Matrix    world = model.World * model.boneMatrices[mesh.ParentBone.Index];

                // Set world matrix for all mesh parts
                currentEffect.Parameters["World"].SetValue(world);

                foreach (ModelMeshPart meshPart in mesh.MeshParts)
                {
                    Material  meshMaterial = model.materials[meshIndex];
                    Texture2D textureValue = (meshMaterial.textures["Texture"] != null) ?
                                             meshMaterial.textures["Texture"] : blankTexture;

                    // Assign all proper textures to the effect
                    foreach (EffectParameter effectParam in currentEffect.Parameters)
                    {
                        if (meshMaterial.textures.ContainsKey(effectParam.Name))
                        {
                            effectParam.SetValue(meshMaterial.textures[effectParam.Name]);
                        }
                    }

                    DrawInstancedMeshPart(meshPart, instanceGroup);
                    meshIndex++;
                }
                // Finished drawing mesh parts
                visibleInstances += instanceGroup.totalVisible;
            }
            // Finished model rendering
            return(visibleInstances);
        }
Example #3
0
        /// <summary>
        /// A bit hacky way to limit bone transforms. Will fix soon.
        /// </summary>

        private void TrimBoneTransforms(Meteor.Resources.Model instancedModel)
        {
            if (instancedModel.animationPlayer != null)
            {
                Matrix[] bones    = instancedModel.animationPlayer.GetSkinTransforms();
                int      maxBones = (bones.Count() > 60) ? 60 : bones.Count();

                // Not very efficient to do, need a way to avoid copying arrays
                Array.Copy(bones, tempBones, maxBones);
            }
        }
Example #4
0
        private void DrawBoundingBoxes(Meteor.Resources.Model model, Camera camera)
        {
            int      meshIndex   = 0;
            Viewport v           = graphicsDevice.Viewport;
            float    farDistance = camera.farPlaneDistance;

            // Matrices to project into screen space
            Matrix worldViewProjection = camera.view * camera.projection;
            Matrix invClient           = Matrix.Invert(Matrix.CreateOrthographicOffCenter(0, v.Width, v.Height, 0, -1, 1));

            foreach (MeshInstanceGroup instancedGroup in model.MeshInstanceGroups.Values)
            {
                BoundingBox box = instancedGroup.boundingBox;

                // Assign the box corners
                boxCorners[0] = new Vector3(box.Min.X, box.Max.Y, box.Max.Z);
                boxCorners[1] = new Vector3(box.Max.X, box.Max.Y, box.Max.Z);                 // maximum
                boxCorners[2] = new Vector3(box.Max.X, box.Min.Y, box.Max.Z);
                boxCorners[3] = new Vector3(box.Min.X, box.Min.Y, box.Max.Z);
                boxCorners[4] = new Vector3(box.Min.X, box.Max.Y, box.Min.Z);
                boxCorners[5] = new Vector3(box.Max.X, box.Max.Y, box.Min.Z);
                boxCorners[6] = new Vector3(box.Max.X, box.Min.Y, box.Min.Z);
                boxCorners[7] = new Vector3(box.Min.X, box.Min.Y, box.Min.Z);                 // minimum

                //Color[] colors = { Color.Cyan, Color.White, Color.Magenta, Color.Blue,
                //	Color.Green, Color.Yellow, Color.Red, Color.Black };XZ

                spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
                int visible = 0;

                foreach (MeshInstance meshInstance in instancedGroup.visibleInstances)
                {
                    if (meshInstance == null)
                    {
                        continue;
                    }

                    // If we have exceeded the visible count, we have already rendered
                    // all visible instances
                    if (visible >= instancedGroup.totalVisible)
                    {
                        break;
                    }

                    Matrix modelTransform = meshInstance.Transform;

                    Vector2 rectMin     = new Vector2(v.Width, v.Height);
                    Vector2 rectMax     = Vector2.Zero;
                    float   minDistance = camera.farPlaneDistance;

                    for (int i = 0; i < boxCorners.Length; i++)
                    {
                        model.boxVertices[i].Position = Vector3.Transform(boxCorners[i], modelTransform);
                        model.boxVertices[i].Color    = Color.Cyan;

                        // Determin the closest distance point in the bounding box
                        float camDistance = Vector3.Distance(model.boxVertices[i].Position, camera.position);
                        minDistance = Math.Min(camDistance, minDistance);

                        // Project the corners of the bounding box onto screen space

                        Vector4 position = new Vector4(model.boxVertices[i].Position, 1);
                        Vector4.Transform(ref position, ref worldViewProjection, out position);
                        position /= position.W;

                        Vector2 clientResult = Vector2.Transform(new Vector2(position.X, position.Y), invClient);

                        rectMin.X = (int)Math.Min((float)clientResult.X, (float)rectMin.X);
                        rectMin.Y = (int)Math.Min((float)clientResult.Y, (float)rectMin.Y);
                        rectMax.X = (int)Math.Max((float)clientResult.X, (float)rectMax.X);
                        rectMax.Y = (int)Math.Max((float)clientResult.Y, (float)rectMax.Y);
                    }

                    Vector3 topLeft     = v.Unproject(new Vector3(rectMin, minDistance), camera.projection, camera.view, camera.worldMatrix);
                    Vector3 bottomRight = v.Unproject(new Vector3(rectMax, minDistance), camera.projection, camera.view, camera.worldMatrix);

                    // Transform the temporary bounding boxes with the model instance's world matrix
                    // TODO: Update these boxes only when intances are updated

                    // Render the bounding box for this instance
                    if (camera.frustum.Contains(meshInstance.boundingSphere) != ContainmentType.Disjoint)
                    {
                        // Add a bounding sphere to the list of shapes to draw
                        //ShapeRenderer.AddBoundingSphere(meshInstance.BSphere, Color.Red);

                        for (int i = 0; i < basicEffect.CurrentTechnique.Passes.Count; i++)
                        {
                            basicEffect.CurrentTechnique.Passes[i].Apply();
                            graphicsDevice.DrawUserIndexedPrimitives <VertexPositionColor>(
                                PrimitiveType.LineList, model.boxVertices, 0, 8,
                                Meteor.Resources.Model.bBoxIndices, 0, 12);
                        }
                    }

                    // Render our shapes now
                    //ShapeRenderer.Draw(camera.View, camera.Projection);

                    // Add to the total visible
                    visible++;
                }
                spriteBatch.End();
                meshIndex++;
            }

            // End box rendering
        }