private float GetPointValue(PointLight light, BoundingVolume volume) { if (volume == null) { return(0); } if (!light.Attenuate) { return(GetColorStrength(light)); } else { Vector3 pos = light.Position; float dist = volume.DistanceTo(pos); float strength = GetColorStrength(light); float att = light.Constant + (light.Linear * dist) + (light.Quadratic * dist * dist); return(strength / att); } }
public Bone(Assimp.Node node, Rigging.Bone parent) { Children = new List <Bone>(); m_MatrixType = 1; Name = node.Name; Parent = parent; TransformationMatrix = new Matrix4( node.Transform.A1, node.Transform.B1, node.Transform.C1, node.Transform.D1, node.Transform.A2, node.Transform.B2, node.Transform.C2, node.Transform.D2, node.Transform.A3, node.Transform.B3, node.Transform.C3, node.Transform.D3, node.Transform.A4, node.Transform.B4, node.Transform.C4, node.Transform.D4); m_Scale = TransformationMatrix.ExtractScale(); m_Rotation = TransformationMatrix.ExtractRotation(); m_Translation = TransformationMatrix.ExtractTranslation(); Bounds = new BoundingVolume(); }
private bool FindLeastPenetrating(Vector2 axis, BoundingVolume other, ref Vector2 penetrationNormal, ref float penetrationLength) { float minThis, maxThis, minOther, maxOther; // Tests if separating axis exists if (TestSeparatingAxis(axis, other, out minThis, out maxThis, out minOther, out maxOther)) { return(false); } // Find least penetrating axis float diff = Math.Min(maxOther, maxThis) - Math.Max(minOther, minThis); // Store penetration vector if (diff < penetrationLength) { penetrationLength = diff; penetrationNormal = axis; } return(true); }
public void RayCast(Vector3 from, Vector3 to, RayCastCallback callback) { var rayBounding = BoundingVolume.TowPoints(from, to); var v = FindOrthogonal((to - from).normalized); var abs_v = new Vector3(Mathf.Abs(v.x), Mathf.Abs(v.y), Mathf.Abs(v.z)); var stack = new Stack <int> (); stack.Push(rootNode); while (stack.Count > 0) { var index = stack.Pop(); if (!BoundingVolume.Intersects(rayBounding, nodes[index].bounding)) { continue; } var c = nodes[index].bounding.center; var h = nodes[index].bounding.extents; var separation = Mathf.Abs(Vector3.Dot(v, from - c)) - Vector3.Dot(abs_v, h); if (separation > 0.0f) { continue; } if (nodes[index].isLeaf) { if (callback != null) { callback.Invoke(from, to, nodes[index]); // TODO: Fraction update } } else { stack.Push(nodes[index].childA); stack.Push(nodes[index].childB); } } }
public void UpdateMinTimeToCollide(Vector3 pos, Vector3 velocity, ref float collideTime, ref IGeometry collideShape) { if (!BoundingVolume.CalculateTimeToIntersect(pos, velocity, out float min, out float max) || min > collideTime) { return; } foreach (var shape in GeometryShapes) { float time = shape.CalculateTimeToIntersectWithRay(pos, velocity); if (0 <= time && time < collideTime && shape.IsIntersectWithRay(pos, velocity)) { collideTime = time; collideShape = shape; } } foreach (var node in ChildList) { node.UpdateMinTimeToCollide(pos, velocity, ref collideTime, ref collideShape); } }
/****************************************************************** * 模型加载 完成度90% * *******************************************************************/ private void importPolygonToolStripMenuItem_Click(object sender, EventArgs e) { //打开模型文件对话框 OpenFileDialog openDialog = new OpenFileDialog(); openDialog.Multiselect = true; openDialog.Title = "选择obj文件"; openDialog.Filter = "模型|*.obj";//SerializationEngine.Instance.Filter; if (openDialog.ShowDialog() == DialogResult.OK) { foreach (var str in openDialog.FileNames) { ObjReader objReader = new ObjReader(str); List <Polygon> polyList = new List <Polygon>(objReader.obj); for (int i = 0; i < polyList.Count; i++) { // Get the bounds of the polygon. BoundingVolume boundingVolume = polyList[i].BoundingVolume; float[] extent = new float[3]; polyList[i].BoundingVolume.GetBoundDimensions(out extent[0], out extent[1], out extent[2]); // Get the max extent. float maxExtent = extent.Max(); // Scale so that we are at most 10 units in size. float scaleFactor = maxExtent > 10 ? 10.0f / maxExtent : 1; polyList[i].Transformation.ScaleX = scaleFactor; polyList[i].Transformation.ScaleY = scaleFactor; polyList[i].Transformation.ScaleZ = scaleFactor; polyList[i].AddEffect(objectArcBallEffect); polyList[i].Material = new Material(); sceneControl1.Scene.SceneContainer.AddChild(polyList[i]); } treeView1.Nodes.Clear(); AddElementToTree(sceneControl1.Scene.SceneContainer, treeView1.Nodes); } } }
/// <summary> /// Tests if a bounding volume is contained in the camera's frustum. Used to make /// cull checks. If the volume is null, it will always return ContainmentType.Inside /// </summary> /// <param name="volume">Volume to test</param> /// <returns>Result of the test</returns> public ContainmentType Contains(BoundingVolume volume) { //Assume we're inside to start with ContainmentType rval = ContainmentType.Inside; //If there is no volume, return if (volume == null) { return(rval); } //Check each frustum plane for (int i = 0; i < 6; i++) { Plane plane; PlaneIntersectionType intersection; _frustum.GetPlane(ref i, out plane); volume.Intersects(ref plane, out intersection); switch (intersection) { case PlaneIntersectionType.Back: //It's outside one plane, therefore its entirely outside the frustum return(ContainmentType.Outside); case PlaneIntersectionType.Front: //Keep checking break; case PlaneIntersectionType.Intersects: //If it intersects just one, set rval rval = ContainmentType.Intersects; break; } } return(rval); }
/// <summary> /// Handles the Click event of the importPolygonToolStripMenuItem control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> private void importPolygonToolStripMenuItem_Click(object sender, EventArgs e) { // Show a file open dialog. OpenFileDialog openDialog = new OpenFileDialog(); //openDialog.Filter = SerializationEngine.Instance.Filter; if (openDialog.ShowDialog() == DialogResult.OK) { var file = FileFormatWavefront.FileFormatObj.Load(openDialog.FileName, false); file.Model. Scene scene = SerializationEngine.Instance.LoadScene(openDialog.FileName); if (scene != null) { foreach (var polygon in scene.SceneContainer.Traverse <Polygon>()) { // Get the bounds of the polygon. BoundingVolume boundingVolume = polygon.BoundingVolume; float[] extent = new float[3]; polygon.BoundingVolume.GetBoundDimensions(out extent[0], out extent[1], out extent[2]); // Get the max extent. float maxExtent = extent.Max(); // Scale so that we are at most 10 units in size. float scaleFactor = maxExtent > 10 ? 10.0f / maxExtent : 1; polygon.Transformation.ScaleX = scaleFactor; polygon.Transformation.ScaleY = scaleFactor; polygon.Transformation.ScaleZ = scaleFactor; polygon.Freeze(openGLControl1.OpenGL); polygons.Add(polygon); } } } }
public Bone(EndianBinaryReader reader, string name) { Children = new List <Bone>(); Name = name; m_MatrixType = reader.ReadInt16(); m_UnknownIndex = reader.ReadByte(); reader.SkipByte(); m_Scale = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); short xRot = reader.ReadInt16(); short yRot = reader.ReadInt16(); short zRot = reader.ReadInt16(); float xConvRot = xRot * (180 / 32768f); float yConvRot = yRot * (180 / 32768f); float zConvRot = zRot * (180 / 32768f); Vector3 rotFull = new Vector3(xConvRot * (float)(Math.PI / 180f), yConvRot * (float)(Math.PI / 180f), zConvRot * (float)(Math.PI / 180f)); m_Rotation = Quaternion.FromAxisAngle(new Vector3(0, 0, 1), rotFull.Z) * Quaternion.FromAxisAngle(new Vector3(0, 1, 0), rotFull.Y) * Quaternion.FromAxisAngle(new Vector3(1, 0, 0), rotFull.X); reader.SkipInt16(); m_Translation = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); TransformationMatrix = Matrix4.CreateScale(m_Scale) * Matrix4.CreateFromQuaternion(m_Rotation) * Matrix4.CreateTranslation(m_Translation); Bounds = new BoundingVolume(reader); }
public bool Intersects(BoundingVolume other, out Vector2 penetrationNormal, out float penetrationLength) { penetrationNormal = Vector2.zero; penetrationLength = float.MaxValue; // Axis of this if (Axis != null) { foreach (Vector2 axis in Axis) { if (!FindLeastPenetrating(axis, other, ref penetrationNormal, ref penetrationLength)) { return(false); } } } // Axis of other if (other.Axis != null) { foreach (Vector2 axis in other.Axis) { if (!FindLeastPenetrating(axis, other, ref penetrationNormal, ref penetrationLength)) { return(false); } } } // Flip penetrationDirection to point away from this if (Vector2.Dot(other.Position - Position, penetrationNormal) > 0.0f) { penetrationNormal = penetrationNormal * -1.0f; } return(true); }
private SHP1(EndianBinaryReader reader, int offset) { Shapes = new List <Shape>(); RemapTable = new List <int>(); reader.BaseStream.Seek(offset, System.IO.SeekOrigin.Begin); reader.SkipInt32(); int shp1Size = reader.ReadInt32(); int entryCount = reader.ReadInt16(); reader.SkipInt16(); int shapeHeaderDataOffset = reader.ReadInt32(); int shapeRemapTableOffset = reader.ReadInt32(); int unusedOffset = reader.ReadInt32(); int attributeDataOffset = reader.ReadInt32(); int matrixIndexDataOffset = reader.ReadInt32(); int primitiveDataOffset = reader.ReadInt32(); int matrixDataOffset = reader.ReadInt32(); int PacketInfoDataOffset = reader.ReadInt32(); reader.BaseStream.Seek(offset + shapeRemapTableOffset, System.IO.SeekOrigin.Begin); // Remap table for (int i = 0; i < entryCount; i++) { RemapTable.Add(reader.ReadInt16()); } int highestIndex = J3DUtility.GetHighestValue(RemapTable); // Packet data List <Tuple <int, int> > packetData = new List <Tuple <int, int> >(); // <packet size, packet offset> int packetDataCount = (shp1Size - PacketInfoDataOffset) / 8; reader.BaseStream.Seek(PacketInfoDataOffset + offset, System.IO.SeekOrigin.Begin); for (int i = 0; i < packetDataCount; i++) { packetData.Add(new Tuple <int, int>(reader.ReadInt32(), reader.ReadInt32())); } // Matrix data List <Tuple <int, int> > matrixData = new List <Tuple <int, int> >(); // <index count, start index> List <int[]> matrixIndices = new List <int[]>(); int matrixDataCount = (PacketInfoDataOffset - matrixDataOffset) / 8; reader.BaseStream.Seek(matrixDataOffset + offset, System.IO.SeekOrigin.Begin); for (int i = 0; i < matrixDataCount; i++) { reader.SkipInt16(); matrixData.Add(new Tuple <int, int>(reader.ReadInt16(), reader.ReadInt32())); } for (int i = 0; i < matrixDataCount; i++) { reader.BaseStream.Seek(offset + matrixIndexDataOffset + (matrixData[i].Item2 * 2), System.IO.SeekOrigin.Begin); int[] indices = new int[matrixData[i].Item1]; for (int j = 0; j < matrixData[i].Item1; j++) { indices[j] = reader.ReadInt16(); } matrixIndices.Add(indices); } // Shape data List <Shape> tempShapeList = new List <Shape>(); reader.BaseStream.Seek(offset + shapeHeaderDataOffset, System.IO.SeekOrigin.Begin); for (int i = 0; i < highestIndex + 1; i++) { byte matrixType = reader.ReadByte(); reader.SkipByte(); int packetCount = reader.ReadInt16(); int shapeAttributeOffset = reader.ReadInt16(); int shapeMatrixDataIndex = reader.ReadInt16(); int firstPacketIndex = reader.ReadInt16(); reader.SkipInt16(); BoundingVolume shapeVol = new BoundingVolume(reader); long curOffset = reader.BaseStream.Position; ShapeVertexDescriptor descriptor = new ShapeVertexDescriptor(reader, offset + attributeDataOffset + shapeAttributeOffset); List <Packet> shapePackets = new List <Packet>(); for (int j = 0; j < packetCount; j++) { int packetSize = packetData[j + firstPacketIndex].Item1; int packetOffset = packetData[j + firstPacketIndex].Item2; Packet pack = new Packet(packetSize, packetOffset + primitiveDataOffset + offset, matrixIndices[j + firstPacketIndex]); pack.ReadPrimitives(reader, descriptor); shapePackets.Add(pack); } tempShapeList.Add(new Shape(descriptor, shapeVol, shapePackets, matrixType)); reader.BaseStream.Seek(curOffset, System.IO.SeekOrigin.Begin); } for (int i = 0; i < entryCount; i++) { Shapes.Add(tempShapeList[RemapTable[i]]); } reader.BaseStream.Seek(offset + shp1Size, System.IO.SeekOrigin.Begin); }
// TODO: create proxy, destory proxy, move proxy public void Query(BoundingVolume bounds, QueryCallback callback) { // TODO: Query method }
public void Query(List<ICullable> results, BoundingVolume volume) { root.Query(results, volume); }
/// <summary> /// Convienence method to propagate a model bounding volume down the scene graph. /// </summary> /// <param name="volume">Bounding Volume</param> public abstract void SetModelBound(BoundingVolume volume);
void recalcBoundingVolumeKDop14(IList <SpatialVectorDouble> vertices) { boundingVolume = new BoundingVolume(); boundingVolume.kdop = KDop.calculateKdopFromVertices(vertices, 14); }
public void Query(List<ICullable> results, BoundingVolume volume) { var containmentType = volume.Contains(Bounds); if (containmentType == ContainmentType.Intersects) { foreach (var item in Items) { if (volume.Contains(item.Bounds) != ContainmentType.Disjoint) results.Add(item); } foreach (var child in Children) { child.Query(results, volume); } } else if (containmentType == ContainmentType.Contains) AddAll(results); }
public static BoundingVolume Combine(BoundingVolume a, BoundingVolume b) { return(new BoundingVolume(Vector3.Min(a.min, b.min), Vector3.Max(a.max, b.max))); }
public static bool Intersects(BoundingVolume a, BoundingVolume b) { return(a.min.x <= b.max.x && a.max.x >= b.min.x && a.min.y <= b.max.y && a.max.y >= b.min.y && a.min.z <= b.max.z && a.max.z >= b.min.z); }
public Collider(BoundingVolume bound) { this.bound = bound; }
async Task LoadLVL() { loadingState = "Loading level memory"; await WaitIfNecessary(); files_array[Mem.Lvl].GotoHeader(); Reader reader = files_array[Mem.Lvl].reader; long totalSize = reader.BaseStream.Length; reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); Pointer.Read(reader); Pointer.Read(reader); reader.ReadString(0x1E); reader.ReadString(0x1E); //Pointer off_animBankLvl = null; loadingState = "Loading globals"; await WaitIfNecessary(); globals.off_transitDynamicWorld = null; globals.off_actualWorld = Pointer.Read(reader); globals.off_dynamicWorld = Pointer.Read(reader); globals.off_fatherSector = Pointer.Read(reader); // It is I, Father Sector. globals.off_firstSubMapPosition = Pointer.Read(reader); globals.num_always = reader.ReadUInt32(); globals.spawnablePersos = LinkedList <Perso> .ReadHeader(reader, Pointer.Current(reader), LinkedList.Type.Double); Pointer.Read(reader); globals.off_always_reusableSO = Pointer.Read(reader); // There are (num_always) empty SuperObjects starting with this one. globals.off_always_reusableUnknown1 = Pointer.Read(reader); // (num_always) * 0x2c blocks globals.off_always_reusableUnknown2 = Pointer.Read(reader); // (num_always) * 0x4 blocks // Settings for perso in fix? Lights? Pointer.Read(reader); Pointer.Read(reader); Pointer.Read(reader); Pointer.Read(reader); // perso Pointer.Read(reader); Pointer off_unknown_first = Pointer.Read(reader); Pointer off_unknown_last = Pointer.Read(reader); uint num_unknown = reader.ReadUInt32(); families = LinkedList <Family> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Double); Pointer off_alwaysActiveCharacters_first = Pointer.Read(reader); Pointer off_alwaysActiveCharacters_last = Pointer.Read(reader); uint num_alwaysActiveChars = reader.ReadUInt32(); Pointer.Read(reader); reader.ReadUInt32(); globals.off_camera = Pointer.Read(reader); reader.ReadUInt32(); reader.ReadByte(); reader.ReadByte(); reader.ReadByte(); reader.ReadByte(); //print(Pointer.Current(reader)); Pointer.Read(reader); Pointer off_unk0_first = Pointer.Read(reader); Pointer off_unk0_last = Pointer.Read(reader); uint num_unk = reader.ReadUInt32(); Pointer off_unk = Pointer.Read(reader); loadingState = "Loading level textures"; await ReadTexturesLvl(reader, Pointer.Current(reader)); Pointer.Read(reader); // maybe perso in fix reader.ReadUInt32(); Pointer.Read(reader); uint num_soundMaterials = reader.ReadUInt32(); Pointer off_soundMaterials = Pointer.Read(reader); Pointer off_unkBlocks = Pointer.Read(reader); // 3 blocks of 0xb4 uint num_unkBlocks = reader.ReadUInt32(); Pointer.Read(reader); reader.ReadUInt32(); BoundingVolume.Read(reader, Pointer.Current(reader), BoundingVolume.Type.Box); reader.ReadUInt16(); reader.ReadUInt16(); Pointer.Read(reader); reader.ReadUInt32(); uint num_ipo = reader.ReadUInt32(); // Entries with an IPO SO pointer and a mesh pointer, then a pointer to an empty offset. RLI table? Pointer off_ipo = Pointer.Read(reader); reader.ReadBytes(0x30); uint num_unkPtrs = reader.ReadUInt32(); for (int i = 0; i < num_unkPtrs; i++) { Pointer.Read(reader); } reader.ReadBytes(0x10d8); // that's a lot of null bytes uint num_shadowDQ = reader.ReadUInt32(); for (int i = 0; i < 21; i++) { Pointer.Read(reader); } uint num_shadowHQ = reader.ReadUInt32(); for (int i = 0; i < 21; i++) { Pointer.Read(reader); } localization = FromOffsetOrRead <LocalizationStructure>(reader, Pointer.Current(reader), inline: true); //print("Yay " + Pointer.Current(reader)); reader.ReadUInt16(); reader.ReadUInt16(); reader.ReadUInt32(); uint num_lightmaps = reader.ReadUInt32(); Pointer off_lightmapUVs = Pointer.Read(reader); Pointer.DoAt(ref reader, off_lightmapUVs, () => { off_lightmapUV = new Pointer[num_lightmaps]; for (int i = 0; i < num_lightmaps; i++) { reader.ReadUInt32(); reader.ReadByte(); reader.ReadBytes(3); off_lightmapUV[i] = Pointer.Read(reader); } }); reader.ReadByte(); reader.ReadBytes(3); reader.ReadUInt32(); reader.ReadUInt32(); Pointer.Read(reader); Pointer.Read(reader); Pointer.Read(reader); // Parse actual world & always structure loadingState = "Loading families"; await WaitIfNecessary(); ReadFamilies(reader); loadingState = "Loading superobject hierarchy"; await WaitIfNecessary(); ReadSuperObjects(reader); loadingState = "Loading always structure"; await WaitIfNecessary(); ReadAlways(reader); loadingState = "Filling in cross-references"; await WaitIfNecessary(); ReadCrossReferences(reader); }
public static SuperObject Read(Reader reader, Pointer off_so, SuperObject parent = null) { MapLoader l = MapLoader.Loader; if (IsParsed(off_so)) { return(null); } bool isValidNode = true; SuperObject so = new SuperObject(off_so); l.superObjects.Add(so); // Global list of superobjects (all) if (parent != null) { so.parent = parent; } so.typeCode = reader.ReadUInt32(); // 0 - 4 so.off_data = Pointer.Read(reader); // 4 - 8 so.children = LinkedList <SuperObject> .ReadHeader(reader, Pointer.Current(reader), LinkedList.Type.Double); // 8 - 14 so.off_brother_next = Pointer.Read(reader); // 14 - 18 so.off_brother_prev = Pointer.Read(reader); // 18 - 1C so.off_parent = Pointer.Read(reader); // 1C - 20 so.off_matrix = Pointer.Read(reader); // 0x20->0x24 so.off_staticMatrix = Pointer.Read(reader); // other matrix so.globalMatrix = reader.ReadInt32(); // 0x28 -> 0x2C so.drawFlags = SuperObjectDrawFlags.Read(reader); so.flags = SuperObjectFlags.Read(reader); // 0x30->0x34 if (Settings.s.engineVersion == Settings.EngineVersion.R3) { reader.ReadUInt32(); // Visual Bounding Volume? } Pointer off_boundingVolume = Pointer.Read(reader); //l.print("SuperObject T" + so.typeCode + ": " + off_so + " - " + so.off_matrix); Pointer.DoAt(ref reader, so.off_matrix, () => { so.matrix = Matrix.Read(reader, so.off_matrix); }); /*Pointer.DoAt(ref reader, so.off_matrix2, () => { * so.matrix2 = Matrix.Read(reader, so.off_matrix2); * if (so.matrix == null) { * pos = so.matrix2.GetPosition(convertAxes: true); * rot = so.matrix2.GetRotation(convertAxes: true); * scale = so.matrix2.GetScale(convertAxes: true); * } * });*/ so.type = GetSOType(so.typeCode); switch (so.type) { case Type.IPO: Pointer.DoAt(ref reader, so.off_data, () => { so.data = IPO.Read(reader, so.off_data, so); }); break; case Type.IPO_2: Pointer.DoAt(ref reader, so.off_data, () => { l.print("IPO with code 0x40 at offset " + so.off_data); so.data = IPO.Read(reader, so.off_data, so); }); break; case Type.PhysicalObject: if (!Settings.s.loadFromMemory) { Pointer.DoAt(ref reader, so.off_data, () => { so.data = PhysicalObject.Read(reader, so.off_data, so); }); } break; case Type.Perso: Pointer.DoAt(ref reader, so.off_data, () => { so.data = Perso.Read(reader, so.off_data, so); }); break; case Type.World: so.data = World.New(so); //print("parsing world superobject with " + num_children + " children"); break; case Type.Sector: Pointer.DoAt(ref reader, so.off_data, () => { so.data = Sector.Read(reader, so.off_data, so); }); break; case Type.GeometricObject: Pointer.DoAt(ref reader, so.off_data, () => { so.data = Visual.GeometricObject.Read(reader, so.off_data); }); break; case Type.GeometricShadowObject: Pointer.DoAt(ref reader, so.off_data, () => { so.data = Visual.GeometricShadowObject.Read(reader, so.off_data, so); }); break; default: l.print("Unknown SO type " + so.typeCode + " at " + so.offset + " - " + so.off_data); //isValidNode = false; break; } Pointer.DoAt(ref reader, off_boundingVolume, () => { //l.print(so.type + " - " + so.offset + " - " + off_boundingVolume); if (Settings.s.engineVersion <= Settings.EngineVersion.Montreal) { so.boundingVolumeTT = GeometricObjectCollide.Read(reader, off_boundingVolume, isBoundingVolume: true); } else { so.boundingVolume = BoundingVolume.Read(reader, off_boundingVolume, so.flags.HasFlag(SuperObjectFlags.Flags.BoundingBoxInsteadOfSphere) ? BoundingVolume.Type.Box : BoundingVolume.Type.Sphere); } }); if (isValidNode) { so.children.ReadEntries(ref reader, (off_child) => { SuperObject child = SuperObject.FromOffsetOrRead(off_child, reader, parent: so); child.parent = so; return(child); }, LinkedList.Flags.HasHeaderPointers); } return(so); }
public RectangleHitTestResultTreeLeaf(RectangleHitTestResultTreeNode parent, DependencyObject objectHit, BoundingVolume transformedFrustum, Ray3D frustumCenterRay, Matrix3D transform) { this.parent = parent; this.objectHit = objectHit; this.transformedFrustum = transformedFrustum; this.frustumCenterRay = frustumCenterRay; this.compositeTransform = transform; }
public MeshGeometryRectangleHitTestResultTreeLeaf(RectangleHitTestResultTreeNode parent, DependencyObject objectHit, MeshGeometry3D geometryHit, BoundingVolume transformedFrustum, Ray3D frustumCenterRay, Matrix3D transform, Material frontMaterial, Material backMaterial) : base(parent, objectHit, transformedFrustum, frustumCenterRay, transform) { this.geometryHit = geometryHit; this.frontMaterial = frontMaterial; this.backMaterial = backMaterial; }
public static SuperObject Read(Reader reader, Pointer off_so, SuperObject parent = null) { MapLoader l = MapLoader.Loader; if (IsParsed(off_so)) { return(null); } bool isValidNode = true; SuperObject so = new SuperObject(off_so); l.superObjects.Add(so); // Global list of superobjects (all) if (parent != null) { so.parent = parent; } so.typeCode = reader.ReadUInt32(); // 0 - 4 so.off_data = Pointer.Read(reader); // 4 - 8 so.children = LinkedList <SuperObject> .ReadHeader(reader, Pointer.Current(reader), LinkedList.Type.Double); // 8 - 14 so.off_brother_next = Pointer.Read(reader); // 14 - 18 so.off_brother_prev = Pointer.Read(reader); // 18 - 1C so.off_parent = Pointer.Read(reader); // 1C - 20 so.off_matrix = Pointer.Read(reader); // 0x20->0x24 so.off_staticMatrix = Pointer.Read(reader); // other matrix so.globalMatrix = reader.ReadInt32(); // 0x28 -> 0x2C so.drawFlags = SuperObjectDrawFlags.Read(reader); so.flags = SuperObjectFlags.Read(reader); // 0x30->0x34 if (Settings.s.engineVersion == Settings.EngineVersion.R3) { reader.ReadUInt32(); } Pointer off_boundingVolume = Pointer.Read(reader); //l.print("SuperObject T" + so.typeCode + ": " + off_so + " - " + so.off_matrix); //R3Pointer.Read(reader); // a copy of the matrix right after, at least in R3GC Vector3 pos = Vector3.zero; Vector3 scale = Vector3.one; Quaternion rot = Quaternion.identity; Pointer.DoAt(ref reader, so.off_matrix, () => { so.matrix = Matrix.Read(reader, so.off_matrix); pos = so.matrix.GetPosition(convertAxes: true); rot = so.matrix.GetRotation(convertAxes: true); scale = so.matrix.GetScale(convertAxes: true); }); /*Pointer.DoAt(ref reader, so.off_matrix2, () => { * so.matrix2 = Matrix.Read(reader, so.off_matrix2); * if (so.matrix == null) { * pos = so.matrix2.GetPosition(convertAxes: true); * rot = so.matrix2.GetRotation(convertAxes: true); * scale = so.matrix2.GetScale(convertAxes: true); * } * });*/ so.type = GetSOType(so.typeCode); switch (so.type) { case Type.IPO: Pointer.DoAt(ref reader, so.off_data, () => { so.data = IPO.Read(reader, so.off_data, so); }); break; case Type.IPO_2: Pointer.DoAt(ref reader, so.off_data, () => { l.print("IPO with code 0x40 at offset " + so.off_data); so.data = IPO.Read(reader, so.off_data, so); }); break; case Type.PhysicalObject: if (!Settings.s.loadFromMemory) { Pointer.DoAt(ref reader, so.off_data, () => { so.data = PhysicalObject.Read(reader, so.off_data, so); }); } break; case Type.Perso: Pointer.DoAt(ref reader, so.off_data, () => { so.data = Perso.Read(reader, so.off_data, so); }); break; case Type.World: so.data = World.New(so); //print("parsing world superobject with " + num_children + " children"); break; case Type.Sector: Pointer.DoAt(ref reader, so.off_data, () => { so.data = Sector.Read(reader, so.off_data, so); }); break; case Type.GeometricObject: Pointer.DoAt(ref reader, so.off_data, () => { so.data = Visual.GeometricObject.Read(reader, so.off_data); }); break; case Type.GeometricShadowObject: Pointer.DoAt(ref reader, so.off_data, () => { so.data = Visual.GeometricShadowObject.Read(reader, so.off_data, so); }); break; default: l.print("Unknown SO type " + so.typeCode + " at " + so.offset + " - " + so.off_data); //isValidNode = false; break; } Pointer.DoAt(ref reader, off_boundingVolume, () => { //l.print(off_boundingVolume); so.boundingVolume = BoundingVolume.Read(reader, off_boundingVolume, so.flags.HasFlag(SuperObjectFlags.Flags.BoundingBoxInsteadOfSphere) ? BoundingVolume.Type.Box : BoundingVolume.Type.Sphere); }); if (so.Gao != null) { if (parent != null && parent.Gao != null) { so.Gao.transform.parent = parent.Gao.transform; } so.Gao.transform.localPosition = pos; so.Gao.transform.localRotation = rot; so.Gao.transform.localScale = scale; SuperObjectComponent soc = so.Gao.AddComponent <SuperObjectComponent>(); so.Gao.layer = LayerMask.NameToLayer("SuperObject"); soc.so = so; if (so.boundingVolume != null) { if (so.boundingVolume.type == BoundingVolume.Type.Box) { BoxCollider collider = so.Gao.AddComponent <BoxCollider>(); collider.center = so.boundingVolume.Center; collider.center -= so.Gao.transform.position; collider.size = so.boundingVolume.Size; } else { SphereCollider collider = so.Gao.AddComponent <SphereCollider>(); collider.center = so.boundingVolume.Center; collider.radius = so.boundingVolume.sphereRadius; } } } if (isValidNode) { so.children.ReadEntries(ref reader, (off_child) => { SuperObject child = SuperObject.Read(reader, off_child, so); child.parent = so; return(child); }, LinkedList.Flags.HasHeaderPointers); } return(so); }
public void InsertLeaf(int objectIndex, BoundingVolume bounding) { var leaf = AllocateNode(); nodes[leaf].bounding = bounding; nodes[leaf].dataId = objectIndex; if (rootNode == -1) { rootNode = leaf; return; } // Stage 1: find the best sibling for the new leaf var sibling = PickBestSibling(leaf); // Stage 2: create a new parent var oldParent = nodes[sibling].parent; var newParent = AllocateNode(); nodes[newParent].parent = oldParent; nodes[newParent].bounding = BoundingVolume.Combine(nodes[leaf].bounding, nodes[sibling].bounding); nodes[newParent].height = nodes[sibling].height + 1; if (oldParent != -1) { // The sibling was not the root. if (nodes[oldParent].childA == sibling) { nodes[oldParent].childA = newParent; } else { nodes[oldParent].childB = newParent; } nodes[newParent].childA = sibling; nodes[newParent].childB = leaf; nodes[sibling].parent = newParent; nodes[leaf].parent = newParent; } else { // The sibling was the root. nodes[newParent].childA = sibling; nodes[newParent].childB = leaf; nodes[sibling].parent = newParent; nodes[leaf].parent = newParent; rootNode = newParent; } // Stage 3: walk back up the tree refitting AABBs var index = nodes[leaf].parent; while (index != -1) { index = Balance(index); var childA = nodes[index].childA; var childB = nodes[index].childB; nodes[index].height = 1 + Mathf.Max(nodes[childA].height, nodes[childB].height); nodes[index].bounding = BoundingVolume.Combine(nodes[childA].bounding, nodes[childB].bounding); index = nodes[index].parent; } }
public static Sector Read(Reader reader, Pointer offset, SuperObject so) { MapLoader l = MapLoader.Loader; Sector s = new Sector(offset, so); s.name = "Sector @ " + offset + ", SPO @ " + so.offset; //l.print(s.name); if (Settings.s.engineVersion <= Settings.EngineVersion.Montreal) { if (Settings.s.game == Settings.Game.TTSE) { reader.ReadUInt32(); // always 1 or 0. whether the sector is active or not? } Pointer off_collideObj = Pointer.Read(reader); Pointer.DoAt(ref reader, off_collideObj, () => { //CollideMeshObject collider = CollideMeshObject.Read(reader, off_collideObj); // This has the exact same structure as a CollideMeshObject but with a sector superobject as material for the collieMeshElements }); LinkedList <int> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Double); // "environments list" LinkedList <int> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Double); // "surface list" } s.persos = LinkedList <Perso> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Double); s.staticLights = LinkedList <LightInfo> .Read(ref reader, Pointer.Current(reader), (off_element) => { LightInfo li = l.FromOffsetOrRead <LightInfo>(reader, off_element); if (li != null) { li.containingSectors.Add(s); } return(li); }, flags : LinkedList.Flags.ElementPointerFirst | LinkedList.Flags.ReadAtPointer | ((Settings.s.hasLinkedListHeaderPointers) ? LinkedList.Flags.HasHeaderPointers : LinkedList.Flags.NoPreviousPointersForDouble), type : LinkedList.Type.Minimize ); s.dynamicLights = LinkedList <int> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Double); if (Settings.s.engineVersion <= Settings.EngineVersion.Montreal) { LinkedList <int> .ReadHeader(reader, Pointer.Current(reader)); // "streams list", probably related to water } s.neighbors = LinkedList <NeighborSector> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Minimize); s.sectors_unk1 = LinkedList <NeighborSector> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Minimize); s.sectors_unk2 = LinkedList <Sector> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Minimize); LinkedList <int> .ReadHeader(reader, Pointer.Current(reader)); // Placeholder LinkedList <int> .ReadHeader(reader, Pointer.Current(reader)); // Placeholder if (Settings.s.engineVersion > Settings.EngineVersion.Montreal) { s.sectorBorder = BoundingVolume.Read(reader, Pointer.Current(reader), BoundingVolume.Type.Box); reader.ReadUInt32(); if (Settings.s.game == Settings.Game.R2Revolution || Settings.s.game == Settings.Game.LargoWinch) { s.isSectorVirtual = reader.ReadByte(); reader.ReadByte(); s.sectorPriority = reader.ReadByte(); reader.ReadByte(); } else { s.isSectorVirtual = reader.ReadByte(); reader.ReadByte(); reader.ReadByte(); s.sectorPriority = reader.ReadByte(); if (Settings.s.engineVersion <= Settings.EngineVersion.R2) { s.off_skyMaterial = Pointer.Read(reader); s.skyMaterial = VisualMaterial.FromOffsetOrRead(s.off_skyMaterial, reader); } else { reader.ReadUInt32(); } reader.ReadByte(); if (Settings.s.hasNames) { s.name = reader.ReadString(0x104); l.print(s.name); } } } else { if (Settings.s.engineVersion == Settings.EngineVersion.Montreal) { reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); reader.ReadUInt32(); } if (Settings.s.game != Settings.Game.TTSE) { reader.ReadUInt32(); } Pointer off_name = Pointer.Read(reader); Pointer.DoAt(ref reader, off_name, () => { s.name = reader.ReadNullDelimitedString() + " @ " + offset; }); } /*if(num_subsectors_unk > 0 && off_subsector_unk_first != null) { // only for father sector * R3Pointer off_subsector_next = off_subsector_unk_first; * for (int i = 0; i < num_subsectors_unk; i++) { * R3Pointer.Goto(ref reader, off_subsector_next); * R3Pointer off_subsector = R3Pointer.Read(reader); * off_subsector_next = R3Pointer.Read(reader); * R3Pointer off_subsector_prev = R3Pointer.Read(reader); * R3Pointer off_sector_start = R3Pointer.Read(reader); * if (off_subsector != null) { * sect.neighborsPointers.Add(off_subsector); * } * } * }*/ l.sectors.Add(s); return(s); }
int PickBestSibling(int leaf) { var sibling = rootNode; var leafBounding = nodes[leaf].bounding; while (nodes[sibling].isLeaf == false) { var childA = nodes[sibling].childA; var childB = nodes[sibling].childB; float area = nodes[sibling].bounding.GetPerimeter(); var combinedBounding = BoundingVolume.Combine(nodes[sibling].bounding, leafBounding); float combinedArea = combinedBounding.GetPerimeter(); // Cost of creating a new parent for this node and the new leaf float cost = 2.0f * combinedArea; // Minimum cost of pushing the leaf further down the tree float inheritanceCost = 2.0f * (combinedArea - area); // Cost of descending into childA float costA; if (nodes[childA].isLeaf) { costA = BoundingVolume.Combine(leafBounding, nodes[childA].bounding).GetPerimeter() + inheritanceCost; } else { float oldArea = nodes[childA].bounding.GetPerimeter(); float newArea = BoundingVolume.Combine(leafBounding, nodes[childA].bounding).GetPerimeter(); costA = (newArea - oldArea) + inheritanceCost; } // Cost of descending into child2 float costB; if (nodes[childB].isLeaf) { costB = BoundingVolume.Combine(leafBounding, nodes[childB].bounding).GetPerimeter() + inheritanceCost; } else { float oldArea = nodes[childB].bounding.GetPerimeter(); float newArea = BoundingVolume.Combine(leafBounding, nodes[childB].bounding).GetPerimeter(); costB = (newArea - oldArea) + inheritanceCost; } // Descend according to the minimum cost. if (cost < costA && cost < costB) { break; } // Descend if (costA < costB) { sibling = childA; } else { sibling = childB; } } return(sibling); }
private bool TestGeometryAgainstFrustum(MeshGeometry3D rawGeometry, Material frontMaterial, Material backMaterial, BoundingVolume frustum, Matrix3D transform) { if (rawGeometry == null) { return(false); } TriangleEnumerator triangleEnumerator = new TriangleEnumerator(rawGeometry.Positions, rawGeometry.TriangleIndices); Point3D[] point3DArray = new Point3D[3]; foreach (int[] numArray in triangleEnumerator.TriangleList) { point3DArray[0] = rawGeometry.Positions[numArray[0]]; point3DArray[1] = rawGeometry.Positions[numArray[1]]; point3DArray[2] = rawGeometry.Positions[numArray[2]]; transform.Transform(point3DArray); if (frustum.IsPolygonContainedOrIntersecting(point3DArray)) { double num = Vector3D.DotProduct(Vector3D.CrossProduct(point3DArray[1] - point3DArray[0], point3DArray[2] - point3DArray[0]), point3DArray[0] - this.frustumCenterRay.Origin); if (Tolerances.LessThanOrClose(num, 0.0) && frontMaterial != null || Tolerances.GreaterThan(num, 0.0) && backMaterial != null) { return(true); } } } return(false); }
public bool CollidesWith(BoundingVolume v) { return(v.CollidesWith(this)); }