Exemple #1
0
        /// <summary>
        /// Initializes a new instance of the TerrainShape class.
        /// </summary>
        /// <param name="heights">An array containing the heights of the terrain surface.</param>
        /// <param name="scaleX">The x-scale factor. (The x-space between neighbour heights)</param>
        /// <param name="scaleZ">The y-scale factor. (The y-space between neighbour heights)</param>
        public TerrainShape(float[,] heights, float scaleX, float scaleZ)
        {
            heightsLength0 = heights.GetLength(0);
            heightsLength1 = heights.GetLength(1);

            #region Bounding Box
            boundings = JBBox.SmallBox;

            for (int i = 0; i < heightsLength0; i++)
            {
                for (int e = 0; e < heightsLength1; e++)
                {
                    if (heights[i, e] > boundings.Max.Y)
                        boundings.Max.Y = heights[i, e];
                    else if (heights[i, e] < boundings.Min.Y)
                        boundings.Min.Y = heights[i, e];
                }
            }

            boundings.Min.X = 0.0f;
            boundings.Min.Z = 0.0f;

            boundings.Max.X = checked(heightsLength0 * scaleX);
            boundings.Max.Z = checked(heightsLength1 * scaleZ);

            #endregion

            this.heights = heights;
            this.scaleX = scaleX;
            this.scaleZ = scaleZ;

            UpdateShape();
        }
 /// <summary>
 /// Calculates the bounding box of the sphere.
 /// </summary>
 /// <param name="orientation">The orientation of the shape.</param>
 /// <param name="box">The resulting axis aligned bounding box.</param>
 public override void GetBoundingBox(ref JMatrix orientation, out JBBox box)
 {
     box.Min.X = -radius;
     box.Min.Y = -radius;
     box.Min.Z = -radius;
     box.Max.X = radius;
     box.Max.Y = radius;
     box.Max.Z = radius;
 }
Exemple #3
0
        /// <summary>
        /// Gets the axis aligned bounding box of the orientated shape. This includes
        /// the whole shape.
        /// </summary>
        /// <param name="orientation">The orientation of the shape.</param>
        /// <param name="box">The axis aligned bounding box of the shape.</param>
        public override void GetBoundingBox(ref JMatrix orientation, out JBBox box)
        {
            JBBox helpBox = JBBox.LargeBox;
            int length = this.Prepare(ref helpBox);

            box = JBBox.SmallBox;

            for (int i = 0; i < length; i++)
            {
                this.SetCurrentShape(i);
                base.GetBoundingBox(ref orientation, out helpBox);
                JBBox.CreateMerged(ref box, ref helpBox, out box);
            }
        }
        /// <summary>
        /// Passes a axis aligned bounding box to the shape where collision
        /// could occour.
        /// </summary>
        /// <param name="box">The bounding box where collision could occur.</param>
        /// <returns>The upper index with which <see cref="SetCurrentShape"/> can be 
        /// called.</returns>
        public override int Prepare(ref JBBox box)
        {
            potentialTriangles.Clear();

            #region Expand Spherical
            JBBox exp = box;

            exp.Min.X -= sphericalExpansion;
            exp.Min.Y -= sphericalExpansion;
            exp.Min.Z -= sphericalExpansion;
            exp.Max.X += sphericalExpansion;
            exp.Max.Y += sphericalExpansion;
            exp.Max.Z += sphericalExpansion;
            #endregion

            octree.GetTrianglesIntersectingtAABox(potentialTriangles, ref exp);

            return potentialTriangles.Count;
        }
 /// <summary>
 /// Passes a axis aligned bounding box to the shape where collision
 /// could occour.
 /// </summary>
 /// <param name="box">The bounding box where collision could occur.</param>
 /// <returns>The upper index with which <see cref="SetCurrentShape"/> can be 
 /// called.</returns>
 public abstract int Prepare(ref JBBox box);
        /// <summary>
        /// Uses the supportMapping to calculate the bounding box. Should be overidden
        /// to make this faster.
        /// </summary>
        /// <param name="orientation">The orientation of the shape.</param>
        /// <param name="box">The resulting axis aligned bounding box.</param>
        public virtual void GetBoundingBox(ref JMatrix orientation, out JBBox box)
        {
            // I don't think that this can be done faster.
            // 6 is the minimum number of SupportMap calls.

            JVector vec = JVector.Zero;

            vec.Set(orientation.M11, orientation.M21, orientation.M31);
            SupportMapping(ref vec, out vec);
            box.Max.X = orientation.M11 * vec.X + orientation.M21 * vec.Y + orientation.M31 * vec.Z;

            vec.Set(orientation.M12, orientation.M22, orientation.M32);
            SupportMapping(ref vec, out vec);
            box.Max.Y = orientation.M12 * vec.X + orientation.M22 * vec.Y + orientation.M32 * vec.Z;

            vec.Set(orientation.M13, orientation.M23, orientation.M33);
            SupportMapping(ref vec, out vec);
            box.Max.Z = orientation.M13 * vec.X + orientation.M23 * vec.Y + orientation.M33 * vec.Z;

            vec.Set(-orientation.M11, -orientation.M21, -orientation.M31);
            SupportMapping(ref vec, out vec);
            box.Min.X = orientation.M11 * vec.X + orientation.M21 * vec.Y + orientation.M31 * vec.Z;

            vec.Set(-orientation.M12, -orientation.M22, -orientation.M32);
            SupportMapping(ref vec, out vec);
            box.Min.Y = orientation.M12 * vec.X + orientation.M22 * vec.Y + orientation.M32 * vec.Z;

            vec.Set(-orientation.M13, -orientation.M23, -orientation.M33);
            SupportMapping(ref vec, out vec);
            box.Min.Z = orientation.M13 * vec.X + orientation.M23 * vec.Y + orientation.M33 * vec.Z;
        }
        /// <summary>
        /// Gets the axis aligned bounding box of the orientated shape. This includes
        /// the whole shape.
        /// </summary>
        /// <param name="orientation">The orientation of the shape.</param>
        /// <param name="box">The axis aligned bounding box of the shape.</param>
        public override void GetBoundingBox(ref JMatrix orientation, out JBBox box)
        {
            box = octree.rootNodeBox;

            #region Expand Spherical
            box.Min.X -= sphericalExpansion;
            box.Min.Y -= sphericalExpansion;
            box.Min.Z -= sphericalExpansion;
            box.Max.X += sphericalExpansion;
            box.Max.Y += sphericalExpansion;
            box.Max.Z += sphericalExpansion;
            #endregion

            box.Transform(ref orientation);
        }
Exemple #8
0
        /// <summary>
        /// Passes a axis aligned bounding box to the shape where collision
        /// could occour.
        /// </summary>
        /// <param name="box">The bounding box where collision could occur.</param>
        /// <returns>The upper index with which <see cref="SetCurrentShape"/> can be 
        /// called.</returns>
        public override int Prepare(ref JBBox box)
        {
            // simple idea: the terrain is a grid. x and z is the position in the grid.
            // y the height. we know compute the min and max grid-points. All quads
            // between these points have to be checked.

            // including overflow exception prevention

            if (box.Min.X < boundings.Min.X) minX = 0;
            else
            {
                minX = (int)Math.Floor((float)((box.Min.X - sphericalExpansion) / scaleX));
                minX = Math.Max(minX, 0);
            }

            if (box.Max.X > boundings.Max.X) maxX = heightsLength0 - 1;
            else
            {
                maxX = (int)Math.Ceiling((float)((box.Max.X + sphericalExpansion) / scaleX));
                maxX = Math.Min(maxX, heightsLength0 - 1);
            }

            if (box.Min.Z < boundings.Min.Z) minZ = 0;
            else
            {
                minZ = (int)Math.Floor((float)((box.Min.Z - sphericalExpansion) / scaleZ));
                minZ = Math.Max(minZ, 0);
            }

            if (box.Max.Z > boundings.Max.Z) maxZ = heightsLength1 - 1;
            else
            {
                maxZ = (int)Math.Ceiling((float)((box.Max.Z + sphericalExpansion) / scaleZ));
                maxZ = Math.Min(maxZ, heightsLength1 - 1);
            }

            numX = maxX - minX;
            numZ = maxZ - minZ;

            // since every quad contains two triangles we multiply by 2.
            return numX * numZ * 2;
        }
 /// <summary>
 /// Creates a new instance of the TransformedShape struct.
 /// </summary>
 /// <param name="shape">The shape.</param>
 /// <param name="orientation">The orientation this shape should have.</param>
 /// <param name="position">The position this shape should have.</param>
 public TransformedShape(Shape shape, JMatrix orientation, JVector position)
 {
     this.position = position;
     this.orientation = orientation;
     JMatrix.Transpose(ref orientation, out invOrientation);
     this.shape = shape;
     this.boundingBox = new JBBox();
     UpdateBoundingBox();
 }
Exemple #10
0
        /// <summary>
        /// Create a bounding box appropriate for a child, based on a parents AABox
        /// </summary>
        /// <param name="aabb"></param>
        /// <param name="child"></param>
        /// <param name="result"></param>
        #region  private void CreateAABox(ref JBBox aabb, EChild child,out JBBox result)
        private void CreateAABox(ref JBBox aabb, EChild child,out JBBox result)
        {
            JVector dims;
            JVector.Subtract(ref aabb.Max, ref aabb.Min, out dims);
            JVector.Multiply(ref dims, 0.5f, out dims);

            JVector offset = JVector.Zero;

            switch (child)
            {
                case EChild.PPP: offset = new JVector(1, 1, 1); break;
                case EChild.PPM: offset = new JVector(1, 1, 0); break;
                case EChild.PMP: offset = new JVector(1, 0, 1); break;
                case EChild.PMM: offset = new JVector(1, 0, 0); break;
                case EChild.MPP: offset = new JVector(0, 1, 1); break;
                case EChild.MPM: offset = new JVector(0, 1, 0); break;
                case EChild.MMP: offset = new JVector(0, 0, 1); break;
                case EChild.MMM: offset = new JVector(0, 0, 0); break;

                default:
                    System.Diagnostics.Debug.WriteLine("Octree.CreateAABox  got impossible child");
                    break;
            }

            result = new JBBox();
            result.Min = new JVector(offset.X * dims.X, offset.Y * dims.Y, offset.Z * dims.Z);
            JVector.Add(ref result.Min, ref aabb.Min, out result.Min);

            JVector.Add(ref result.Min, ref dims, out result.Max);

            // expand it just a tiny bit just to be safe!
            float extra = 0.00001f;

            JVector temp; JVector.Multiply(ref dims, extra, out temp);
            JVector.Subtract(ref result.Min, ref temp, out result.Min);
            JVector.Add(ref result.Max, ref temp, out result.Max);
        }
Exemple #11
0
        /// <summary>
        /// Returns all triangles which intersect the given axis aligned bounding box.
        /// </summary>
        /// <param name="triangles">The list to add the triangles to.</param>
        /// <param name="testBox">The axis alignes bounding box.</param>
        /// <returns></returns>
        #region public int GetTrianglesIntersectingtAABox(List<int> triangles, ref JBBox testBox)
        public int GetTrianglesIntersectingtAABox(List<int> triangles, ref JBBox testBox)
        {
            if (nodes.Length == 0)
                return 0;
            int curStackIndex = 0;
            int endStackIndex = 1;

            UInt16[] nodeStack = nodeStackPool.GetNew();

            nodeStack[0] = 0;

            int triCount = 0;

            while (curStackIndex < endStackIndex)
            {
                UInt16 nodeIndex = nodeStack[curStackIndex];
                curStackIndex++;
                if (nodes[nodeIndex].box.Contains(ref testBox) != JBBox.ContainmentType.Disjoint)
                {
                    for (int i = 0; i < nodes[nodeIndex].triIndices.Length; ++i)
                    {
                        if (triBoxes[nodes[nodeIndex].triIndices[i]].Contains(ref testBox) != JBBox.ContainmentType.Disjoint)
                        {
                            triangles.Add(nodes[nodeIndex].triIndices[i]);
                            triCount++;
                        }
                    }

                    int numChildren = nodes[nodeIndex].nodeIndices.Length;
                    for (int i = 0; i < numChildren; ++i)
                    {
                        nodeStack[endStackIndex++] = nodes[nodeIndex].nodeIndices[i];
                    }
                }
            }

            nodeStackPool.GiveBack(nodeStack);

            return triCount;
        }
        /// <summary>
        /// Passes a axis aligned bounding box to the shape where collision
        /// could occour.
        /// </summary>
        /// <param name="box">The bounding box where collision could occur.</param>
        /// <returns>The upper index with which <see cref="SetCurrentShape"/> can be 
        /// called.</returns>
        public override int Prepare(ref JBBox box)
        {
            currentSubShapes.Clear();

            for (int i = 0; i < shapes.Length; i++)
            {
                if (shapes[i].boundingBox.Contains(ref box) != JBBox.ContainmentType.Disjoint)
                    currentSubShapes.Add(i);
            }

            return currentSubShapes.Count;
        }
Exemple #13
0
        /// <summary>
        /// Builds the octree.
        /// </summary>
        #region public void BuildOctree()
        public void BuildOctree()
        {
            // create tri and tri bounding box arrays
            triBoxes = new JBBox[tris.Length];

            // create an infinite size root box
            rootNodeBox = new JBBox(new JVector(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity),
                                           new JVector(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity));


            for (int i = 0; i < tris.Length; i++)
            {
                JVector.Min(ref positions[tris[i].I1], ref positions[tris[i].I2], out triBoxes[i].Min);
                JVector.Min(ref positions[tris[i].I0], ref triBoxes[i].Min, out triBoxes[i].Min);

                JVector.Max(ref positions[tris[i].I1], ref positions[tris[i].I2], out triBoxes[i].Max);
                JVector.Max(ref positions[tris[i].I0], ref triBoxes[i].Max, out triBoxes[i].Max);

                // get size of the root box
                JVector.Min(ref rootNodeBox.Min, ref triBoxes[i].Min, out rootNodeBox.Min);
                JVector.Max(ref rootNodeBox.Max, ref triBoxes[i].Max, out rootNodeBox.Max);
            }

            List<BuildNode> buildNodes = new List<BuildNode>();
            buildNodes.Add(new BuildNode());
            buildNodes[0].box = rootNodeBox;

            JBBox[] children = new JBBox[8];
            for (int triNum = 0; triNum < tris.Length; triNum++)
            {
                int nodeIndex = 0;
                JBBox box = rootNodeBox;

                while (box.Contains(ref triBoxes[triNum]) == JBBox.ContainmentType.Contains)
                {
                    int childCon = -1;
                    for (int i = 0; i < 8; ++i)
                    {
                        CreateAABox(ref box, (EChild)i,out children[i]);
                        if (children[i].Contains(ref triBoxes[triNum]) == JBBox.ContainmentType.Contains)
                        {
                            // this box contains the tri, it can be the only one that does,
                            // so we can stop our child search now and recurse into it
                            childCon = i;
                            break;
                        }
                    }

                    // no child contains this tri completely, so it belong in this node
                    if (childCon == -1)
                    {
                        buildNodes[nodeIndex].triIndices.Add(triNum);
                        break;
                    }
                    else
                    {
                        // do we already have this child
                        int childIndex = -1;
                        for (int index = 0; index < buildNodes[nodeIndex].nodeIndices.Count; ++index)
                        {
                            if (buildNodes[buildNodes[nodeIndex].nodeIndices[index]].childType == childCon)
                            {
                                childIndex = index;
                                break;
                            }
                        }
                        if (childIndex == -1)
                        {
                            // nope create child
                            BuildNode parentNode = buildNodes[nodeIndex];
                            BuildNode newNode = new BuildNode();
                            newNode.childType = childCon;
                            newNode.box = children[childCon];
                            buildNodes.Add(newNode);

                            nodeIndex = buildNodes.Count - 1;
                            box = children[childCon];
                            parentNode.nodeIndices.Add(nodeIndex);
                        }
                        else
                        {
                            nodeIndex = buildNodes[nodeIndex].nodeIndices[childIndex];
                            box = children[childCon];
                        }
                    }
                }
            }

            // now convert to the tighter Node from BuildNodes
            nodes = new Node[buildNodes.Count];
            nodeStackPool = new ArrayResourcePool<ushort>(buildNodes.Count);
            //nodeStack = new UInt16[buildNodes.Count];
            for (int i = 0; i < nodes.Length; i++)
            {
                nodes[i].nodeIndices = new UInt16[buildNodes[i].nodeIndices.Count];
                for (int index = 0; index < nodes[i].nodeIndices.Length; ++index)
                {
                    nodes[i].nodeIndices[index] = (UInt16)buildNodes[i].nodeIndices[index];
                }

                nodes[i].triIndices = new int[buildNodes[i].triIndices.Count];
                buildNodes[i].triIndices.CopyTo(nodes[i].triIndices);
                nodes[i].box = buildNodes[i].box;
            }
            buildNodes.Clear(); buildNodes = null;
        }
Exemple #14
0
        /// <summary>
        /// Gets the axis aligned bounding box of the orientated shape. (Inlcuding all
        /// 'sub' shapes)
        /// </summary>
        /// <param name="orientation">The orientation of the shape.</param>
        /// <param name="box">The axis aligned bounding box of the shape.</param>
        public override void GetBoundingBox(ref JMatrix orientation, out JBBox box)
        {
            box.Min = mInternalBBox.Min;
            box.Max = mInternalBBox.Max;

            JVector localHalfExtents = 0.5f * (box.Max - box.Min);
            JVector localCenter = 0.5f * (box.Max + box.Min);

            JVector center;
            JVector.Transform(ref localCenter, ref orientation, out center);

            JMatrix abs; JMath.Absolute(ref orientation, out abs);
            JVector temp;
            JVector.Transform(ref localHalfExtents, ref abs, out temp);

            box.Max = center + temp;
            box.Min = center - temp;
        }
            public void UpdateBoundingBox()
            {
                boundingBox = JBBox.SmallBox;
                boundingBox.AddPoint(ref owner.points[indices.I0].position);
                boundingBox.AddPoint(ref owner.points[indices.I1].position);
                boundingBox.AddPoint(ref owner.points[indices.I2].position);

                boundingBox.Min -= new JVector(owner.triangleExpansion);
                boundingBox.Max += new JVector(owner.triangleExpansion);
            }
Exemple #16
0
 /// <summary>
 /// Passes a axis aligned bounding box to the shape where collision
 /// could occour.
 /// </summary>
 /// <param name="box">The bounding box where collision could occur.</param>
 /// <returns>The upper index with which <see cref="SetCurrentShape"/> can be 
 /// called.</returns>
 public override int Prepare(ref JBBox box)
 {
     return shapes.Length;
 }
Exemple #17
0
 /// <summary>
 /// Creates a new box containing the two given ones.
 /// </summary>
 /// <param name="original">First box.</param>
 /// <param name="additional">Second box.</param>
 /// <param name="result">A JBBox containing the two given boxes.</param>
 public static void CreateMerged(ref JBBox original, ref JBBox additional, out JBBox result)
 {
     JVector vector;
     JVector vector2;
     JVector.Min(ref original.Min, ref additional.Min, out vector2);
     JVector.Max(ref original.Max, ref additional.Max, out vector);
     result.Min = vector2;
     result.Max = vector;
 }
Exemple #18
0
        /// <summary>
        /// Creates a new box containing the two given ones.
        /// </summary>
        /// <param name="original">First box.</param>
        /// <param name="additional">Second box.</param>
        /// <returns>A JBBox containing the two given boxes.</returns>
        #region public static JBBox CreateMerged(JBBox original, JBBox additional)

        public static JBBox CreateMerged(JBBox original, JBBox additional)
        {
            JBBox result;
            JBBox.CreateMerged(ref original, ref additional, out result);
            return result;
        }
Exemple #19
0
        /// <summary>
        /// Checks whether another bounding box is inside, outside or intersecting
        /// this box. 
        /// </summary>
        /// <param name="box">The other bounding box to check.</param>
        /// <returns>The ContainmentType of the box.</returns>
        public ContainmentType Contains(ref JBBox box)
        {
            ContainmentType result = ContainmentType.Disjoint;
            if ((((this.Max.X >= box.Min.X) && (this.Min.X <= box.Max.X)) && ((this.Max.Y >= box.Min.Y) && (this.Min.Y <= box.Max.Y))) && ((this.Max.Z >= box.Min.Z) && (this.Min.Z <= box.Max.Z)))
            {
                result = ((((this.Min.X <= box.Min.X) && (box.Max.X <= this.Max.X)) && ((this.Min.Y <= box.Min.Y) && (box.Max.Y <= this.Max.Y))) && ((this.Min.Z <= box.Min.Z) && (box.Max.Z <= this.Max.Z))) ? ContainmentType.Contains : ContainmentType.Intersects;
            }

            return result;
        }
Exemple #20
0
        /// <summary>
        /// Checks whether another bounding box is inside, outside or intersecting
        /// this box. 
        /// </summary>
        /// <param name="box">The other bounding box to check.</param>
        /// <returns>The ContainmentType of the box.</returns>
        #region public ContainmentType Contains(JBBox box)

        public ContainmentType Contains(JBBox box)
        {
            return this.Contains(ref box);
        }
        public virtual void Update(float timestep)
        {
            active = false;

            foreach (MassPoint point in points)
            {
                if (point.isActive && !point.isStatic) { active = true; break; }
            }

            if(!active) return;

            box = JBBox.SmallBox;
            volume = 0.0f;
            mass = 0.0f;

            foreach (MassPoint point in points)
            {
                mass += point.Mass;
                box.AddPoint(point.position);
            }

            box.Min -= new JVector(TriangleExpansion);
            box.Max += new JVector(TriangleExpansion);

            foreach (Triangle t in triangles)
            {
                // Update bounding box and move proxy in dynamic tree.
                JVector prevCenter = t.boundingBox.Center;
                t.UpdateBoundingBox();

                JVector linVel = t.VertexBody1.linearVelocity + 
                    t.VertexBody2.linearVelocity + 
                    t.VertexBody3.linearVelocity;

                linVel *= 1.0f / 3.0f;

                dynamicTree.MoveProxy(t.dynamicTreeID, ref t.boundingBox, linVel * timestep);

                JVector v1 = points[t.indices.I0].position;
                JVector v2 = points[t.indices.I1].position;
                JVector v3 = points[t.indices.I2].position;

                volume -= ((v2.Y - v1.Y) * (v3.Z - v1.Z) -
                    (v2.Z - v1.Z) * (v3.Y - v1.Y)) * (v1.X + v2.X + v3.X);
            }

            volume /= 6.0f;

            AddPressureForces(timestep);
        }
Exemple #22
0
        /// <summary>
        /// Gets the axis aligned bounding box of the orientated shape.
        /// </summary>
        /// <param name="orientation">The orientation of the shape.</param>
        /// <param name="box">The axis aligned bounding box of the shape.</param>
        public override void GetBoundingBox(ref JMatrix orientation, out JBBox box)
        {
            JMatrix abs; JMath.Absolute(ref orientation, out abs);
            JVector temp;
            JVector.Transform(ref halfSize, ref abs, out temp);

            box.Max = temp;
            JVector.Negate(ref temp, out box.Min);
        }