public string RayIntersectsHitbox(Ray ray, out float?distance) { GenerateHitBoxesTriangles(); foreach (Display3D.Triangle tri in GetRealTriangles()) { Display3D.Triangle triangle = tri; float?dist = Display3D.TriangleTest.Intersects(ref ray, ref triangle); if (dist.HasValue) { distance = dist; return(tri.TriName); } } distance = null; return(""); }
public List <Display3D.Triangle> GetRealTriangles(bool drawHitbox = false) { Matrix world = GetModelMatrix(); List <Display3D.Triangle> triangles = new List <Display3D.Triangle>(); foreach (KeyValuePair <string, Display3D.Triangle> tri in hitBoxesTriangles) { //world = tri.Value.transformMatrix; Display3D.Triangle newTri = tri.Value.NewByMatrix(world); triangles.Add(newTri); if (drawHitbox) { Display3D.CSimpleShapes.AddTriangle(newTri.V0, newTri.V1, newTri.V2, Color.Black); } } return(triangles); }
/// <summary> /// Gets the new position of the entity by applying it all the physics /// </summary> public Vector3 GetNewPosition(GameTime gameTime, Vector3 entityPos, Vector3 translation, bool isUnderwater) { _isUnderwater = isUnderwater; bool isVerticalIntersecting = false; Vector3 translationOriginal = translation; translation *= (float)gameTime.ElapsedGameTime.TotalSeconds; Vector3 assumedNewPosition = entityPos + translation; Ray translationRay = new Ray(new Vector3(entityPos.X, entityPos.Y - _entityHeight / 2 + heightCorrection, entityPos.Z), translation); Vector3 horizontalNormalReaction = Vector3.Zero; // Water surface check float waterHeight = -1; foreach (float waterH in _waterHeight) { if (entityPos.Y + translation.Y > waterHeight) { waterHeight = waterH; } } if (_isGameUsing[1] && (_isUnderwater || _isOnWaterSurface) && waterHeight != -1) { _isOnWaterSurface = true; _velocity.Y = 0; assumedNewPosition.Y = waterHeight + translation.Y; } else if (_isOnWaterSurface) { _isOnWaterSurface = false; } /* Horizontal check - models */ for (int i = 0; i < _triangleList.Count; i++) { Display3D.Triangle triangleToTest = _triangleList[i]; float?distance = Display3D.TriangleTest.Intersects(ref translationRay, ref triangleToTest); if (distance != null && distance <= _intersectionDistanceH) { horizontalNormalReaction = -_triangleNormalsList[i] * translation.Length() * (_intersectionDistanceH - (float)distance); //horizontalNormalReaction = -translation; break; } } assumedNewPosition += horizontalNormalReaction; /* Vertical check - terrain */ // Terrain informations float Steepness; float terrainHeight = (_isGameUsing[0]) ? _terrain.GetHeightAtPosition(assumedNewPosition.X, assumedNewPosition.Z, out Steepness) : 0; float jumpVelocity = 0f; if (_velocity.Y > 0) { jumpVelocity = _velocity.Y; } if (_isGameUsing[0] && assumedNewPosition.Y + jumpVelocity <= terrainHeight + _entityHeight + 0.001f) { isVerticalIntersecting = true; assumedNewPosition.Y = terrainHeight + _entityHeight; _velocity = Vector3.Zero; Vector3 normal = _terrain.getNormalAtPoint(assumedNewPosition.X, assumedNewPosition.Z); if (normal.Y > _slippingResistance) { _velocity = -0.1f * normal; _velocity.Y = -0.1f; } } else { isVerticalIntersecting = false; //float dt = (float)(gameTime.TotalGameTime.TotalMilliseconds - _lastFreeFall) * (float)gameTime.ElapsedGameTime.TotalMilliseconds; float dt = (float)gameTime.ElapsedGameTime.TotalSeconds; if (_isUnderwater && translation == Vector3.Zero) { _velocity.Y += _gravityConstantWater * dt; } else { _velocity.Y += _gravityConstant * dt; } if (_isUnderwater && _velocity.Y < _maxFallingVelocityWater) { _velocity.Y = _maxFallingVelocityWater; } else if (_velocity.Y < _maxFallingVelocity) { _velocity.Y = _maxFallingVelocity; } } Ray newPosTranslationRay = new Ray(assumedNewPosition + _velocity, (_velocity.Y > 0) ? Vector3.Up : Vector3.Down); /* Vertical check - models */ float closestTriangleBelowDistance = 999f; int closestTriangle = -1; for (int i = 0; i < _triangleList.Count; i++) { Display3D.Triangle triangleToTest = _triangleList[i]; float?distance = Display3D.TriangleTest.Intersects(ref newPosTranslationRay, ref triangleToTest); if (distance != null) { if (distance < closestTriangleBelowDistance) { closestTriangle = i; closestTriangleBelowDistance = (float)distance; } } } if (closestTriangle != -1 && closestTriangleBelowDistance <= (_velocity.Y <= 0 ? _entityHeight : _entityHeight / 3)) { // If the player is falling, and not jumping if (_velocity.Y <= 0) { isVerticalIntersecting = true; assumedNewPosition += _velocity; Display3D.Triangle closestTriangleT = _triangleList[closestTriangle]; assumedNewPosition.Y = assumedNewPosition.Y - closestTriangleBelowDistance + _entityHeight; Vector3 normal = _triangleNormalsList[closestTriangle]; if (normal.Y > _slippingResistance) { _velocity = -0.1f * normal; _velocity.Y = -0.1f; } } _velocity.Y = 0; } if (_isOnWaterSurface) { _velocity.Y = 0; } if (isVerticalIntersecting) { _lastFreeFall = gameTime.TotalGameTime.TotalSeconds; _isOnWaterSurface = false; } return(assumedNewPosition + _velocity); }