A trace model is an arbitrary polygonal model which is used by the collision detection system to find collisions, contacts or the contents of a volume. For collision detection speed reasons the number of vertices and edges are limited. The trace model can have any shape. However convex models are usually preferred.
예제 #1
0
        public idTraceModel Copy()
        {
            idTraceModel traceModel = new idTraceModel();

            traceModel._type   = _type;
            traceModel._bounds = _bounds;
            traceModel._offset = _offset;
            traceModel._edges  = (TraceModelEdge[])_edges.Clone();

            traceModel._polygons = (TraceModelPolygon[])_polygons.Clone();
            traceModel._vertices = (Vector3[])_vertices.Clone();

            traceModel._isConvex = _isConvex;

            return(traceModel);
        }
예제 #2
0
        public void GetMassProperties(float density, out float mass, out Vector3 centerOfMass, out Matrix inertiaTensor)
        {
            inertiaTensor = Matrix.Identity;

            // if polygon trace model
            if (_type == TraceModelType.Polygon)
            {
                idTraceModel traceModel = VolumeFromPolygon(1.0f);
                traceModel.GetMassProperties(density, out mass, out centerOfMass, out inertiaTensor);
            }
            else
            {
                VolumeIntegrals integrals = GetVolumeIntegrals();

                // if no volume
                if (integrals.T0 == 0.0f)
                {
                    mass          = 1.0f;
                    centerOfMass  = Vector3.Zero;
                    inertiaTensor = Matrix.Identity;
                }
                else
                {
                    // mass of model
                    mass = density * integrals.T0;

                    // center of mass
                    centerOfMass = integrals.T1 / integrals.T0;

                    // compute inertia tensor
                    inertiaTensor.M11 = density * (integrals.T2.Y + integrals.T2.Z);
                    inertiaTensor.M22 = density * (integrals.T2.Z + integrals.T2.X);
                    inertiaTensor.M33 = density * (integrals.T2.X + integrals.T2.Y);
                    inertiaTensor.M12 = inertiaTensor.M21 = -density * integrals.TP.X;
                    inertiaTensor.M23 = inertiaTensor.M32 = -density * integrals.TP.Y;
                    inertiaTensor.M31 = inertiaTensor.M13 = -density * integrals.TP.Z;

                    // translate inertia tensor to center of mass
                    inertiaTensor.M11 -= mass * (centerOfMass.Y * centerOfMass.Y + centerOfMass.Z * centerOfMass.Z);
                    inertiaTensor.M22 -= mass * (centerOfMass.Z * centerOfMass.Z + centerOfMass.X * centerOfMass.X);
                    inertiaTensor.M33 -= mass * (centerOfMass.X * centerOfMass.X + centerOfMass.Y * centerOfMass.Y);
                    inertiaTensor.M12  = inertiaTensor.M21 += mass * centerOfMass.X * centerOfMass.Y;
                    inertiaTensor.M23  = inertiaTensor.M32 += mass * centerOfMass.Y * centerOfMass.Z;
                    inertiaTensor.M31  = inertiaTensor.M13 += mass * centerOfMass.Z * centerOfMass.X;
                }
            }
        }
예제 #3
0
        private idTraceModel VolumeFromPolygon(float thickness)
        {
            idTraceModel traceModel = this.Copy();

            traceModel._type     = TraceModelType.PolygonVolume;
            traceModel._vertices = new Vector3[_vertices.Length * 2];
            traceModel._edges    = new TraceModelEdge[_edges.Length * 3];
            traceModel._polygons = new TraceModelPolygon[_edges.Length + 2];

            int edgeCount = _edges.Length;
            int vertCount = _vertices.Length;

            for (int i = 0; i < edgeCount; i++)
            {
                traceModel._vertices[vertCount + i] = _vertices[i] - thickness * _polygons[0].Normal;

                traceModel._edges[edgeCount + i + 1].V[0]     = vertCount + i;
                traceModel._edges[edgeCount + i + 1].V[1]     = vertCount + (i + 1) % vertCount;
                traceModel._edges[edgeCount * 2 + i + 1].V[0] = i;
                traceModel._edges[edgeCount * 2 + i + 1].V[1] = vertCount + i;

                traceModel._polygons[1].Edges[i]     = -(edgeCount + i + 1);
                traceModel._polygons[2 + i].Edges    = new int[4];
                traceModel._polygons[2 + i].Edges[0] = -(i + 1);
                traceModel._polygons[2 + i].Edges[1] = edgeCount * 2 + i + 1;
                traceModel._polygons[2 + i].Edges[2] = edgeCount + i + 1;
                traceModel._polygons[2 + i].Edges[3] = -(edgeCount * 2 + (i + 1) % edgeCount + 1);
                traceModel._polygons[2 + i].Normal   = Vector3.Cross(_vertices[(i + 1) % vertCount] - _vertices[i], _polygons[0].Normal);
                traceModel._polygons[2 + i].Normal.Normalize();
                traceModel._polygons[2 + i].Distance = (traceModel._polygons[2 + i].Normal * _vertices[i]).Length();
            }

            traceModel._polygons[1].Distance = (traceModel._polygons[1].Normal * traceModel._vertices[edgeCount]).Length();
            traceModel.GenerateEdgeNormals();

            return(traceModel);
        }
예제 #4
0
        public bool Equals(idTraceModel traceModel)
        {
            if ((this._type != traceModel._type) ||
                (this._vertices.Length != traceModel._vertices.Length) ||
                (this._edges.Length != traceModel._edges.Length) ||
                (this._polygons.Length != traceModel._polygons.Length))
            {
                return(false);
            }

            if ((_bounds != traceModel._bounds) ||
                (_offset != traceModel._offset))
            {
                return(false);
            }

            switch (_type)
            {
            case TraceModelType.Bone:
            case TraceModelType.Polygon:
            case TraceModelType.PolygonVolume:
            case TraceModelType.Custom:
                int vertexCount = traceModel._vertices.Length;

                for (int i = 0; i < vertexCount; i++)
                {
                    if ((i >= _vertices.Length) || (_vertices[i] != traceModel._vertices[i]))
                    {
                        return(false);
                    }
                }
                break;
            }

            return(true);
        }
예제 #5
0
		private void InitDefaultPhysics(Vector3 origin, Matrix axis)
		{
			string temp = _spawnArgs.GetString("clipmodel", "");
			idClipModel clipModel = null;

			// check if a clipmodel key/value pair is set
			if(temp != string.Empty)
			{
				if(idClipModel.CheckModel(temp) != null)
				{
					clipModel = new idClipModel(temp);
				}
			}

			if(_spawnArgs.GetBool("noclipmodel", false) == false)
			{
				// check if mins/maxs or size key/value pairs are set
				if(clipModel == null)
				{
					idBounds bounds = idBounds.Zero;
					bool setClipModel = false;

					if((_spawnArgs.ContainsKey("mins") == true)
						&& (_spawnArgs.ContainsKey("maxs") == true))
					{
						bounds = new idBounds(_spawnArgs.GetVector3("mins"), _spawnArgs.GetVector3("maxs"));
						setClipModel = true;

						if((bounds.Min.X > bounds.Max.X)
							|| (bounds.Min.Y > bounds.Max.Y)
							|| (bounds.Min.Z > bounds.Max.Z))
						{
							idConsole.Error("Invalid bounds '{0}'-'{1}' on entity '{2}'", bounds.Min, bounds.Max, this.Name);
						}
					}
					else if(_spawnArgs.ContainsKey("size") == true)
					{
						Vector3 size = _spawnArgs.GetVector3("size");

						if((size.X < 0.0f)
							|| (size.Y < 0.0f)
							|| (size.Z < 0.0f))
						{
							idConsole.Error("Invalid size '{0}' on entity '{1}'", size, this.Name);
						}

						setClipModel = true;
						bounds = new idBounds(
									new Vector3(size.X * -0.5f, size.Y * -0.5f, 0.0f),
									new Vector3(size.X * 0.5f, size.Y * 0.5f, size.Z)
								);
					}

					if(setClipModel == true)
					{
						int sideCount = _spawnArgs.GetInteger("cyclinder", 0);

						idTraceModel traceModel = new idTraceModel();

						if(sideCount > 0)
						{
							idConsole.Warning("TODO: traceModel.SetupCyclinder(bounds, (sideCount < 3) ? 3 : sideCount);");
						}
						else if((sideCount = _spawnArgs.GetInteger("cone", 0)) > 0)
						{
							idConsole.Warning("TODO: traceModel.SetupCone(bounds, (sideCount < 3) ? 3 : sideCount);");
						}
						else
						{
							traceModel.SetupBox(bounds);
						}

						clipModel = new idClipModel(traceModel);
					}
				}

				// check if the visual model can be used as collision model
				if(clipModel == null)
				{
					temp = _spawnArgs.GetString("model");

					if(temp != string.Empty)
					{
						if(idClipModel.CheckModel(temp) != null)
						{
							clipModel = new idClipModel(temp);
						}
					}
				}
			}

			_defaultPhysicsObject.Self = this;
			_defaultPhysicsObject.SetClipModel(clipModel, 1.0f);
			_defaultPhysicsObject.SetOrigin(origin);
			_defaultPhysicsObject.SetAxis(axis);

			_physics = _defaultPhysicsObject;
		}
예제 #6
0
		public bool Equals(idTraceModel traceModel)
		{
			if((this._type != traceModel._type) 
				|| (this._vertices.Length != traceModel._vertices.Length)
				|| (this._edges.Length != traceModel._edges.Length)
				|| (this._polygons.Length != traceModel._polygons.Length))
			{
				return false;
			}

			if((_bounds != traceModel._bounds)
				|| (_offset != traceModel._offset))
			{
				return false;
			}

			switch(_type)
			{
				case TraceModelType.Bone:
				case TraceModelType.Polygon:
				case TraceModelType.PolygonVolume:
				case TraceModelType.Custom:
					int vertexCount = traceModel._vertices.Length;

					for(int i = 0; i < vertexCount; i++)
					{
						if((i >= _vertices.Length) || (_vertices[i] != traceModel._vertices[i]))
						{
							return false;
						}
					}
					break;
			}

			return true;
		}
예제 #7
0
		public idTraceModel Copy()
		{
			idTraceModel traceModel = new idTraceModel();
			traceModel._type = _type;
			traceModel._bounds = _bounds;
			traceModel._offset = _offset;
			traceModel._edges = (TraceModelEdge[]) _edges.Clone();

			traceModel._polygons = (TraceModelPolygon[]) _polygons.Clone();
			traceModel._vertices = (Vector3[]) _vertices.Clone();

			traceModel._isConvex = _isConvex;

			return traceModel;
		}