private void GetNodeBounds_R(ref idBounds bounds, CollisionModelNode node) { while (true) { foreach (CollisionModelPolygon poly in node.Polygons) { bounds.AddPoint(poly.Bounds.Min); bounds.AddPoint(poly.Bounds.Max); } foreach (CollisionModelBrush brush in node.Brushes) { bounds.AddPoint(brush.Bounds.Min); bounds.AddPoint(brush.Bounds.Max); } if (node.PlaneType == -1) { break; } GetNodeBounds_R(ref bounds, node.Children[1]); node = node.Children[0]; } }
public void Link(idClip clip, idEntity entity, int newID, Vector3 newOrigin, Matrix newAxis, int renderModelHandle) { if (this.Disposed == true) { throw new ObjectDisposedException("idClipModel"); } _entity = entity; _id = newID; _origin = newOrigin; _axis = newAxis; if (_renderModelHandle != -1) { _renderModelHandle = renderModelHandle; RenderEntityComponent renderEntity = idR.Game.RenderWorld.GetRenderEntity(renderModelHandle); if (renderEntity != null) { _bounds = renderEntity.Bounds; } } Link(clip); }
public idClipModel(idClipModel model) { _id = model.ID; _owner = model.Owner; _enabled = model.Enabled; _entity = model.Entity; _origin = model.Origin; _axis = model.Axis; _bounds = model.Bounds; _absBounds = model.AbsoluteBounds; _material = model.Material; _contents = model.Contents; _collisionModelHandle = model.CollisionModelHandle; _traceModelCache = null; if (model.TraceModelCache != null) { idConsole.Warning("TODO: LoadModel( *GetCachedTraceModel( model->traceModelIndex ) );"); } _renderModelHandle = model.RenderModelHandle; _touchCount = -1; }
private bool InsideAllChildren(CollisionModelNode node, idBounds bounds) { if (node.PlaneType != -1) { float v = (node.PlaneType == 0) ? bounds.Min.X : (node.PlaneType == 1) ? bounds.Min.Y : bounds.Min.Z; float v2 = (node.PlaneType == 0) ? bounds.Max.X : (node.PlaneType == 1) ? bounds.Max.Y : bounds.Max.Z; if (v >= node.PlaneDistance) { return(false); } else if (v2 <= node.PlaneDistance) { return(false); } else if (InsideAllChildren(node.Children[0], bounds) == false) { return(false); } else if (InsideAllChildren(node.Children[1], bounds) == false) { return(false); } } return(true); }
/// <summary> /// Builds a uniformly subdivided tree for the given world size. /// </summary> /// <param name="depth"></param> /// <param name="bounds"></param> /// <param name="?"></param> /// <returns></returns> private ClipSector CreateClipSectors(int depth, idBounds bounds, ref Vector3 maxSector) { idBounds front, back; ClipSector anode = _clipSectors[_clipSectorCount] = new ClipSector(); _clipSectorCount++; if (depth == idClip.MaxSectorDepth) { anode.Axis = -1; anode.Children[0] = anode.Children[1] = null; if ((bounds.Max.X - bounds.Min.X) > maxSector.X) { maxSector.X = bounds.Max.X - bounds.Min.X; } if ((bounds.Max.Y - bounds.Min.Y) > maxSector.Y) { maxSector.Y = bounds.Max.Y - bounds.Min.Y; } if ((bounds.Max.Z - bounds.Min.Z) > maxSector.Z) { maxSector.Z = bounds.Max.Z - bounds.Min.Z; } return(anode); } Vector3 size = bounds.Max - bounds.Min; front = bounds; back = bounds; if ((size.X >= size.Y) && (size.X >= size.Z)) { anode.Axis = 0; anode.Distance = 0.5f * (bounds.Max.X + bounds.Min.X); front.Min.X = back.Max.X = anode.Distance; } else if ((size.Y >= size.X) && (size.Y >= size.Z)) { anode.Axis = 1; anode.Distance = 0.5f * (bounds.Max.Y + bounds.Min.Y); front.Min.Y = back.Max.Y = anode.Distance; } else { anode.Axis = 2; anode.Distance = 0.5f * (bounds.Max.Z + bounds.Min.Z); front.Min.Z = back.Max.Z = anode.Distance; } anode.Children[0] = CreateClipSectors(depth + 1, front, ref maxSector); anode.Children[1] = CreateClipSectors(depth + 1, back, ref maxSector); return(anode); }
public idTraceModel() { _type = TraceModelType.Invalid; _bounds = idBounds.Zero; _edges = new TraceModelEdge[0]; _polygons = new TraceModelPolygon[0]; _vertices = new Vector3[0]; }
public virtual void SetClipBox(idBounds bounds, float density) { if (this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } SetClipModel(new idClipModel(new idTraceModel(bounds)), density); }
public idBounds CalculateBounds(idJointMatrix[] joints) { Vertex[] verts = new Vertex[_texCoords.Length]; idBounds bounds = idBounds.Zero; TransformVertices(verts, joints); idHelper.MinMax(ref bounds.Min, ref bounds.Max, verts, _texCoords.Length); return(bounds); }
public bool GetBounds(out idBounds bounds, int animNumber, int currentTime, int cycleCount) { if (_anims[animNumber] == null) { bounds = idBounds.Zero; return(false); } bounds = _anims[animNumber].GetBounds(currentTime, cycleCount); return(true); }
public void LoadModel(idTraceModel traceModel) { if (this.Disposed == true) { throw new ObjectDisposedException("idClipModel"); } _collisionModelHandle = 0; _renderModelHandle = -1; _traceModelCache = GetTraceModelCache(traceModel); _bounds = traceModel.Bounds; }
public override void AddSurface(RenderModelSurface surface) { if (this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } _surfaces.Add(surface); if (surface.Geometry != null) { _bounds += surface.Geometry.Bounds; } }
private idBounds GetNodeBounds(CollisionModelNode node) { idBounds bounds = idBounds.Zero; bounds.Clear(); GetNodeBounds_R(ref bounds, node); if (bounds.IsCleared == true) { bounds = idBounds.Zero; } return(bounds); }
public void SetupJoints(idJointMatrix[] joints, ref idBounds frameBounds, bool removeOriginOffset) { if (this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } if ((_model == null) || (_model.IsDefault == true)) { joints = null; frameBounds.Clear(); } // get the number of joints int count = _model.JointCount; if (count == 0) { idConsole.Error("model '{0}' has no joints", _model.Name); } // set up initial pose for model (with no pose, model is just a jumbled mess) joints = new idJointMatrix[count]; idJointQuaternion[] pose = this.DefaultPose; // convert the joint quaternions to joint matrices idHelper.ConvertJointQuaternionsToJointMatrices(joints, pose); // check if we offset the model by the origin joint if (removeOriginOffset == true) { #if VELOCITY_MOVE joints[0].Translation(new Vector3(_offset.X, _offset.Y + pose[0].Translation.Y, _offset.Z + pose[0].Translation.Z)); #else joints[0].Translation = _offset; #endif } else { joints[0].Translation = pose[0].Translation + _offset; } // transform the joint hierarchy idHelper.TransformJoints(joints, _jointParents, 1, joints.Length - 1); // get the bounds of the default pose frameBounds = _model.GetBounds(null); }
public void SetupBox(idBounds bounds) { if (_type != TraceModelType.Box) { InitBox(); } // offset to center _offset = (bounds.Min + bounds.Max) * 0.5f; // set box vertices _vertices = new Vector3[8]; for (int i = 0; i < 8; i++) { _vertices[i] = new Vector3( ((i ^ (i >> 1)) == 0) ? bounds.Min.X : bounds.Max.X, (((i >> 1) & 1) == 0) ? bounds.Min.Y : bounds.Max.Y, (((i >> 2) & 1) == 0) ? bounds.Min.Z : bounds.Max.Z ); } // set polygon plane distances _polygons = new TraceModelPolygon[6]; _polygons[0].Distance = -_bounds.Min.Z; _polygons[1].Distance = bounds.Max.Z; _polygons[2].Distance = -bounds.Min.Y; _polygons[3].Distance = bounds.Max.X; _polygons[4].Distance = bounds.Max.Y; _polygons[5].Distance = -bounds.Min.X; // set polygon bounds for (int i = 0; i < 6; i++) { _polygons[i].Bounds = bounds; _polygons[i].Edges = new int[0]; } _polygons[0].Bounds.Max.Z = bounds.Min.Z; _polygons[1].Bounds.Min.Z = bounds.Max.Z; _polygons[2].Bounds.Max.Y = bounds.Min.Y; _polygons[3].Bounds.Min.X = bounds.Max.X; _polygons[4].Bounds.Min.Y = bounds.Max.Y; _polygons[5].Bounds.Max.X = bounds.Min.X; _bounds = bounds; }
public bool AddBounds(int currentTime, ref idBounds bounds, bool removeOriginOffset) { if((_endTime > 0) && (currentTime > _endTime)) { return false; } idAnim anim = GetAnimation(); if(anim == null) { return false; } float weight = GetWeight(currentTime); if(weight == 0) { return false; } int time = GetAnimationTime(currentTime); int animCount = anim.AnimationCount; bool addOrigin = (_allowMove == false) || (removeOriginOffset == false); idBounds b; Vector3 pos; for(int i = 0; i < animCount; i++) { if(anim.GetBounds(out b, i, time, _cycle) == true) { if(addOrigin == true) { anim.GetOrigin(out pos, i, time, _cycle); b.Translate(pos); } bounds.AddBounds(b); } } return true; }
public bool AddBounds(int currentTime, ref idBounds bounds, bool removeOriginOffset) { if ((_endTime > 0) && (currentTime > _endTime)) { return(false); } idAnim anim = GetAnimation(); if (anim == null) { return(false); } float weight = GetWeight(currentTime); if (weight == 0) { return(false); } int time = GetAnimationTime(currentTime); int animCount = anim.AnimationCount; bool addOrigin = (_allowMove == false) || (removeOriginOffset == false); idBounds b; Vector3 pos; for (int i = 0; i < animCount; i++) { if (anim.GetBounds(out b, i, time, _cycle) == true) { if (addOrigin == true) { anim.GetOrigin(out pos, i, time, _cycle); b.Translate(pos); } bounds.AddBounds(b); } } return(true); }
/// <summary> /// /// </summary> /// <remarks>Must have been linked with an entity and ID before.</remarks> /// <param name="clip"></param> public void Link(idClip clip) { if (this.Disposed == true) { throw new ObjectDisposedException("idClipModel"); } if (_entity == null) { return; } if (_clipLinks != null) { Unlink(); // unlink from old position. } if (_bounds.IsCleared == true) { return; } // set the abs box if (_axis != Matrix.Identity) { // expand for rotation _absBounds = idBounds.FromTransformedBounds(_bounds, _origin, _axis); } else { // normal _absBounds.Min = _bounds.Min + _origin; _absBounds.Max = _bounds.Max + _origin; } // because movement is clipped an epsilon away from an actual edge, // we must fully check even when bounding boxes don't quite touch _absBounds.Min -= new Vector3(BoxEpsilon, BoxEpsilon, BoxEpsilon); _absBounds.Max += new Vector3(BoxEpsilon, BoxEpsilon, BoxEpsilon); // TODO: this may not be correct! from what I can gleam it just starts at the start of the array LinkSectors(clip.Sectors[0]); }
/// <summary> /// /// </summary> /// <remarks> /// an ent will be excluded from testing if: /// cm->entity == passEntity (don't clip against the pass entity) /// cm->entity == passOwner (missiles don't clip with owner) /// cm->owner == passEntity (don't interact with your own missiles) /// cm->owner == passOwner (don't interact with other missiles from same owner) /// </remarks> /// <param name="bounds"></param> /// <param name="contentMask"></param> /// <param name="passEntity"></param> /// <returns></returns> private idClipModel[] GetTraceClipModels(idBounds bounds, ContentFlags contentMask, idEntity passEntity) { idConsole.Warning("TODO: idClip.GetTraceClipModels"); // TODO /*int i, num; * idClipModel *cm; * idEntity *passOwner; * * num = ClipModelsTouchingBounds( bounds, contentMask, clipModelList, MAX_GENTITIES ); * * if ( !passEntity ) { * return num; * } * * if ( passEntity->GetPhysics()->GetNumClipModels() > 0 ) { * passOwner = passEntity->GetPhysics()->GetClipModel()->GetOwner(); * } else { * passOwner = NULL; * } * * for ( i = 0; i < num; i++ ) { * * cm = clipModelList[i]; * * // check if we should ignore this entity * if ( cm->entity == passEntity ) { * clipModelList[i] = NULL; // don't clip against the pass entity * } else if ( cm->entity == passOwner ) { * clipModelList[i] = NULL; // missiles don't clip with their owner * } else if ( cm->owner ) { * if ( cm->owner == passEntity ) { * clipModelList[i] = NULL; // don't clip against own missiles * } else if ( cm->owner == passOwner ) { * clipModelList[i] = NULL; // don't clip against other missiles from same owner * } * } * } * * return num;*/ return(null); }
/// <summary> /// /// </summary> /// <param name="?"></param> /// <returns>False if no part of the bounds extends beyond the near plane.</returns> public bool ConstrainToBounds(idBounds bounds) { float min, max; Vector3 tmp = new Vector3(_axis.M11, _axis.M12, _axis.M12); bounds.AxisProjection(tmp, out min, out max); float newDFar = max - (tmp * _origin).Length(); if (newDFar <= _dNear) { MoveFarDistance(_dNear + 1.0f); return(false); } MoveFarDistance(newDFar); return(true); }
private void SetupBox(idBounds bounds) { if (_type != TraceModelType.Box) { InitBox(); } // offset to center _offset = (bounds.Min + bounds.Max) * 0.5f; // set box vertices for (int i = 0; i < 8; i++) { _vertices[i].X = (((i ^ (i >> 1)) & 1) == 0) ? bounds.Min.X : bounds.Max.X; _vertices[i].Y = (((i >> 1) & 1) == 0) ? bounds.Min.Y : bounds.Max.Y; _vertices[i].Z = (((i >> 2) & 1) == 0) ? bounds.Min.Z : bounds.Max.Z; } // set polygon plane distances _polygons[0].Distance = -bounds.Min.Z; _polygons[1].Distance = bounds.Max.Z; _polygons[2].Distance = -bounds.Min.Y; _polygons[3].Distance = bounds.Max.X; _polygons[4].Distance = bounds.Max.Y; _polygons[5].Distance = -bounds.Min.X; // set polygon bounds for (int i = 0; i < 6; i++) { _polygons[i].Bounds = bounds; } _polygons[0].Bounds.Max.Z = bounds.Min.Z; _polygons[1].Bounds.Min.Z = bounds.Max.Z; _polygons[2].Bounds.Max.Y = bounds.Min.Y; _polygons[3].Bounds.Min.X = bounds.Max.X; _polygons[4].Bounds.Min.Y = bounds.Max.Y; _polygons[5].Bounds.Max.X = bounds.Min.X; _bounds = bounds; }
public idBounds GetBounds(int time, int cycleCount) { FrameBlend frame = ConvertTimeToFrame(time, cycleCount); idBounds bounds = _bounds[frame.Frame1]; bounds.AddBounds(_bounds[frame.Frame2]); // origin position Vector3 offset = _baseFrame[0].Translation; if ((_jointInfo[0].AnimationBits & (AnimationBits.TranslationX | AnimationBits.TranslationY | AnimationBits.TranslationZ)) != 0) { int componentOffset1 = _animatedComponentCount * frame.Frame1 + _jointInfo[0].FirstComponent; int componentOffset2 = _animatedComponentCount * frame.Frame2 + _jointInfo[0].FirstComponent; if ((_jointInfo[0].AnimationBits & AnimationBits.TranslationX) == AnimationBits.TranslationX) { offset.X = _componentFrames[componentOffset1] * frame.FrontLerp + _componentFrames[componentOffset2] * frame.BackLerp; componentOffset1++; componentOffset2++; } if ((_jointInfo[0].AnimationBits & AnimationBits.TranslationY) == AnimationBits.TranslationY) { offset.Y = _componentFrames[componentOffset1] * frame.FrontLerp + _componentFrames[componentOffset2] * frame.BackLerp; componentOffset1++; componentOffset2++; } if ((_jointInfo[0].AnimationBits & AnimationBits.TranslationZ) == AnimationBits.TranslationZ) { offset.Z = _componentFrames[componentOffset1] * frame.FrontLerp + _componentFrames[componentOffset2] * frame.BackLerp; } } bounds.Min -= offset; bounds.Max -= offset; return(bounds); }
public override void InitEmpty(string name) { if (this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } // model names of the form _area* are static parts of the // world, and have already been considered for optimized shadows // other model names are inline entity models, and need to be // shadowed normally _isStaticWorldModel = (name.StartsWith("_area") == true); _name = name; _reloadable = false; // if it didn't come from a file, we can't reload it Purge(); _purged = false; _bounds = idBounds.Zero; }
public void Init() { Vector3 maxSector = Vector3.Zero; // clear clip sectors _clipSectors = new ClipSector[MaxSectors]; _clipSectorCount = 0; _touchCount = -1; // get world map bounds CollisionModel collisionModel = idR.CollisionModelManager.LoadModel("worldMap", false); if (collisionModel != null) { _worldBounds = collisionModel.Bounds; } // create world sectors CreateClipSectors(0, _worldBounds, ref maxSector); Vector3 size = _worldBounds.Max - _worldBounds.Min; idConsole.WriteLine("map bounds are ({0})", size); idConsole.WriteLine("max clip sector is ({0})", maxSector); // initialize a default clip model _defaultClipModel = new idClipModel(); _defaultClipModel.LoadModel(new idTraceModel(idBounds.Expand(8))); // set counters to zero _rotationCount = 0; _translationCount = 0; _motionCount = 0; _renderModelTraceCount = 0; _contentCount = 0; _contactCount = 0; }
/// <summary> /// /// </summary> /// <remarks>Must have been linked with an entity and ID before.</remarks> /// <param name="clip"></param> public void Link(idClip clip) { if(this.Disposed == true) { throw new ObjectDisposedException("idClipModel"); } if(_entity == null) { return; } if(_clipLinks != null) { Unlink(); // unlink from old position. } if(_bounds.IsCleared == true) { return; } // set the abs box if(_axis != Matrix.Identity) { // expand for rotation _absBounds = idBounds.FromTransformedBounds(_bounds, _origin, _axis); } else { // normal _absBounds.Min = _bounds.Min + _origin; _absBounds.Max = _bounds.Max + _origin; } // because movement is clipped an epsilon away from an actual edge, // we must fully check even when bounding boxes don't quite touch _absBounds.Min -= new Vector3(BoxEpsilon, BoxEpsilon, BoxEpsilon); _absBounds.Max += new Vector3(BoxEpsilon, BoxEpsilon, BoxEpsilon); // TODO: this may not be correct! from what I can gleam it just starts at the start of the array LinkSectors(clip.Sectors[0]); }
/* =============================================================================== Writing of collision model file =============================================================================== */ void CM_GetNodeBounds( idBounds *bounds, cm_node_t *node );
public void LoadModel(idTraceModel traceModel) { if(this.Disposed == true) { throw new ObjectDisposedException("idClipModel"); } _collisionModelHandle = 0; _renderModelHandle = -1; _traceModelCache = GetTraceModelCache(traceModel); _bounds = traceModel.Bounds; }
/// <summary> /// /// </summary> /// <remarks> /// The mergeShadows option allows surfaces with different textures to share /// silhouette edges for shadow calculation, instead of leaving shared edges /// hanging. /// <para/> /// If any of the original shaders have the noSelfShadow flag set, the surfaces /// can't be merged, because they will need to be drawn in different order. /// <para/> /// If there is only one surface, a separate merged surface won't be generated. /// <para/> /// A model with multiple surfaces can't later have a skinned shader change the /// state of the noSelfShadow flag. /// <para/> /// ----------------- /// <para/> /// Creates mirrored copies of two sided surfaces with normal maps, which would /// otherwise light funny. /// <para/> /// Extends the bounds of deformed surfaces so they don't cull incorrectly at screen edges. /// </remarks> public override void FinishSurfaces() { if (this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } _purged = false; // make sure we don't have a huge bounds even if we don't finish everything _bounds = idBounds.Zero; if (_surfaces.Count == 0) { return; } // renderBump doesn't care about most of this if (_fastLoad == true) { _bounds = idBounds.Zero; foreach (RenderModelSurface surf in _surfaces) { idHelper.BoundTriangleSurface(surf.Geometry); _bounds.AddBounds(surf.Geometry.Bounds); } return; } // cleanup all the final surfaces, but don't create sil edges int totalVerts = 0; int totalIndexes = 0; // decide if we are going to merge all the surfaces into one shadower int numOriginalSurfaces = _surfaces.Count; // make sure there aren't any NULL shaders or geometry for (int i = 0; i < numOriginalSurfaces; i++) { RenderModelSurface surf = _surfaces[i]; if ((surf.Geometry == null) || (surf.Material == null)) { MakeDefault(); idConsole.Error("Model {0}, surface {1} had NULL goemetry", this.Name, i); } if (surf.Material == null) { MakeDefault(); idConsole.Error("Model {0}, surface {1} had NULL material", this.Name, i); } } // duplicate and reverse triangles for two sided bump mapped surfaces // note that this won't catch surfaces that have their shaders dynamically // changed, and won't work with animated models. // It is better to create completely separate surfaces, rather than // add vertexes and indexes to the existing surface, because the // tangent generation wouldn't like the acute shared edges for (int i = 0; i < numOriginalSurfaces; i++) { RenderModelSurface surf = _surfaces[i]; if (surf.Material.ShouldCreateBackSides == true) { idConsole.Warning("TODO: should create back sides"); /*srfTriangles_t *newTri; * * newTri = R_CopyStaticTriSurf( surf->geometry ); * R_ReverseTriangles( newTri ); * * modelSurface_t newSurf; * * newSurf.shader = surf->shader; * newSurf.geometry = newTri; * * AddSurface( newSurf );*/ } } // clean the surfaces // TODO: clean surfaces /*for ( i = 0 ; i < surfaces.Num() ; i++ ) { * const modelSurface_t *surf = &surfaces[i]; * * R_CleanupTriangles( surf->geometry, surf->geometry->generateNormals, true, surf->shader->UseUnsmoothedTangents() ); * if ( surf->shader->SurfaceCastsShadow() ) { * totalVerts += surf->geometry->numVerts; * totalIndexes += surf->geometry->numIndexes; * } * }*/ // add up the total surface area for development information // TODO: surf dev info /*for ( i = 0 ; i < surfaces.Num() ; i++ ) { * const modelSurface_t *surf = &surfaces[i]; * srfTriangles_t *tri = surf->geometry; * * for ( int j = 0 ; j < tri->numIndexes ; j += 3 ) { * float area = idWinding::TriangleArea( tri->verts[tri->indexes[j]].xyz, * tri->verts[tri->indexes[j+1]].xyz, tri->verts[tri->indexes[j+2]].xyz ); * const_cast<idMaterial *>(surf->shader)->AddToSurfaceArea( area ); * } * }*/ // calculate the bounds int surfaceCount = _surfaces.Count; if (surfaceCount == 0) { _bounds = idBounds.Zero; } else { _bounds.Clear(); for (int i = 0; i < surfaceCount; i++) { RenderModelSurface surf = _surfaces[i]; // if the surface has a deformation, increase the bounds // the amount here is somewhat arbitrary, designed to handle // autosprites and flares, but could be done better with exact // deformation information. // Note that this doesn't handle deformations that are skinned in // at run time... if (surf.Material.Deform != DeformType.None) { idConsole.Warning("TODO: deform"); /*srfTriangles_t *tri = surf->geometry; * idVec3 mid = ( tri->bounds[1] + tri->bounds[0] ) * 0.5f; * float radius = ( tri->bounds[0] - mid ).Length(); * radius += 20.0f; * * tri->bounds[0][0] = mid[0] - radius; * tri->bounds[0][1] = mid[1] - radius; * tri->bounds[0][2] = mid[2] - radius; * * tri->bounds[1][0] = mid[0] + radius; * tri->bounds[1][1] = mid[1] + radius; * tri->bounds[1][2] = mid[2] + radius;*/ } // add to the model bounds _bounds.AddBounds(surf.Geometry.Bounds); } } }
public bool GetBounds(int currentTime, out idBounds bounds) { bounds = idBounds.Zero; if ((_modelDef == null) || (_modelDef.Model == null)) { return(false); } int count = 0; if (_afPoseJoints.Count > 0) { bounds = _afPoseBounds; count = 1; } for (int i = (int)AnimationChannel.All; i < (int)AnimationChannel.Count; i++) { for (int j = 0; j < idR.AnimationCountPerChannel; j++) { idAnimBlend blend = _channels[i, j]; if (blend.AddBounds(currentTime, ref bounds, _removeOriginOffset) == true) { count++; } } } if (count == 0) { if (_frameBounds.IsCleared == false) { bounds = _frameBounds; return(true); } else { return(false); } } bounds.Translate(_modelDef.VisualOffset); if (idR.CvarSystem.GetBool("g_debugBounds") == true) { idConsole.Warning("TODO: g_debugBounds"); /*if ( bounds[1][0] - bounds[0][0] > 2048 || bounds[1][1] - bounds[0][1] > 2048 ) { * if ( entity ) { * gameLocal.Warning( "big frameBounds on entity '%s' with model '%s': %f,%f", entity->name.c_str(), modelDef->ModelHandle()->Name(), bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1] ); * } else { * gameLocal.Warning( "big frameBounds on model '%s': %f,%f", modelDef->ModelHandle()->Name(), bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1] ); * } * }*/ } _frameBounds = bounds; return(true); }
public override bool Parse(string text) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } idToken token; string tokenLower; idLexer lexer = new idLexer(idDeclFile.LexerOptions); lexer.LoadMemory(text, this.FileName, this.LineNumber); lexer.SkipUntilString("{"); List<idParticleStage> stages = new List<idParticleStage>(); _depthHack = 0.0f; while(true) { if((token = lexer.ReadToken()) == null) { break; } tokenLower = token.ToString().ToLower(); if(tokenLower == "}") { break; } else if(tokenLower == "{") { idParticleStage stage = ParseParticleStage(lexer); if(stage == null) { lexer.Warning("Particle stage parse failed"); MakeDefault(); return false; } stages.Add(stage); } else if(tokenLower == "depthhack") { _depthHack = lexer.ParseFloat(); } else { lexer.Warning("bad token {0}", token.ToString()); MakeDefault(); return false; } } _stages = stages.ToArray(); // // calculate the bounds // _bounds.Clear(); int count = _stages.Length; for(int i = 0; i < count; i++) { idConsole.Warning("TODO: GetStageBounds"); // TODO: GetStageBounds(stages[i]); _bounds += _stages[i].Bounds; } if(_bounds.Volume <= 0.1f) { _bounds = idBounds.Expand(idBounds.Zero, 8.0f); } return true; }
private void SetupBox(idBounds bounds) { if(_type != TraceModelType.Box) { InitBox(); } // offset to center _offset = (bounds.Min + bounds.Max) * 0.5f; // set box vertices for(int i = 0; i < 8; i++) { _vertices[i].X = (((i ^ (i >> 1)) & 1) == 0) ? bounds.Min.X : bounds.Max.X; _vertices[i].Y = (((i >> 1) & 1) == 0) ? bounds.Min.Y : bounds.Max.Y; _vertices[i].Z = (((i >> 2) & 1) == 0) ? bounds.Min.Z : bounds.Max.Z; } // set polygon plane distances _polygons[0].Distance = -bounds.Min.Z; _polygons[1].Distance = bounds.Max.Z; _polygons[2].Distance = -bounds.Min.Y; _polygons[3].Distance = bounds.Max.X; _polygons[4].Distance = bounds.Max.Y; _polygons[5].Distance = -bounds.Min.X; // set polygon bounds for(int i = 0; i < 6; i++) { _polygons[i].Bounds = bounds; } _polygons[0].Bounds.Max.Z = bounds.Min.Z; _polygons[1].Bounds.Min.Z = bounds.Max.Z; _polygons[2].Bounds.Max.Y = bounds.Min.Y; _polygons[3].Bounds.Min.X = bounds.Max.X; _polygons[4].Bounds.Min.Y = bounds.Max.Y; _polygons[5].Bounds.Max.X = bounds.Min.X; _bounds = bounds; }
public override void AddSurface(RenderModelSurface surface) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } _surfaces.Add(surface); if(surface.Geometry != null) { _bounds += surface.Geometry.Bounds; } }
public bool GetBounds(int currentTime, out idBounds bounds) { bounds = idBounds.Zero; if((_modelDef == null) || (_modelDef.Model == null)) { return false; } int count = 0; if(_afPoseJoints.Count > 0) { bounds = _afPoseBounds; count = 1; } for(int i = (int) AnimationChannel.All; i < (int) AnimationChannel.Count; i++) { for(int j = 0; j < idR.AnimationCountPerChannel; j++) { idAnimBlend blend = _channels[i, j]; if(blend.AddBounds(currentTime, ref bounds, _removeOriginOffset) == true) { count++; } } } if(count == 0) { if(_frameBounds.IsCleared == false) { bounds = _frameBounds; return true; } else { return false; } } bounds.Translate(_modelDef.VisualOffset); if(idR.CvarSystem.GetBool("g_debugBounds") == true) { idConsole.Warning("TODO: g_debugBounds"); /*if ( bounds[1][0] - bounds[0][0] > 2048 || bounds[1][1] - bounds[0][1] > 2048 ) { if ( entity ) { gameLocal.Warning( "big frameBounds on entity '%s' with model '%s': %f,%f", entity->name.c_str(), modelDef->ModelHandle()->Name(), bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1] ); } else { gameLocal.Warning( "big frameBounds on model '%s': %f,%f", modelDef->ModelHandle()->Name(), bounds[1][0] - bounds[0][0], bounds[1][1] - bounds[0][1] ); } }*/ } _frameBounds = bounds; return true; }
private void Dispose(bool disposing) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } if(disposing == true) { this.Bounds = idBounds.Zero; this.Indexes = null; this.Vertices = null; this.ShadowVertices = null; this.IndexCache = null; this.AmbientCache = null; } _disposed = true; }
public bool LoadAnimation(string fileName) { idToken token; idLexer lexer = new idLexer(LexerOptions.AllowPathNames | LexerOptions.NoStringEscapeCharacters | LexerOptions.NoStringConcatination); if(lexer.LoadFile(fileName) == false) { return false; } Clear(); _name = fileName; lexer.ExpectTokenString(idRenderModel_MD5.VersionString); int version = lexer.ParseInt(); if(version != idRenderModel_MD5.Version) { lexer.Error("Invalid version {0}. Should be version {1}", version, idRenderModel_MD5.Version); } // skip the commandline lexer.ExpectTokenString("commandline"); lexer.ReadToken(); // parse num frames lexer.ExpectTokenString("numFrames"); int frameCount = lexer.ParseInt(); if(frameCount <= 0) { lexer.Error("Invalid number of frames: {0}", frameCount); } // parse num joints lexer.ExpectTokenString("numJoints"); int jointCount = lexer.ParseInt(); if(jointCount <= 0) { lexer.Error("Invalid number of joints: {0}", jointCount); } // parse frame rate lexer.ExpectTokenString("frameRate"); _frameRate = lexer.ParseInt(); if(_frameRate < 0) { lexer.Error("Invalid frame rate: {0}", _frameRate); } // parse number of animated components lexer.ExpectTokenString("numAnimatedComponents"); _animatedComponentCount = lexer.ParseInt(); if((_animatedComponentCount < 0) || (_animatedComponentCount > (jointCount * 6))) { lexer.Error("Invalid number of animated components: {0}", _animatedComponentCount); } // parse the hierarchy _jointInfo = new JointAnimationInfo[jointCount]; lexer.ExpectTokenString("hierarchy"); lexer.ExpectTokenString("{"); for(int i = 0; i < jointCount; i++) { token = lexer.ReadToken(); _jointInfo[i] = new JointAnimationInfo(); _jointInfo[i].NameIndex = idR.AnimManager.GetJointIndex(token.ToString()); // parse parent num _jointInfo[i].ParentIndex = lexer.ParseInt(); if(_jointInfo[i].ParentIndex >= i) { lexer.Error("Invalid parent num: {0}", _jointInfo[i].ParentIndex); } if((i != 0) && (_jointInfo[i].ParentIndex < 0)) { lexer.Error("Animations may have only one root joint"); } // parse anim bits _jointInfo[i].AnimationBits = (AnimationBits) lexer.ParseInt(); if(((int) _jointInfo[i].AnimationBits & ~63) != 0) { lexer.Error("Invalid anim bits: {0}", _jointInfo[i].AnimationBits); } // parse first component _jointInfo[i].FirstComponent = lexer.ParseInt(); if((_animatedComponentCount > 0) && ((_jointInfo[i].FirstComponent < 0) || (_jointInfo[i].FirstComponent >= _animatedComponentCount))) { lexer.Error("Invalid first component: {0}", _jointInfo[i].FirstComponent); } } lexer.ExpectTokenString("}"); // parse bounds lexer.ExpectTokenString("bounds"); lexer.ExpectTokenString("{"); _bounds = new idBounds[frameCount]; for(int i = 0; i < frameCount; i++) { float[] tmp = lexer.Parse1DMatrix(3); float[] tmp2 = lexer.Parse1DMatrix(3); _bounds[i] = new idBounds( new Vector3(tmp[0], tmp[1], tmp[2]), new Vector3(tmp2[0], tmp2[1], tmp2[2]) ); } lexer.ExpectTokenString("}"); // parse base frame _baseFrame = new idJointQuaternion[jointCount]; lexer.ExpectTokenString("baseframe"); lexer.ExpectTokenString("{"); for(int i = 0; i < jointCount; i++) { float[] tmp = lexer.Parse1DMatrix(3); float[] tmp2 = lexer.Parse1DMatrix(3); idCompressedQuaternion q = new idCompressedQuaternion(tmp2[0], tmp2[1], tmp2[2]); _baseFrame[i] = new idJointQuaternion(); _baseFrame[i].Translation = new Vector3(tmp[0], tmp[1], tmp[2]); _baseFrame[i].Quaternion = q.ToQuaternion(); } lexer.ExpectTokenString("}"); // parse frames _componentFrames = new float[_animatedComponentCount * frameCount]; int frameOffset = 0; for(int i = 0; i < frameCount; i++) { lexer.ExpectTokenString("frame"); int count = lexer.ParseInt(); if(count != i) { lexer.Error("Expected frame number {0}", i); } lexer.ExpectTokenString("{"); for(int j = 0; j < _animatedComponentCount; j++, frameOffset++) { _componentFrames[frameOffset] = lexer.ParseFloat(); } lexer.ExpectTokenString("}"); } // get total move delta if(_animatedComponentCount == 0) { _totalDelta = Vector3.Zero; } else { int componentOffset = _jointInfo[0].FirstComponent; if((_jointInfo[0].AnimationBits & AnimationBits.TranslationX) == AnimationBits.TranslationX) { for(int i = 0; i < frameCount; i++) { _componentFrames[componentOffset + (_animatedComponentCount * i)] -= _baseFrame[0].Translation.X; } _totalDelta.X = _componentFrames[componentOffset + (_animatedComponentCount * (frameCount - 1))]; componentOffset++; } else { _totalDelta.X = 0; } if((_jointInfo[0].AnimationBits & AnimationBits.TranslationY) == AnimationBits.TranslationY) { for(int i = 0; i < frameCount; i++) { _componentFrames[componentOffset + (_animatedComponentCount * i)] -= _baseFrame[0].Translation.Y; } _totalDelta.Y = _componentFrames[componentOffset + (_animatedComponentCount * (frameCount - 1))]; componentOffset++; } else { _totalDelta.Y = 0; } if((_jointInfo[0].AnimationBits & AnimationBits.TranslationZ) == AnimationBits.TranslationZ) { for(int i = 0; i < frameCount; i++) { _componentFrames[componentOffset + (_animatedComponentCount * i)] -= _baseFrame[0].Translation.Z; } _totalDelta.Z = _componentFrames[componentOffset + (_animatedComponentCount * (frameCount - 1))]; } else { _totalDelta.Z = 0; } } _baseFrame[0].Translation = Vector3.Zero; // we don't count last frame because it would cause a 1 frame pause at the end _animLength = ((frameCount - 1) * 1000 + _frameRate - 1) / _frameRate; // done return true; }
public idTraceModel(idBounds bounds, int sideCount) { SetupCylinder(bounds, sideCount); }
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; }
/// <summary> /// Axial bounding box. /// </summary> /// <param name="boxBounds"></param> public idTraceModel(idBounds boxBounds) { InitBox(); SetupBox(boxBounds); }
public bool LoadAnimation(string fileName) { idToken token; idLexer lexer = new idLexer(LexerOptions.AllowPathNames | LexerOptions.NoStringEscapeCharacters | LexerOptions.NoStringConcatination); if (lexer.LoadFile(fileName) == false) { return(false); } Clear(); _name = fileName; lexer.ExpectTokenString(idRenderModel_MD5.VersionString); int version = lexer.ParseInt(); if (version != idRenderModel_MD5.Version) { lexer.Error("Invalid version {0}. Should be version {1}", version, idRenderModel_MD5.Version); } // skip the commandline lexer.ExpectTokenString("commandline"); lexer.ReadToken(); // parse num frames lexer.ExpectTokenString("numFrames"); int frameCount = lexer.ParseInt(); if (frameCount <= 0) { lexer.Error("Invalid number of frames: {0}", frameCount); } // parse num joints lexer.ExpectTokenString("numJoints"); int jointCount = lexer.ParseInt(); if (jointCount <= 0) { lexer.Error("Invalid number of joints: {0}", jointCount); } // parse frame rate lexer.ExpectTokenString("frameRate"); _frameRate = lexer.ParseInt(); if (_frameRate < 0) { lexer.Error("Invalid frame rate: {0}", _frameRate); } // parse number of animated components lexer.ExpectTokenString("numAnimatedComponents"); _animatedComponentCount = lexer.ParseInt(); if ((_animatedComponentCount < 0) || (_animatedComponentCount > (jointCount * 6))) { lexer.Error("Invalid number of animated components: {0}", _animatedComponentCount); } // parse the hierarchy _jointInfo = new JointAnimationInfo[jointCount]; lexer.ExpectTokenString("hierarchy"); lexer.ExpectTokenString("{"); for (int i = 0; i < jointCount; i++) { token = lexer.ReadToken(); _jointInfo[i] = new JointAnimationInfo(); _jointInfo[i].NameIndex = idR.AnimManager.GetJointIndex(token.ToString()); // parse parent num _jointInfo[i].ParentIndex = lexer.ParseInt(); if (_jointInfo[i].ParentIndex >= i) { lexer.Error("Invalid parent num: {0}", _jointInfo[i].ParentIndex); } if ((i != 0) && (_jointInfo[i].ParentIndex < 0)) { lexer.Error("Animations may have only one root joint"); } // parse anim bits _jointInfo[i].AnimationBits = (AnimationBits)lexer.ParseInt(); if (((int)_jointInfo[i].AnimationBits & ~63) != 0) { lexer.Error("Invalid anim bits: {0}", _jointInfo[i].AnimationBits); } // parse first component _jointInfo[i].FirstComponent = lexer.ParseInt(); if ((_animatedComponentCount > 0) && ((_jointInfo[i].FirstComponent < 0) || (_jointInfo[i].FirstComponent >= _animatedComponentCount))) { lexer.Error("Invalid first component: {0}", _jointInfo[i].FirstComponent); } } lexer.ExpectTokenString("}"); // parse bounds lexer.ExpectTokenString("bounds"); lexer.ExpectTokenString("{"); _bounds = new idBounds[frameCount]; for (int i = 0; i < frameCount; i++) { float[] tmp = lexer.Parse1DMatrix(3); float[] tmp2 = lexer.Parse1DMatrix(3); _bounds[i] = new idBounds( new Vector3(tmp[0], tmp[1], tmp[2]), new Vector3(tmp2[0], tmp2[1], tmp2[2]) ); } lexer.ExpectTokenString("}"); // parse base frame _baseFrame = new idJointQuaternion[jointCount]; lexer.ExpectTokenString("baseframe"); lexer.ExpectTokenString("{"); for (int i = 0; i < jointCount; i++) { float[] tmp = lexer.Parse1DMatrix(3); float[] tmp2 = lexer.Parse1DMatrix(3); idCompressedQuaternion q = new idCompressedQuaternion(tmp2[0], tmp2[1], tmp2[2]); _baseFrame[i] = new idJointQuaternion(); _baseFrame[i].Translation = new Vector3(tmp[0], tmp[1], tmp[2]); _baseFrame[i].Quaternion = q.ToQuaternion(); } lexer.ExpectTokenString("}"); // parse frames _componentFrames = new float[_animatedComponentCount * frameCount]; int frameOffset = 0; for (int i = 0; i < frameCount; i++) { lexer.ExpectTokenString("frame"); int count = lexer.ParseInt(); if (count != i) { lexer.Error("Expected frame number {0}", i); } lexer.ExpectTokenString("{"); for (int j = 0; j < _animatedComponentCount; j++, frameOffset++) { _componentFrames[frameOffset] = lexer.ParseFloat(); } lexer.ExpectTokenString("}"); } // get total move delta if (_animatedComponentCount == 0) { _totalDelta = Vector3.Zero; } else { int componentOffset = _jointInfo[0].FirstComponent; if ((_jointInfo[0].AnimationBits & AnimationBits.TranslationX) == AnimationBits.TranslationX) { for (int i = 0; i < frameCount; i++) { _componentFrames[componentOffset + (_animatedComponentCount * i)] -= _baseFrame[0].Translation.X; } _totalDelta.X = _componentFrames[componentOffset + (_animatedComponentCount * (frameCount - 1))]; componentOffset++; } else { _totalDelta.X = 0; } if ((_jointInfo[0].AnimationBits & AnimationBits.TranslationY) == AnimationBits.TranslationY) { for (int i = 0; i < frameCount; i++) { _componentFrames[componentOffset + (_animatedComponentCount * i)] -= _baseFrame[0].Translation.Y; } _totalDelta.Y = _componentFrames[componentOffset + (_animatedComponentCount * (frameCount - 1))]; componentOffset++; } else { _totalDelta.Y = 0; } if ((_jointInfo[0].AnimationBits & AnimationBits.TranslationZ) == AnimationBits.TranslationZ) { for (int i = 0; i < frameCount; i++) { _componentFrames[componentOffset + (_animatedComponentCount * i)] -= _baseFrame[0].Translation.Z; } _totalDelta.Z = _componentFrames[componentOffset + (_animatedComponentCount * (frameCount - 1))]; } else { _totalDelta.Z = 0; } } _baseFrame[0].Translation = Vector3.Zero; // we don't count last frame because it would cause a 1 frame pause at the end _animLength = ((frameCount - 1) * 1000 + _frameRate - 1) / _frameRate; // done return(true); }
/// <summary> /// /// </summary> /// <param name="?"></param> /// <returns>False if no part of the bounds extends beyond the near plane.</returns> public bool ConstrainToBounds(idBounds bounds) { float min, max; Vector3 tmp = new Vector3(_axis.M11, _axis.M12, _axis.M12); bounds.AxisProjection(tmp, out min, out max); float newDFar = max - (tmp * _origin).Length(); if(newDFar <= _dNear) { MoveFarDistance(_dNear + 1.0f); return false; } MoveFarDistance(newDFar); return true; }
public idRenderEntity() { _parameters = new RenderEntityComponent(); _modelMatrix = Matrix.Identity; _referenceBounds = idBounds.Zero; }
public virtual void SetClipBox(idBounds bounds, float density) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } SetClipModel(new idClipModel(new idTraceModel(bounds)), density); }
public void SetupJoints(idJointMatrix[] joints, ref idBounds frameBounds, bool removeOriginOffset) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } if((_model == null) || (_model.IsDefault == true)) { joints = null; frameBounds.Clear(); } // get the number of joints int count = _model.JointCount; if(count == 0) { idConsole.Error("model '{0}' has no joints", _model.Name); } // set up initial pose for model (with no pose, model is just a jumbled mess) joints = new idJointMatrix[count]; idJointQuaternion[] pose = this.DefaultPose; // convert the joint quaternions to joint matrices idHelper.ConvertJointQuaternionsToJointMatrices(joints, pose); // check if we offset the model by the origin joint if(removeOriginOffset == true) { #if VELOCITY_MOVE joints[0].Translation(new Vector3(_offset.X, _offset.Y + pose[0].Translation.Y, _offset.Z + pose[0].Translation.Z)); #else joints[0].Translation = _offset; #endif } else { joints[0].Translation = pose[0].Translation + _offset; } // transform the joint hierarchy idHelper.TransformJoints(joints, _jointParents, 1, joints.Length - 1); // get the bounds of the default pose frameBounds = _model.GetBounds(null); }
/// <summary> /// /// </summary> /// <remarks> /// The mergeShadows option allows surfaces with different textures to share /// silhouette edges for shadow calculation, instead of leaving shared edges /// hanging. /// <para/> /// If any of the original shaders have the noSelfShadow flag set, the surfaces /// can't be merged, because they will need to be drawn in different order. /// <para/> /// If there is only one surface, a separate merged surface won't be generated. /// <para/> /// A model with multiple surfaces can't later have a skinned shader change the /// state of the noSelfShadow flag. /// <para/> /// ----------------- /// <para/> /// Creates mirrored copies of two sided surfaces with normal maps, which would /// otherwise light funny. /// <para/> /// Extends the bounds of deformed surfaces so they don't cull incorrectly at screen edges. /// </remarks> public override void FinishSurfaces() { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } _purged = false; // make sure we don't have a huge bounds even if we don't finish everything _bounds = idBounds.Zero; if(_surfaces.Count == 0) { return; } // renderBump doesn't care about most of this if(_fastLoad == true) { _bounds = idBounds.Zero; foreach(RenderModelSurface surf in _surfaces) { idHelper.BoundTriangleSurface(surf.Geometry); _bounds.AddBounds(surf.Geometry.Bounds); } return; } // cleanup all the final surfaces, but don't create sil edges int totalVerts = 0; int totalIndexes = 0; // decide if we are going to merge all the surfaces into one shadower int numOriginalSurfaces = _surfaces.Count; // make sure there aren't any NULL shaders or geometry for(int i = 0; i < numOriginalSurfaces; i++) { RenderModelSurface surf = _surfaces[i]; if((surf.Geometry == null) || (surf.Material == null)) { MakeDefault(); idConsole.Error("Model {0}, surface {1} had NULL goemetry", this.Name, i); } if(surf.Material == null) { MakeDefault(); idConsole.Error("Model {0}, surface {1} had NULL material", this.Name, i); } } // duplicate and reverse triangles for two sided bump mapped surfaces // note that this won't catch surfaces that have their shaders dynamically // changed, and won't work with animated models. // It is better to create completely separate surfaces, rather than // add vertexes and indexes to the existing surface, because the // tangent generation wouldn't like the acute shared edges for(int i = 0; i < numOriginalSurfaces; i++) { RenderModelSurface surf = _surfaces[i]; if(surf.Material.ShouldCreateBackSides == true) { idConsole.Warning("TODO: should create back sides"); /*srfTriangles_t *newTri; newTri = R_CopyStaticTriSurf( surf->geometry ); R_ReverseTriangles( newTri ); modelSurface_t newSurf; newSurf.shader = surf->shader; newSurf.geometry = newTri; AddSurface( newSurf );*/ } } // clean the surfaces // TODO: clean surfaces /*for ( i = 0 ; i < surfaces.Num() ; i++ ) { const modelSurface_t *surf = &surfaces[i]; R_CleanupTriangles( surf->geometry, surf->geometry->generateNormals, true, surf->shader->UseUnsmoothedTangents() ); if ( surf->shader->SurfaceCastsShadow() ) { totalVerts += surf->geometry->numVerts; totalIndexes += surf->geometry->numIndexes; } }*/ // add up the total surface area for development information // TODO: surf dev info /*for ( i = 0 ; i < surfaces.Num() ; i++ ) { const modelSurface_t *surf = &surfaces[i]; srfTriangles_t *tri = surf->geometry; for ( int j = 0 ; j < tri->numIndexes ; j += 3 ) { float area = idWinding::TriangleArea( tri->verts[tri->indexes[j]].xyz, tri->verts[tri->indexes[j+1]].xyz, tri->verts[tri->indexes[j+2]].xyz ); const_cast<idMaterial *>(surf->shader)->AddToSurfaceArea( area ); } }*/ // calculate the bounds int surfaceCount = _surfaces.Count; if(surfaceCount == 0) { _bounds = idBounds.Zero; } else { _bounds.Clear(); for(int i = 0; i < surfaceCount; i++) { RenderModelSurface surf = _surfaces[i]; // if the surface has a deformation, increase the bounds // the amount here is somewhat arbitrary, designed to handle // autosprites and flares, but could be done better with exact // deformation information. // Note that this doesn't handle deformations that are skinned in // at run time... if(surf.Material.Deform != DeformType.None) { idConsole.Warning("TODO: deform"); /*srfTriangles_t *tri = surf->geometry; idVec3 mid = ( tri->bounds[1] + tri->bounds[0] ) * 0.5f; float radius = ( tri->bounds[0] - mid ).Length(); radius += 20.0f; tri->bounds[0][0] = mid[0] - radius; tri->bounds[0][1] = mid[1] - radius; tri->bounds[0][2] = mid[2] - radius; tri->bounds[1][0] = mid[0] + radius; tri->bounds[1][1] = mid[1] + radius; tri->bounds[1][2] = mid[2] + radius;*/ } // add to the model bounds _bounds.AddBounds(surf.Geometry.Bounds); } } }
public idClipModel(idClipModel model) { _id = model.ID; _owner = model.Owner; _enabled = model.Enabled; _entity = model.Entity; _origin = model.Origin; _axis = model.Axis; _bounds = model.Bounds; _absBounds = model.AbsoluteBounds; _material = model.Material; _contents = model.Contents; _collisionModelHandle = model.CollisionModelHandle; _traceModelCache = null; if(model.TraceModelCache != null) { idConsole.Warning("TODO: LoadModel( *GetCachedTraceModel( model->traceModelIndex ) );"); } _renderModelHandle = model.RenderModelHandle; _touchCount = -1; }
public override void InitEmpty(string name) { if(this.Disposed == true) { throw new ObjectDisposedException(this.GetType().Name); } // model names of the form _area* are static parts of the // world, and have already been considered for optimized shadows // other model names are inline entity models, and need to be // shadowed normally _isStaticWorldModel = (name.StartsWith("_area") == true); _name = name; _reloadable = false; // if it didn't come from a file, we can't reload it Purge(); _purged = false; _bounds = idBounds.Zero; }
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; }
private void GetNodeBounds_R(ref idBounds bounds, CollisionModelNode node) { while(true) { foreach(CollisionModelPolygon poly in node.Polygons) { bounds.AddPoint(poly.Bounds.Min); bounds.AddPoint(poly.Bounds.Max); } foreach(CollisionModelBrush brush in node.Brushes) { bounds.AddPoint(brush.Bounds.Min); bounds.AddPoint(brush.Bounds.Max); } if(node.PlaneType == -1) { break; } GetNodeBounds_R(ref bounds, node.Children[1]); node = node.Children[0]; } }
public bool GetBounds(out idBounds bounds, int animNumber, int currentTime, int cycleCount) { if(_anims[animNumber] == null) { bounds = idBounds.Zero; return false; } bounds = _anims[animNumber].GetBounds(currentTime, cycleCount); return true; }
private bool InsideAllChildren(CollisionModelNode node, idBounds bounds) { if(node.PlaneType != -1) { float v = (node.PlaneType == 0) ? bounds.Min.X : (node.PlaneType == 1) ? bounds.Min.Y : bounds.Min.Z; float v2 = (node.PlaneType == 0) ? bounds.Max.X : (node.PlaneType == 1) ? bounds.Max.Y : bounds.Max.Z; if(v >= node.PlaneDistance) { return false; } else if(v2 <= node.PlaneDistance) { return false; } else if(InsideAllChildren(node.Children[0], bounds) == false) { return false; } else if(InsideAllChildren(node.Children[1], bounds) == false) { return false; } } return true; }
public void Link(idClip clip, idEntity entity, int newID, Vector3 newOrigin, Matrix newAxis, int renderModelHandle) { if(this.Disposed == true) { throw new ObjectDisposedException("idClipModel"); } _entity = entity; _id = newID; _origin = newOrigin; _axis = newAxis; if(_renderModelHandle != -1) { _renderModelHandle = renderModelHandle; RenderEntityComponent renderEntity = idR.Game.RenderWorld.GetRenderEntity(renderModelHandle); if(renderEntity != null) { _bounds = renderEntity.Bounds; } } Link(clip); }
public void SetupCylinder(idBounds bounds, int sideCount) { int n = sideCount; if (n < 3) { n = 3; } if ((n * 2) > MaxVertices) { idConsole.WriteLine("WARNING: idTraceModel::SetupCylinder: too many vertices"); n = MaxVertices / 2; } if ((n * 3) > MaxEdges) { idConsole.WriteLine("WARNING: idTraceModel::SetupCylinder: too many sides"); n = MaxEdges / 3; } if ((n + 2) > MaxPolygons) { idConsole.WriteLine("WARNING: idTraceModel::SetupCylinder: too many polygons"); n = MaxPolygons - 2; } _type = TraceModelType.Cylinder; _vertices = new Vector3[n * 2]; _edges = new TraceModelEdge[n * 3]; _polygons = new TraceModelPolygon[n + 2]; _offset = (bounds.Min + bounds.Max) * 0.5f; Vector3 halfSize = bounds.Max - _offset; for (int i = 0; i < n; i++) { // verts float angle = idMath.TwoPi * i / n; _vertices[i].X = idMath.Cos(angle) * halfSize.X + _offset.X; _vertices[i].Y = idMath.Sin(angle) * halfSize.Y + _offset.Y; _vertices[i].Z = -halfSize.Z + _offset.Z; _vertices[n + i].X = _vertices[i].X; _vertices[n + i].Y = _vertices[i].Y; _vertices[n + i].Z = halfSize.Z + _offset.Z; // edges int ii = i + 1; int n2 = n << 1; _edges[ii].V[0] = i; _edges[ii].V[1] = ii % n; _edges[n + ii].V[0] = _edges[ii].V[0] + n; _edges[n + ii].V[1] = _edges[ii].V[1] + n; _edges[n2 + ii].V[0] = i; _edges[n2 + ii].V[1] = n + i; // vertical polygon edges _polygons[i].Edges = new int[4]; _polygons[i].Edges[0] = ii; _polygons[i].Edges[1] = n2 + (ii % n) + 1; _polygons[i].Edges[2] = -(n + ii); _polygons[i].Edges[3] = -(n2 + ii); // bottom and top polygon edges _polygons[n].Edges[i] = -(n - i); _polygons[n + 1].Edges[i] = n + ii; } // bottom and top polygon numEdges _polygons[n].Edges = new int[n]; _polygons[n + 1].Edges = new int[n]; // polygons for (int i = 0; i < n; i++) { // vertical polygon plane _polygons[i].Normal = Vector3.Cross(_vertices[(i + 1) % n] - _vertices[i], _vertices[n + i] - _vertices[i]); _polygons[i].Normal.Normalize(); // vertical polygon bounds _polygons[i].Bounds.Clear(); _polygons[i].Bounds.AddPoint(_vertices[i]); _polygons[i].Bounds.AddPoint(_vertices[(i + 1) % n]); _polygons[i].Bounds.Min.Z = -halfSize.Z + _offset.Z; _polygons[i].Bounds.Max.Z = halfSize.Z + _offset.Z; } // bottom and top polygon plane _polygons[n].Normal = new Vector3(0, 0, -1.0f); _polygons[n].Distance = -bounds.Min.Z; _polygons[n + 1].Normal = new Vector3(0, 0, 1.0f); _polygons[n + 1].Distance = bounds.Max.Z; // trm bounds _bounds = bounds; // bottom and top polygon bounds _polygons[n].Bounds = bounds; _polygons[n].Bounds.Max.Z = bounds.Min.Z; _polygons[n + 1].Bounds = bounds; _polygons[n + 1].Bounds.Min.Z = bounds.Max.Z; // convex model _isConvex = true; GenerateEdgeNormals(); }
private void ConstrainViewFrustum() { idBounds bounds = new idBounds(); // constrain the view frustum to the total bounds of all visible lights and visible entities // TODO: lights /*for(viewLight_t* vLight = tr.viewDef->viewLights; vLight; vLight = vLight->next) { bounds.AddBounds(vLight->lightDef->frustumTris->bounds); }*/ foreach(ViewEntity viewEntity in _viewDefinition.ViewEntities) { bounds.AddBounds(viewEntity.EntityDef.ReferenceBounds); } _viewDefinition.ViewFrustum.ConstrainToBounds(bounds); float farDistance = idE.CvarSystem.GetFloat("r_useFrustumFarDistance"); if(farDistance > 0.0f) { _viewDefinition.ViewFrustum.MoveFarDistance(farDistance); } }