Beispiel #1
0
        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);
            }
        }
Beispiel #2
0
        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);
    }
Beispiel #4
0
    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);
            }
        }
    }
Beispiel #5
0
        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);
            }
        }
Beispiel #6
0
        /******************************************************************
         *   模型加载 完成度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);
                }
            }
        }
Beispiel #7
0
        /// <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);
        }
Beispiel #8
0
        /// <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);
                    }
                }
            }
        }
Beispiel #9
0
        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);
    }
Beispiel #11
0
        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);
        }
Beispiel #12
0
    // TODO: create proxy, destory proxy, move proxy

    public void Query(BoundingVolume bounds, QueryCallback callback)
    {
        // TODO: Query method
    }
Beispiel #13
0
 public void Query(List<ICullable> results, BoundingVolume volume)
 {
     root.Query(results, volume);
 }
Beispiel #14
0
 /// <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);
Beispiel #15
0
 void recalcBoundingVolumeKDop14(IList <SpatialVectorDouble> vertices)
 {
     boundingVolume      = new BoundingVolume();
     boundingVolume.kdop = KDop.calculateKdopFromVertices(vertices, 14);
 }
Beispiel #16
0
            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);
            }
Beispiel #17
0
 public static BoundingVolume Combine(BoundingVolume a, BoundingVolume b)
 {
     return(new BoundingVolume(Vector3.Min(a.min, b.min), Vector3.Max(a.max, b.max)));
 }
Beispiel #18
0
 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);
 }
Beispiel #19
0
 public Collider(BoundingVolume bound)
 {
     this.bound = bound;
 }
Beispiel #20
0
        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);
        }
Beispiel #21
0
        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);
        }
Beispiel #22
0
 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;
 }
Beispiel #24
0
        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);
        }
Beispiel #25
0
    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;
        }
    }
Beispiel #26
0
        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);
        }
Beispiel #27
0
    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);
        }
Beispiel #29
0
 public bool CollidesWith(BoundingVolume v)
 {
     return(v.CollidesWith(this));
 }