예제 #1
0
        int TransformedPointContents(ref idVec3 p, CmHandle model, ref idVec3 origin, ref idMat3 modelAxis)
        {
            // subtract origin offset
            idVec3 p_l = p - origin;

            if (modelAxis.IsRotated())
            {
                p_l *= modelAxis;
            }
            return(PointContents(p_l, model));
        }
 public int Contacts(ContactInfo contacts, int maxContacts, ref idVec3 start, ref idVec6 dir, float depth, idTraceModel trm, ref idMat3 trmAxis, int contentMask, CmHandle model, ref idVec3 origin, ref idMat3 modelAxis)
 {
     // same as Translation but instead of storing the first collision we store all collisions as contacts
     this.getContacts = true;
     this.contacts = contacts;
     this.maxContacts = maxContacts;
     this.numContacts = 0;
     idVec3 end = start + dir.SubVec3(0) * depth;
     Trace results;
     Translation(out results, start, end, trm, trmAxis, contentMask, model, origin, modelAxis);
     if (dir.SubVec3(1).LengthSqr() != 0.0f)
     { 
         // FIXME: rotational contacts 
     }
     this.getContacts = false;
     this.maxContacts = 0;
     return this.numContacts;
 }
 int Contents(ref idVec3 start, idTraceModel trm, ref idMat3 trmAxis, int contentMask, CmHandle model, ref idVec3 modelOrigin, ref idMat3 modelAxis)
 {
     if (model < 0 || model > this.maxModels || model > MAX_SUBMODELS)
     {
         common.Printf("CollisionModelManager::Contents: invalid model handle\n");
         return 0;
     }
     if (this.models == null || this.models[model] == null)
     {
         common.Printf("CollisionModelManager::Contents: invalid model\n");
         return 0;
     }
     Trace results;
     return ContentsTrm(out results, start, trm, trmAxis, contentMask, model, modelOrigin, modelAxis);
 }
        int ContentsTrm(Trace results, ref idVec3 start, idTraceModel trm, ref idMat3 trmAxis, int contentMask, CmHandle model, ref idVec3 modelOrigin, ref idMat3 modelAxis)
        {
            // fast point case
            if (!trm || (trm.bounds[1][0] - trm.bounds[0][0] <= 0.0f &&
                            trm.bounds[1][1] - trm.bounds[0][1] <= 0.0f &&
                            trm.bounds[1][2] - trm.bounds[0][2] <= 0.0f))
            {
                results.c.contents = TransformedPointContents(start, model, modelOrigin, modelAxis);
                results.fraction = (results.c.contents == 0);
                results.endpos = start;
                results.endAxis = trmAxis;
                return results.c.contents;
            }

            this.checkCount++;

            TraceWork tw = new TraceWork();
            tw.trace.fraction = 1.0f;
            tw.trace.c.contents = 0;
            tw.trace.c.type = ContactType.CONTACT_NONE;
            tw.contents = contentMask;
            tw.isConvex = true;
            tw.rotation = false;
            tw.positionTest = true;
            tw.pointTrace = false;
            tw.quickExit = false;
            tw.numContacts = 0;
            tw.model = this.models[(int)model];
            tw.start = start - modelOrigin;
            tw.end = tw.start;

            bool model_rotated = modelAxis.IsRotated();
            if (model_rotated)
                invModelAxis = modelAxis.Transpose();

            // setup trm structure
            SetupTrm(ref tw, trm);

            bool trm_rotated = trmAxis.IsRotated();

            // calculate vertex positions
            if (trm_rotated)
                for (int i = 0; i < tw.numVerts; i++)
                    // rotate trm around the start position
                    tw.vertices[i].p *= trmAxis;
            for (int i = 0; i < tw.numVerts; i++)
                // set trm at start position
                tw.vertices[i].p += tw.start;
            if (model_rotated)
                for (int i = 0; i < tw.numVerts; i++)
                    // rotate trm around model instead of rotating the model
                    tw.vertices[i].p *= invModelAxis;

            // add offset to start point
            if (trm_rotated)
            {
                idVec3 dir = trm->offset * trmAxis;
                tw.start += dir;
                tw.end += dir;
            }
            else
            {
                tw.start += trm->offset;
                tw.end += trm->offset;
            }
            if (model_rotated)
            {
                // rotate trace instead of model
                tw.start *= invModelAxis;
                tw.end *= invModelAxis;
            }

            // setup trm vertices
            tw.size.Clear();
            for (int i = 0; i < tw.numVerts; i++)
                // get axial trm size after rotations
                tw.size.AddPoint(tw.vertices[i].p - tw.start);

            // setup trm edges
            for (int i = 1; i <= tw.numEdges; i++)
            {
                // edge start, end and pluecker coordinate
                tw.edges[i].start = tw.vertices[tw.edges[i].vertexNum[0]].p;
                tw.edges[i].end = tw.vertices[tw.edges[i].vertexNum[1]].p;
                tw.edges[i].pl.FromLine(tw.edges[i].start, tw.edges[i].end);
            }

            // setup trm polygons
            if (trm_rotated & model_rotated)
            {
                idMat3 tmpAxis = trmAxis * invModelAxis;
                for (int i = 0; i < tw.numPolys; i++)
                    tw.polys[i].plane *= tmpAxis;
            }
            else if (trm_rotated)
            {
                for (int i = 0; i < tw.numPolys; i++)
                    tw.polys[i].plane *= trmAxis;
            }
            else if (model_rotated)
            {
                for (int i = 0; i < tw.numPolys; i++)
                    tw.polys[i].plane *= invModelAxis;
            }
            for (int i = 0; i < tw.numPolys; i++)
                tw.polys[i].plane.FitThroughPoint(tw.edges[abs(tw.polys[i].edges[0])].start);

            // bounds for full trace, a little bit larger for epsilons
            for (int i = 0; i < 3; i++)
            {
                if (tw.start[i] < tw.end[i])
                {
                    tw.bounds[0][i] = tw.start[i] + tw.size[0][i] - CM_BOX_EPSILON;
                    tw.bounds[1][i] = tw.end[i] + tw.size[1][i] + CM_BOX_EPSILON;
                }
                else
                {
                    tw.bounds[0][i] = tw.end[i] + tw.size[0][i] - CM_BOX_EPSILON;
                    tw.bounds[1][i] = tw.start[i] + tw.size[1][i] + CM_BOX_EPSILON;
                }
                if (idMath.Fabs(tw.size[0][i]) > idMath.Fabs(tw.size[1][i]))
                    tw.extents[i] = idMath.Fabs(tw.size[0][i]) + CM_BOX_EPSILON;
                else
                    tw.extents[i] = idMath.Fabs(tw.size[1][i]) + CM_BOX_EPSILON;
            }

            // trace through the model
            TraceThroughModel(ref tw);

            results = tw.trace;
            results.fraction = (results.c.contents == 0);
            results.endpos = start;
            results.endAxis = trmAxis;
            return results.c.contents;
        }
 int TransformedPointContents(ref idVec3 p, CmHandle model, ref idVec3 origin, ref idMat3 modelAxis)
 {
     // subtract origin offset
     idVec3 p_l = p - origin;
     if (modelAxis.IsRotated())
         p_l *= modelAxis;
     return PointContents(p_l, model);
 }
예제 #6
0
        int ContentsTrm(Trace results, ref idVec3 start, idTraceModel trm, ref idMat3 trmAxis, int contentMask, CmHandle model, ref idVec3 modelOrigin, ref idMat3 modelAxis)
        {
            // fast point case
            if (!trm || (trm.bounds[1][0] - trm.bounds[0][0] <= 0.0f &&
                         trm.bounds[1][1] - trm.bounds[0][1] <= 0.0f &&
                         trm.bounds[1][2] - trm.bounds[0][2] <= 0.0f))
            {
                results.c.contents = TransformedPointContents(start, model, modelOrigin, modelAxis);
                results.fraction   = (results.c.contents == 0);
                results.endpos     = start;
                results.endAxis    = trmAxis;
                return(results.c.contents);
            }

            this.checkCount++;

            TraceWork tw = new TraceWork();

            tw.trace.fraction   = 1.0f;
            tw.trace.c.contents = 0;
            tw.trace.c.type     = ContactType.CONTACT_NONE;
            tw.contents         = contentMask;
            tw.isConvex         = true;
            tw.rotation         = false;
            tw.positionTest     = true;
            tw.pointTrace       = false;
            tw.quickExit        = false;
            tw.numContacts      = 0;
            tw.model            = this.models[(int)model];
            tw.start            = start - modelOrigin;
            tw.end = tw.start;

            bool model_rotated = modelAxis.IsRotated();

            if (model_rotated)
            {
                invModelAxis = modelAxis.Transpose();
            }

            // setup trm structure
            SetupTrm(ref tw, trm);

            bool trm_rotated = trmAxis.IsRotated();

            // calculate vertex positions
            if (trm_rotated)
            {
                for (int i = 0; i < tw.numVerts; i++)
                {
                    // rotate trm around the start position
                    tw.vertices[i].p *= trmAxis;
                }
            }
            for (int i = 0; i < tw.numVerts; i++)
            {
                // set trm at start position
                tw.vertices[i].p += tw.start;
            }
            if (model_rotated)
            {
                for (int i = 0; i < tw.numVerts; i++)
                {
                    // rotate trm around model instead of rotating the model
                    tw.vertices[i].p *= invModelAxis;
                }
            }

            // add offset to start point
            if (trm_rotated)
            {
                idVec3 dir = trm->offset * trmAxis;
                tw.start += dir;
                tw.end   += dir;
            }
            else
            {
                tw.start += trm->offset;
                tw.end   += trm->offset;
            }
            if (model_rotated)
            {
                // rotate trace instead of model
                tw.start *= invModelAxis;
                tw.end   *= invModelAxis;
            }

            // setup trm vertices
            tw.size.Clear();
            for (int i = 0; i < tw.numVerts; i++)
            {
                // get axial trm size after rotations
                tw.size.AddPoint(tw.vertices[i].p - tw.start);
            }

            // setup trm edges
            for (int i = 1; i <= tw.numEdges; i++)
            {
                // edge start, end and pluecker coordinate
                tw.edges[i].start = tw.vertices[tw.edges[i].vertexNum[0]].p;
                tw.edges[i].end   = tw.vertices[tw.edges[i].vertexNum[1]].p;
                tw.edges[i].pl.FromLine(tw.edges[i].start, tw.edges[i].end);
            }

            // setup trm polygons
            if (trm_rotated & model_rotated)
            {
                idMat3 tmpAxis = trmAxis * invModelAxis;
                for (int i = 0; i < tw.numPolys; i++)
                {
                    tw.polys[i].plane *= tmpAxis;
                }
            }
            else if (trm_rotated)
            {
                for (int i = 0; i < tw.numPolys; i++)
                {
                    tw.polys[i].plane *= trmAxis;
                }
            }
            else if (model_rotated)
            {
                for (int i = 0; i < tw.numPolys; i++)
                {
                    tw.polys[i].plane *= invModelAxis;
                }
            }
            for (int i = 0; i < tw.numPolys; i++)
            {
                tw.polys[i].plane.FitThroughPoint(tw.edges[abs(tw.polys[i].edges[0])].start);
            }

            // bounds for full trace, a little bit larger for epsilons
            for (int i = 0; i < 3; i++)
            {
                if (tw.start[i] < tw.end[i])
                {
                    tw.bounds[0][i] = tw.start[i] + tw.size[0][i] - CM_BOX_EPSILON;
                    tw.bounds[1][i] = tw.end[i] + tw.size[1][i] + CM_BOX_EPSILON;
                }
                else
                {
                    tw.bounds[0][i] = tw.end[i] + tw.size[0][i] - CM_BOX_EPSILON;
                    tw.bounds[1][i] = tw.start[i] + tw.size[1][i] + CM_BOX_EPSILON;
                }
                if (idMath.Fabs(tw.size[0][i]) > idMath.Fabs(tw.size[1][i]))
                {
                    tw.extents[i] = idMath.Fabs(tw.size[0][i]) + CM_BOX_EPSILON;
                }
                else
                {
                    tw.extents[i] = idMath.Fabs(tw.size[1][i]) + CM_BOX_EPSILON;
                }
            }

            // trace through the model
            TraceThroughModel(ref tw);

            results          = tw.trace;
            results.fraction = (results.c.contents == 0);
            results.endpos   = start;
            results.endAxis  = trmAxis;
            return(results.c.contents);
        }
        public int Contacts(ContactInfo contacts, int maxContacts, ref idVec3 start, ref idVec6 dir, float depth, idTraceModel trm, ref idMat3 trmAxis, int contentMask, CmHandle model, ref idVec3 origin, ref idMat3 modelAxis)
        {
            // same as Translation but instead of storing the first collision we store all collisions as contacts
            this.getContacts = true;
            this.contacts    = contacts;
            this.maxContacts = maxContacts;
            this.numContacts = 0;
            idVec3 end = start + dir.SubVec3(0) * depth;
            Trace  results;

            Translation(out results, start, end, trm, trmAxis, contentMask, model, origin, modelAxis);
            if (dir.SubVec3(1).LengthSqr() != 0.0f)
            {
                // FIXME: rotational contacts
            }
            this.getContacts = false;
            this.maxContacts = 0;
            return(this.numContacts);
        }