private void PositionCameraAtNode(TrackNode node) { _cameraNode = node; _camera.Position = Engine.Instance.Random.Next() % 2 == 0 ? _cameraNode.GetLeftBoundary() : _cameraNode.GetRightBoundary(); _camera.Position = _camera.Position + new Vector3(0, Engine.Instance.Random.Next(15, 50), 0); }
void ParseTrackNodesBlock(BinaryReader reader) { reader.BaseStream.Position = 2444; //start of node list TrackNode prevNode = null; for (int i = 0; i < 2400; i++) { var node = new TrackNode(); node.Number = Nodes.Count; float vergeScale = 8000; node.DistanceToLeftVerge = reader.ReadByte(); node.DistanceToLeftVerge *= GameConfig.TerrainScale * vergeScale; node.DistanceToRightVerge = reader.ReadByte(); node.DistanceToRightVerge *= GameConfig.TerrainScale * vergeScale; node.DistanceToLeftBarrier = reader.ReadByte(); node.DistanceToLeftBarrier *= GameConfig.TerrainScale * vergeScale; node.DistanceToRightBarrier = reader.ReadByte(); node.DistanceToRightBarrier *= GameConfig.TerrainScale * vergeScale; node.Flag1 = reader.ReadByte(); node.Flag2 = reader.ReadByte(); node.Flag3 = reader.ReadByte(); node.NodeProperty = reader.ReadByte(); // unused trackNodes are filled with zeroes, so stop when we have a node with a zero position if (node.DistanceToLeftVerge == 0 && node.DistanceToRightVerge == 0 && node.DistanceToLeftBarrier == 0 && node.DistanceToRightBarrier == 0) { break; } //Debug.WriteLine("{0},{1},{2},{3}", node.b[0], node.b[1], node.b[2], node.b[3]); node.Position = new Vector3(reader.ReadInt32(), reader.ReadInt32(), -reader.ReadInt32()) * GameConfig.TerrainScale; // Slope is stored as a 2's complement value. Convert it back to signed value Int16 slope = reader.ReadInt16(); //bool msbSet = (slope & (0x1 << 13)) != 0; //if (msbSet) //{ // slope = (short)~slope; // slope++; // slope *= -1; //} if (slope > 0x2000) { slope -= 0x3FFF; } node.Slope = slope; node.Slant = reader.ReadInt16(); //weird slant-A float orientation = (float)reader.ReadInt16(); //convert to signed degrees //0 = forwards, 0x1000 = right, 0x2000 = back, 0x3000 = left, 0x3FFF back to forwards if (orientation > 0x2000) { orientation -= 0x3FFF; } node.Orientation = ((orientation / 0x3FFF) * -360); node.unk1 = reader.ReadBytes(2); node.ZOrientation = reader.ReadInt16(); node.Slant = reader.ReadInt16(); // slant-B node.XOrientation = reader.ReadInt16(); node.unk2 = reader.ReadBytes(2); if (prevNode != null) { prevNode.Next = node; node.Prev = prevNode; } prevNode = node; Nodes.Add(node); } // If this is a circuit track, hook the last node up to the first if (Vector3.Distance(Nodes[0].Position, Nodes[Nodes.Count - 1].Position) > 100) { IsOpenRoad = true; } else { prevNode.Next = Nodes[0]; Nodes[0].Prev = prevNode; } for (int i = 0; i < Nodes.Count - 1; i++) { var node = Nodes[i]; var normal = Vector3.Cross(node.GetRightBoundary() - node.GetLeftBoundary(), node.Next.Position - node.GetLeftBoundary()); node.Up = Vector3.Normalize(normal); } }
private void FollowTrackOrientation(TrackNode node, TrackNode nextNode) { var closestPoint1 = Utility.GetClosestPointOnLine(node.GetLeftBoundary(), node.GetRightBoundary(), Position); var closestPoint2 = Utility.GetClosestPointOnLine(nextNode.GetLeftBoundary(), nextNode.GetRightBoundary(), Position); var dist = Distance2d(closestPoint1, closestPoint2); var carDist = Distance2d(closestPoint1, Position); float ratio = Math.Min(carDist / dist, 1.0f); TrackPosition = CurrentNode.Number + ratio; // if the road is sloping downwards and we have enough speed, unstick from ground if (node.Slope - nextNode.Slope > 50 && Speed > 100 && _isOnGround) { _isOnGround = false; _upVelocity = -0.4f; } if (_isOnGround) { Up = Vector3.Lerp(node.Up, nextNode.Up, ratio); Up = Vector3.Normalize(Up); Direction = Vector3.Cross(Up, Right); Direction.Normalize(); } _currentHeightOfTrack = MathHelper.Lerp(closestPoint1.Y, closestPoint2.Y, ratio); if (_currentHeightOfTrack == -9999) { throw new Exception(); } if (_isOnGround) { var newPosition = Position; newPosition.Y = _currentHeightOfTrack; Position = newPosition; } //GameConsole.WriteLine("height: " + _position.Y, 0); //GameConsole.WriteLine("ratio: " + ratio, 1); }
public float GetHeightAtPoint(TrackNode node, Vector3 point) { Vector3 a = node.GetLeftBoundary(); Vector3 b = node.GetRightBoundary(); Vector3 c = node.Next.GetRightBoundary(); Vector3 d = node.Next.GetLeftBoundary(); Vector3 hitLoc; float t; Vector3 pos = point; pos.Y += 100; if (Utility.FindRayTriangleIntersection(ref pos, Vector3.Down, 1000f, ref a, ref b, ref c, out hitLoc, out t)) { return hitLoc.Y; } else if (Utility.FindRayTriangleIntersection(ref pos, Vector3.Down, 1000f, ref a, ref c, ref d, out hitLoc, out t)) { return hitLoc.Y; } else { return -9999; } }