public void LoadModel(idTraceModel traceModel) { if (this.Disposed == true) { throw new ObjectDisposedException("idClipModel"); } _collisionModelHandle = 0; _renderModelHandle = -1; _traceModelCache = GetTraceModelCache(traceModel); _bounds = traceModel.Bounds; }
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)); }
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; }
private TraceModelCache GetTraceModelCache(idTraceModel model) { if (_traceModelCacheDict.ContainsKey(model) == true) { if (_traceModelCacheDict[model].IsAlive == true) { return((TraceModelCache)_traceModelCacheDict[model].Target); } _traceModelCacheDict.Remove(model); } TraceModelCache entry = new TraceModelCache(); entry.TraceModel = model; entry.TraceModel.GetMassProperties(1.0f, out entry.Volume, out entry.CenterOfMass, out entry.InertiaTensor); WeakReference weakRef = new WeakReference(entry); _traceModelCacheDict.Add(model, weakRef); return(entry); }
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 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); }
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; }
public void LoadModel(idTraceModel traceModel) { if(this.Disposed == true) { throw new ObjectDisposedException("idClipModel"); } _collisionModelHandle = 0; _renderModelHandle = -1; _traceModelCache = GetTraceModelCache(traceModel); _bounds = traceModel.Bounds; }
private TraceModelCache GetTraceModelCache(idTraceModel model) { if(_traceModelCacheDict.ContainsKey(model) == true) { if(_traceModelCacheDict[model].IsAlive == true) { return (TraceModelCache) _traceModelCacheDict[model].Target; } _traceModelCacheDict.Remove(model); } TraceModelCache entry = new TraceModelCache(); entry.TraceModel = model; entry.TraceModel.GetMassProperties(1.0f, out entry.Volume, out entry.CenterOfMass, out entry.InertiaTensor); WeakReference weakRef = new WeakReference(entry); _traceModelCacheDict.Add(model, weakRef); return entry; }
public idClipModel(idTraceModel traceModel) { Init(); LoadModel(traceModel); }
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); }