Beispiel #1
0
        BatchInfo GetCreateBatchInfo(ResourceHandle <Material> materialHandle)
        {
            if (!batches.ContainsKey(materialHandle.Id))
            {
                var batch = new RenderBatch
                {
                    GeometryBuffer = gb,
                    RenderLayer    = RenderLayer.Overlays,
                    PrimitiveType  = PrimitiveType.Quads,
                    Material       = materialHandle
                };

                var batchInfo = new BatchInfo {
                    Batch = batch, Ranges = new List <int>()
                };
                batches[materialHandle.Id] = batchInfo;
            }

            return(batches[materialHandle.Id]);
        }
Beispiel #2
0
        public void Update(RenderBatch batch)
        {
            for (var i = 0; i < batch.UpdatedComponents.Count; i++)
            {
                var diff        = batch.UpdatedComponents.Array[i];
                var componentId = diff.ComponentId;
                var edits       = diff.Edits;
                UpdateComponent(batch, componentId, edits);
            }

            for (var i = 0; i < batch.DisposedComponentIDs.Count; i++)
            {
                DisposeComponent(batch.DisposedComponentIDs.Array[i]);
            }

            for (var i = 0; i < batch.DisposedEventHandlerIDs.Count; i++)
            {
                DisposeEventHandler(batch.DisposedEventHandlerIDs.Array[i]);
            }
        }
Beispiel #3
0
        protected override void OnLoad(EventArgs e)
        {
            Events.EventHandler.RegisterEvents(this);
            Logger.Name = "GSharp";

            GL.ClearColor(0.1f, 0.2f, 0.5f, 0.0f);
            GL.Enable(EnableCap.ScissorTest);

            Atlas = new TextureAtlas("atlas.png", "atlas.desc", TextureFilter.Nearest);

            Shader shader        = new Shader("Graphics/OpenGL/Shaders/vertex.glsl", "Graphics/OpenGL/Shaders/fragment.glsl");
            Shader textureShader = new Shader("Graphics/OpenGL/Shaders/vertexTex.glsl", "Graphics/OpenGL/Shaders/fragmentTex.glsl");
            Shader atlasShader   = new Shader("Graphics/OpenGL/Shaders/vertexAtlas.glsl", "Graphics/OpenGL/Shaders/fragmentTex.glsl");

            Batch        = new RenderBatch(new VertexComponent[] { VertexComponent.Coord, VertexComponent.Color }, shader, false);
            TextureBatch = new RenderBatch(new VertexComponent[] { VertexComponent.Coord, VertexComponent.TexCoord }, textureShader, false);
            AtlasBatch   = new RenderBatch(new VertexComponent[] { VertexComponent.Coord, VertexComponent.TexCoord, VertexComponent.TexLocation }, atlasShader, false);
            AtlasBatch.SetAtlas(Atlas);

            LoadGeometry();

            base.OnLoad(e);
        }
Beispiel #4
0
        public override void Load()
        {
            // Engine components.
            RessourceManager ressourceManager = Engine.GetComponent <RessourceManager>();


            // Setup the scene
            Entities              = new List <Entity>();
            camera                = new OrbitalCamera(Engine.GraphicDevice.GetBufferSize().X / Engine.GraphicDevice.GetBufferSize().Y, 90);
            render                = new RenderBatch();
            testSun               = new Sun(new Point3D(-150f, 150f, -150f), new Color3(255, 255, 255));
            testScene             = new Scene(camera, testSun);
            testScene.Fog.Density = 0f;

            // Dragon
            Model    dragonModel    = ressourceManager.ImportRessource <Model>("model:dragon.obj");
            Material dragonMaterial = new Material(ressourceManager.ImportRessource <Texture2D>("texture2D:blue.png"));

            dragonMaterial.Reflectivity = 1f;
            dragonMaterial.ShineDamper  = 10f;
            ressourceManager.ImportRessource <ShaderProgram>("shader:material.json");
            Entities.Add(new Entity(new Transform(new Vector3(0, 0, 0), new Vector3(), 0.1f), dragonModel, dragonMaterial));

            // Terrain
            Material GrassMaterial = new Material(ressourceManager.ImportRessource <Texture2D>("texture2D:grass.png"))
            {
                Reflectivity = 0f,
                ShineDamper  = 10f
            };

            terrain = new Entity(new Transform(0, -10f, 0), ModelFactorie.GeneratePlane(640f, 256, 64, new PerlinHeightMap()), GrassMaterial);
            water   = new Entity(new Transform(0, 0, 0), ModelFactorie.GeneratePlane(640f, 16, 64, new FlatHeightMap()), dragonMaterial);


            // Show the inspector.
            new Inspector.InspectorUI(Engine, testScene).ShowInspector();
        }
Beispiel #5
0
        protected override void OnResize(EventArgs e)
        {
            float aspect   = (float)VirtualWidth / VirtualHeight;
            int   vpWidth  = Width;
            int   vpHeight = (int)(Width / aspect + 0.5f);

            if (vpHeight > Height)
            {
                vpHeight = Height;
                vpWidth  = (int)(Height * aspect + 0.5f);
            }

            int vpX = (Width / 2) - (vpWidth / 2);
            int vpY = (Height / 2) - (vpHeight / 2);

            GL.Viewport(vpX, vpY, vpWidth, vpHeight);
            GL.Scissor(vpX, vpY, vpWidth, vpHeight);

            Matrix4 projection = Matrix4.CreateOrthographicOffCenter(0f, VirtualWidth, VirtualHeight, 0f, 0f, 1f);

            RenderBatch.SetProjectionMatrix(projection);

            base.OnResize(e);
        }
Beispiel #6
0
        private void InsertElement(RenderBatch batch, ContainerNode parent, int childIndex, ArraySegment <RenderTreeFrame> frames, RenderTreeFrame frame, int frameIndex)
        {
            // Note: we don't handle SVG here
            var newElement = new ElementNode(frame.ElementName);

            parent.InsertLogicalChild(newElement, childIndex);

            // Apply attributes
            for (var i = frameIndex + 1; i < frameIndex + frame.ElementSubtreeLength; i++)
            {
                var descendantFrame = batch.ReferenceFrames.Array[i];
                if (descendantFrame.FrameType == RenderTreeFrameType.Attribute)
                {
                    ApplyAttribute(batch, newElement, descendantFrame);
                }
                else
                {
                    // As soon as we see a non-attribute child, all the subsequent child frames are
                    // not attributes, so bail out and insert the remnants recursively
                    InsertFrameRange(batch, newElement, 0, frames, i, frameIndex + frame.ElementSubtreeLength);
                    break;
                }
            }
        }
Beispiel #7
0
        private void UpdateShadowCaster()
        {
            if (lookTarget == null)
            {
                GameObject go = GameObject.Find("LookTarget");
                lookTarget = go != null ? go.transform : null;
            }
            if (lookTarget != null)
            {
                sceneData.currentEntityPos = lookTarget.position;
            }
            else
            {
                if (sceneData.CameraRef != null)
                {
                    sceneData.currentEntityPos = cameraForward * 10 + sceneData.cameraPos;
                }
            }
            shadowCasters.Clear();
            if (shadowCasterProxy == null)
            {
                shadowCasterProxy = GameObject.Find("ShadowCaster");
            }
            shadowRenderBatchs.Clear();
            bool   first       = true;
            Bounds shadowBound = new Bounds(Vector3.zero, Vector3.zero);

            if (shadowCasterProxy != null)
            {
                shadowCasterProxy.GetComponentsInChildren <Renderer>(false, shadowCasters);
                if (shadowCasters.Count > 0)
                {
                    for (int i = 0; i < shadowCasters.Count; ++i)
                    {
                        Renderer render = shadowCasters[i];
                        if (render != null &&
                            render.enabled &&
                            render.shadowCastingMode != ShadowCastingMode.Off &&
                            render.sharedMaterial != null)
                        {
                            RenderBatch rb = new RenderBatch();
                            rb.render = render;
                            rb.mat    = render.sharedMaterial;
                            rb.mpbRef = null;
                            rb.passID = 0;
                            shadowRenderBatchs.Add(rb);
                            if (first)
                            {
                                shadowBound = render.bounds;
                                first       = false;
                            }
                            else
                            {
                                shadowBound.Encapsulate(render.bounds);
                            }
                        }
                    }
                }
            }
            sceneData.shadowBound = shadowBound;
        }
 protected override void UpdateDisplay(RenderBatch renderBatch)
 => throw new NotImplementedException();
Beispiel #9
0
        BatchInfo GetCreateBatchInfo(ResourceHandle<Material> materialHandle)
        {
            if (!batches.ContainsKey(materialHandle.Id))
            {
                var batch = new RenderBatch
                {
                    GeometryBuffer = gb,
                    RenderLayer = RenderLayer.Overlays,
                    PrimitiveType = PrimitiveType.Quads,
                    Material = materialHandle
                };

                var batchInfo = new BatchInfo {Batch = batch, Ranges = new List<int>()};
                batches[materialHandle.Id] = batchInfo;
            }

            return batches[materialHandle.Id];
        }
        internal void ApplyEdits(int componentId, ArrayBuilderSegment <RenderTreeEdit> edits, ArrayRange <RenderTreeFrame> referenceFrames, RenderBatch batch)
        {
            Renderer.Dispatcher.AssertAccess();

            if (edits.Count == 0)
            {
                // TODO: Without this check there's a NullRef in ArrayBuilderSegment? Possibly a Blazor bug?
                return;
            }

            foreach (var edit in edits)
            {
                switch (edit.Type)
                {
                case RenderTreeEditType.PrependFrame:
                    ApplyPrependFrame(batch, componentId, edit.SiblingIndex, referenceFrames.Array, edit.ReferenceFrameIndex);
                    break;

                case RenderTreeEditType.RemoveFrame:
                    ApplyRemoveFrame(edit.SiblingIndex);
                    break;

                case RenderTreeEditType.SetAttribute:
                    ApplySetAttribute(ref referenceFrames.Array[edit.ReferenceFrameIndex]);
                    break;

                case RenderTreeEditType.RemoveAttribute:
                    // TODO: See whether siblingIndex is needed here
                    ApplyRemoveAttribute(edit.RemovedAttributeName);
                    break;

                case RenderTreeEditType.UpdateText:
                {
                    var frame = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
                    if (_targetElement is IHandleChildContentText handleChildContentText)
                    {
                        handleChildContentText.HandleText(edit.SiblingIndex, frame.TextContent);
                    }
                    else
                    {
                        throw new Exception("Cannot set text content on child that doesn't handle inner text content.");
                    }
                    break;
                }

                case RenderTreeEditType.StepIn:
                {
                    // TODO: Need to implement this. For now it seems safe to ignore.
                    break;
                }

                case RenderTreeEditType.StepOut:
                {
                    // TODO: Need to implement this. For now it seems safe to ignore.
                    break;
                }

                case RenderTreeEditType.UpdateMarkup:
                {
                    var frame = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
                    if (_targetElement is IHandleChildContentText handleChildContentText)
                    {
                        handleChildContentText.HandleText(edit.SiblingIndex, frame.MarkupContent);
                    }
                    else
                    {
                        throw new Exception("Cannot set markup content on child that doesn't handle inner text content.");
                    }
                    break;
                }

                case RenderTreeEditType.PermutationListEntry:
                    throw new NotImplementedException($"Not supported edit type: {edit.Type}");

                case RenderTreeEditType.PermutationListEnd:
                    throw new NotImplementedException($"Not supported edit type: {edit.Type}");

                default:
                    throw new NotImplementedException($"Invalid edit type: {edit.Type}");
                }
            }
        }
Beispiel #11
0
        private void LoadMap(string map, int centerx, int centery, int distance)
        {
            float TileSize = 1600.0f / 3.0f; //533.333
            float ChunkSize = TileSize / 16.0f; //33.333
            float UnitSize = ChunkSize / 8.0f; //4.166666 // ~~fun fact time with marlamin~~ this times 0.5 ends up being pixelspercoord on minimap
            float MapMidPoint = 32.0f / ChunkSize;

            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.NormalArray);

            List<Vertex> verticelist = new List<Vertex>();
            List<Int32> indicelist = new List<Int32>();

            GL.Enable(EnableCap.Texture2D);

            for (int x = centerx; x < centerx + distance; x++)
            {
                for (int y = centery; y < centery + distance; y++)
                {
                    string filename = "World/Maps/" + map + "/" + map + "_" + y + "_" + x + ".adt";

                    if (WoWFormatLib.Utils.CASC.FileExists(filename))
                    {
                        ADTReader reader = new ADTReader();
                        reader.LoadADT(filename);

                        Terrain adt = new Terrain();

                        adt.vertexBuffer = GL.GenBuffer();
                        adt.indiceBuffer = GL.GenBuffer();

                        GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);
                        GL.BindBuffer(BufferTarget.ElementArrayBuffer, adt.indiceBuffer);

                        List<Material> materials = new List<Material>();

                        //Check if textures are already loaded or not, multiple ADTs close together probably use the same ones mostly
                        for (int ti = 0; ti < reader.adtfile.textures.filenames.Count(); ti++)
                        {
                            Material material = new Material();
                            material.filename = reader.adtfile.textures.filenames[ti];

                            //if (!WoWFormatLib.Utils.CASC.FileExists(material.filename)) { continue; }

                            material.textureID = BLPLoader.LoadTexture(reader.adtfile.textures.filenames[ti], cache);

                            materials.Add(material);
                        }

                        var initialChunkY = reader.adtfile.chunks[0].header.position.Y;
                        var initialChunkX = reader.adtfile.chunks[0].header.position.X;

                        /*  if(firstLocation.X == 0)
                          {
                              firstLocation = new Vector3(initialChunkY, initialChunkX, 1.0f);
                              Console.WriteLine("Setting first location to " + firstLocation.ToString());
                          }
                          */
                        List<RenderBatch> renderBatches = new List<RenderBatch>();

                        for (uint c = 0; c < reader.adtfile.chunks.Count(); c++)
                        {
                            var chunk = reader.adtfile.chunks[c];

                            int off = verticelist.Count();

                            RenderBatch batch = new RenderBatch();

                            for (int i = 0, idx = 0; i < 17; i++)
                            {
                                for (int j = 0; j < (((i % 2) != 0) ? 8 : 9); j++)
                                {
                                    //var v = new Vector3(chunk.header.position.Y - (j * UnitSize), chunk.vertices.vertices[idx++] + chunk.header.position.Z, -(chunk.header.position.X - (i * UnitSize * 0.5f)));
                                    Vertex v = new Vertex();
                                    v.Normal = new Vector3(chunk.normals.normal_0[idx], chunk.normals.normal_1[idx], chunk.normals.normal_2[idx]);
                                    if (chunk.vertexShading.red != null && chunk.vertexShading.red[idx] != 127)
                                    {
                                        v.Color = new Vector3(chunk.vertexShading.blue[idx] / 255.0f, chunk.vertexShading.green[idx] / 255.0f, chunk.vertexShading.red[idx] / 255.0f);
                                        //v.Color = new Vector3(1.0f, 1.0f, 1.0f);
                                    }
                                    else
                                    {
                                        v.Color = new Vector3(1.0f, 1.0f, 1.0f);
                                    }

                                    v.TexCoord = new Vector2(((float)j + (((i % 2) != 0) ? 0.5f : 0f)) / 8f, ((float)i * 0.5f) / 8f);

                                    v.Position = new Vector3(chunk.header.position.Y - (j * UnitSize), chunk.vertices.vertices[idx++] + chunk.header.position.Z, chunk.header.position.X - (i * UnitSize * 0.5f));

                                    if ((i % 2) != 0) v.Position.X -= 0.5f * UnitSize;
                                    verticelist.Add(v);
                                }
                            }

                            batch.firstFace = (uint)indicelist.Count();
                            for (int j = 9; j < 145; j++)
                            {
                                indicelist.AddRange(new Int32[] { off + j + 8, off + j - 9, off + j });
                                indicelist.AddRange(new Int32[] { off + j - 9, off + j - 8, off + j });
                                indicelist.AddRange(new Int32[] { off + j - 8, off + j + 9, off + j });
                                indicelist.AddRange(new Int32[] { off + j + 9, off + j + 8, off + j });
                                if ((j + 1) % (9 + 8) == 0) j += 9;
                            }
                            batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace;

                            if (!cache.materials.ContainsKey(reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[0].textureId].ToLower()))
                            {
                                throw new Exception("MaterialCache does not have texture " + reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[0].textureId].ToLower());
                            }

                            var layermats = new List<uint>();
                            var alphalayermats = new List<int>();

                            for (int li = 0; li < reader.adtfile.texChunks[c].layers.Count(); li++)
                            {
                                if(reader.adtfile.texChunks[c].alphaLayer != null){
                                    alphalayermats.Add(BLPLoader.GenerateAlphaTexture(reader.adtfile.texChunks[c].alphaLayer[li].layer));

                                }
                                layermats.Add((uint)cache.materials[reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[li].textureId].ToLower()]);
                            }

                            batch.materialID = layermats.ToArray();
                            batch.alphaMaterialID = alphalayermats.ToArray();
                            renderBatches.Add(batch);
                        }

                        List<Doodad> doodads = new List<Doodad>();

                        for (int mi = 0; mi < reader.adtfile.objects.models.entries.Count(); mi++)
                        {
                            Console.WriteLine("Loading model #" + mi);

                            var modelentry = reader.adtfile.objects.models.entries[mi];
                            var mmid = reader.adtfile.objects.m2NameOffsets.offsets[modelentry.mmidEntry];

                            var modelfilename = "";
                            for (int mmi = 0; mmi < reader.adtfile.objects.m2Names.offsets.Count(); mmi++)
                            {
                                if (reader.adtfile.objects.m2Names.offsets[mmi] == mmid)
                                {
                                    modelfilename = reader.adtfile.objects.m2Names.filenames[mmi].ToLower();
                                }
                            }

                            var doodad = new Doodad();
                            doodad.filename = modelfilename;
                            doodad.position = new Vector3(-(modelentry.position.X - 17066), modelentry.position.Y, -(modelentry.position.Z - 17066));
                            doodad.rotation = new Vector3(modelentry.rotation.X, modelentry.rotation.Y, modelentry.rotation.Z);
                            doodad.scale = modelentry.scale;
                            doodads.Add(doodad);

                            if (cache.doodadBatches.ContainsKey(modelfilename))
                            {
                                continue;
                            }

                            M2Loader.LoadM2(modelfilename, cache);
                        }

                        List<WorldModelBatch> worldModelBatches = new List<WorldModelBatch>();

                        // WMO loading goes here
                        for (int wmi = 0; wmi < reader.adtfile.objects.worldModels.entries.Count(); wmi++)
                        {
                            Console.WriteLine("Loading WMO #" + wmi);
                            string wmofilename = "";

                            var wmodelentry = reader.adtfile.objects.worldModels.entries[wmi];
                            var mwid = reader.adtfile.objects.wmoNameOffsets.offsets[wmodelentry.mwidEntry];

                            for (int wmfi = 0; wmfi < reader.adtfile.objects.wmoNames.offsets.Count(); wmfi++)
                            {
                                if (reader.adtfile.objects.wmoNames.offsets[wmfi] == mwid)
                                {
                                    wmofilename = reader.adtfile.objects.wmoNames.filenames[wmfi].ToLower();
                                }

                            }

                            if (wmofilename.Length == 0)
                            {
                                throw new Exception("Unable to find filename for WMO!");
                            }

                            WorldModelBatch wmobatch = new WorldModelBatch();
                            wmobatch.position = new Vector3(-(wmodelentry.position.X - 17066), wmodelentry.position.Y, -(wmodelentry.position.Z - 17066));
                            wmobatch.rotation = new Vector3(wmodelentry.rotation.X, wmodelentry.rotation.Y, wmodelentry.rotation.Z);
                            wmobatch.worldModel = WMOLoader.LoadWMO(wmofilename, cache);
                            worldModelBatches.Add(wmobatch);
                        }

                        adt.renderBatches = renderBatches.ToArray();
                        adt.doodads = doodads.ToArray();
                        adt.worldModelBatches = worldModelBatches.ToArray();

                        int[] indices = indicelist.ToArray();
                        Vertex[] vertices = verticelist.ToArray();

                        Console.WriteLine("Vertices in array: " + vertices.Count()); //37120, correct

                        //indices = indicelist.ToArray();
                        Console.WriteLine("Indices in array: " + indices.Count()); //196608, should be 65.5k which is 196608 / 3. in triangles so its correct?

                        GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);
                        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Count() * 11 * sizeof(float)), vertices, BufferUsageHint.StaticDraw);

                        GL.BindBuffer(BufferTarget.ElementArrayBuffer, adt.indiceBuffer);
                        GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(int)), indices, BufferUsageHint.StaticDraw);

                        int verticeBufferSize = 0;
                        int indiceBufferSize = 0;

                        GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);
                        GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out verticeBufferSize);

                        GL.BindBuffer(BufferTarget.ArrayBuffer, adt.indiceBuffer);
                        GL.GetBufferParameter(BufferTarget.ElementArrayBuffer, BufferParameterName.BufferSize, out indiceBufferSize);

                        Console.WriteLine("Vertices in buffer: " + verticeBufferSize / 11 / sizeof(float));
                        Console.WriteLine("Indices in buffer: " + indiceBufferSize / sizeof(int));

                        adts.Add(adt);
                    }
                }
            }
        }
Beispiel #12
0
        private List<J3DRenderer.VertexFormatLayout> BuildVertexArraysFromFile()
        {
            List<J3DRenderer.VertexFormatLayout> finalData = new List<J3DRenderer.VertexFormatLayout>();


            //Now, let's try to get our data.
            for (uint i = 0; i < _file.Shapes.GetBatchCount(); i++)
            {
                J3DFormat.Batch batch = _file.Shapes.GetBatch(i);

                RenderBatch renderBatch = new RenderBatch();
                _renderList.Add(renderBatch);

                //Console.WriteLine("[{0}] Unk0: {5}, Attb: {6} Mtx Type: {1} #Packets {2}[{3}] Matrix Index: {4}", i, batch.MatrixType, batch.PacketCount, batch.PacketIndex, batch.FirstMatrixIndex, batch.Unknown0, batch.AttribOffset);

                uint attributeCount = 0;
                for (uint attribIndex = 0; attribIndex < 13; attribIndex++)
                {
                    J3DFormat.BatchAttribute attrib = _file.Shapes.GetAttribute(attribIndex, batch.AttribOffset);
                    if (attrib.AttribType == J3DFormat.ArrayTypes.NullAttr)
                        break;

                    attributeCount++;
                }

                for (ushort p = 0; p < batch.PacketCount; p++)
                {
                    RenderPacket renderPacket = new RenderPacket();
                    renderBatch.Packets.Add(renderPacket);

                    //Matrix Data
                    J3DFormat.PacketMatrixData pmd = _file.Shapes.GetPacketMatrixData((ushort)(batch.FirstMatrixIndex + p));
                    renderPacket.DrawIndexes = new ushort[pmd.Count];
                    for (ushort mtx = 0; mtx < pmd.Count; mtx++)
                    {
                        //Console.WriteLine("{4} {0} Packet: {1} Index: {2} PMD Unknown: {3}", i, p, _file.Shapes.GetMatrixTableIndex((ushort) (pmd.FirstIndex + mtx)), pmd.Unknown, mtx);
                        renderPacket.DrawIndexes[mtx] = _file.Shapes.GetMatrixTableIndex((ushort)(pmd.FirstIndex + mtx));
                    }

                    J3DFormat.BatchPacketLocation packetLoc = _file.Shapes.GetBatchPacketLocation((ushort)(batch.PacketIndex + p));
                    uint numPrimitiveBytesRead = packetLoc.Offset;
                    while (numPrimitiveBytesRead < packetLoc.Offset + packetLoc.PacketSize)
                    {
                        J3DFormat.BatchPrimitive primitive = _file.Shapes.GetPrimitive(numPrimitiveBytesRead);
                        numPrimitiveBytesRead += J3DFormat.BatchPrimitive.Size;

                        //Game pads the chunks out with zeros, so this is signal for early break.
                        if (primitive.Type == 0)
                        {
                            break;
                        }

                        var primList = new PrimitiveList();
                        primList.VertexCount = primitive.VertexCount;
                        primList.VertexStart = finalData.Count;
                        primList.DrawType = primitive.Type == J3DFormat.PrimitiveTypes.TriangleStrip ? PrimitiveType.TriangleStrip : PrimitiveType.TriangleFan; //Todo: More support
                        renderPacket.PrimList.Add(primList);

                        for (int vert = 0; vert < primitive.VertexCount; vert++)
                        {
                            J3DRenderer.VertexFormatLayout newVertex = new J3DRenderer.VertexFormatLayout();
                            for (uint vertIndex = 0; vertIndex < attributeCount; vertIndex++)
                            {
                                var batchAttrib = _file.Shapes.GetAttribute(vertIndex, batch.AttribOffset);
                                ushort curIndex = _file.Shapes.GetPrimitiveIndex(numPrimitiveBytesRead, batchAttrib);

                                switch (batchAttrib.AttribType)
                                {
                                    case J3DFormat.ArrayTypes.Position:
                                        newVertex.Position = _file.Vertexes.GetPosition(curIndex);
                                        break;
                                    case J3DFormat.ArrayTypes.Normal:
                                        newVertex.Color = new Vector4(_file.Vertexes.GetNormal(curIndex, 14), 1); //temp
                                        break;
                                    case J3DFormat.ArrayTypes.Color0:
                                        newVertex.Color = _file.Vertexes.GetColor0(curIndex);
                                        break;
                                    case J3DFormat.ArrayTypes.Tex0:
                                        newVertex.TexCoord = _file.Vertexes.GetTex0(curIndex, 8);
                                        break;

                                    case J3DFormat.ArrayTypes.PositionMatrixIndex:
                                        //Console.WriteLine("B: {0} P: {1} Prim: {2} Vert{3} Index: {4}", i, p, renderPacket.PrimList.Count, vert, curIndex);
                                        primList.PosMatrixIndex.Add(curIndex);
                                        break;
                                    default:
                                        Console.WriteLine("Unknown AttribType {0}, Index: {1}", batchAttrib.AttribType, curIndex);
                                        break;
                                }

                                numPrimitiveBytesRead += GetAttribElementSize(batchAttrib.DataType);
                            }

                            //Add our vertex to our list of Vertexes
                            finalData.Add(newVertex);
                        }

                        //Console.WriteLine("Batch {0} Prim {1} #Vertices with PosMtxIndex: {2}", i, p, primList.PosMatrixIndex.Count);
                    }
                }

                //Console.WriteLine("Finished batch {0}, triangleStrip count: {1}", i, _renderList.Count);
            }

            return finalData;
        }
Beispiel #13
0
        private void LoadMap(string map, int centerx, int centery, int distance)
        {
            float TileSize    = 1600.0f / 3.0f;   //533.333
            float ChunkSize   = TileSize / 16.0f; //33.333
            float UnitSize    = ChunkSize / 8.0f; //4.166666 // ~~fun fact time with marlamin~~ this times 0.5 ends up being pixelspercoord on minimap
            float MapMidPoint = 32.0f / ChunkSize;

            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.NormalArray);

            List <Vertex> verticelist = new List <Vertex>();
            List <Int32>  indicelist  = new List <Int32>();

            GL.Enable(EnableCap.Texture2D);

            worker.ReportProgress(0, "Loading ADT..");
            for (int x = centerx; x < centerx + distance; x++)
            {
                for (int y = centery; y < centery + distance; y++)
                {
                    string filename = "world\\maps\\" + map + "\\" + map + "_" + y + "_" + x + ".adt";

                    if (WoWFormatLib.Utils.CASC.FileExists(filename))
                    {
                        ADTReader reader = new ADTReader();
                        reader.LoadADT(filename);

                        Terrain adt = new Terrain();

                        adt.vertexBuffer = GL.GenBuffer();
                        adt.indiceBuffer = GL.GenBuffer();

                        GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);
                        GL.BindBuffer(BufferTarget.ElementArrayBuffer, adt.indiceBuffer);

                        List <Material> materials = new List <Material>();

                        //Check if textures are already loaded or not, multiple ADTs close together probably use the same ones mostly
                        //for (int ti = 0; ti < reader.adtfile.textures.filenames.Count(); ti++)
                        //{

                        /*
                         * Material material = new Material();
                         * material.filename = reader.adtfile.textures.filenames[ti];
                         * material.textureID = BLPLoader.LoadTexture(reader.adtfile.textures.filenames[ti], cache);*/

                        /* MAPTEXTURE TEXTURE HACKFIX STUFF STARTS HERE */
                        Material material = new Material();
                        material.filename  = filename.Replace("maps", "maptextures").Replace(".adt", ".blp");
                        material.textureID = BLPLoader.LoadTexture(filename.Replace("maps", "maptextures").Replace(".adt", ".blp"), cache);
                        /* MAPTEXTURE TEXTURE HACKFIX STUFF STOPS HERE */

                        materials.Add(material);
                        //}


                        var initialChunkY = reader.adtfile.chunks[0].header.position.Y;
                        var initialChunkX = reader.adtfile.chunks[0].header.position.X;

                        List <RenderBatch> renderBatches = new List <RenderBatch>();

                        for (uint c = 0; c < reader.adtfile.chunks.Count(); c++)
                        {
                            var chunk = reader.adtfile.chunks[c];

                            int off = verticelist.Count();

                            RenderBatch batch = new RenderBatch();

                            for (int i = 0, idx = 0; i < 17; i++)
                            {
                                for (int j = 0; j < (((i % 2) != 0) ? 8 : 9); j++)
                                {
                                    //var v = new Vector3(chunk.header.position.Y - (j * UnitSize), chunk.vertices.vertices[idx++] + chunk.header.position.Z, -(chunk.header.position.X - (i * UnitSize * 0.5f)));
                                    Vertex v = new Vertex();
                                    v.Normal = new Vector3(chunk.normals.normal_0[idx], chunk.normals.normal_1[idx], chunk.normals.normal_2[idx]);
                                    if (chunk.vertexShading.red != null && chunk.vertexShading.red[idx] != 127)
                                    {
                                        v.Color = new Vector3(chunk.vertexShading.blue[idx] / 255.0f, chunk.vertexShading.green[idx] / 255.0f, chunk.vertexShading.red[idx] / 255.0f);
                                        //v.Color = new Vector3(1.0f, 1.0f, 1.0f);
                                    }
                                    else
                                    {
                                        v.Color = new Vector3(1.0f, 1.0f, 1.0f);
                                    }

                                    // Commented out for maptexture hack
                                    //v.TexCoord = new Vector2(((float)j + (((i % 2) != 0) ? 0.5f : 0f)) / 8f, ((float)i * 0.5f) / 8f);

                                    v.Position = new Vector3(chunk.header.position.X - (i * UnitSize * 0.5f), chunk.header.position.Y - (j * UnitSize), chunk.vertices.vertices[idx++] + chunk.header.position.Z);

                                    if ((i % 2) != 0)
                                    {
                                        v.Position.Y -= 0.5f * UnitSize;
                                    }

                                    //Maptexture hackfix
                                    v.TexCoord = new Vector2(-(v.Position.Y - initialChunkX) / TileSize, -(v.Position.X - initialChunkY) / TileSize);

                                    verticelist.Add(v);
                                }
                            }

                            batch.firstFace = (uint)indicelist.Count();
                            for (int j = 9; j < 145; j++)
                            {
                                indicelist.AddRange(new Int32[] { off + j + 8, off + j - 9, off + j });
                                indicelist.AddRange(new Int32[] { off + j - 9, off + j - 8, off + j });
                                indicelist.AddRange(new Int32[] { off + j - 8, off + j + 9, off + j });
                                indicelist.AddRange(new Int32[] { off + j + 9, off + j + 8, off + j });
                                if ((j + 1) % (9 + 8) == 0)
                                {
                                    j += 9;
                                }
                            }
                            batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace;

                            //if (!cache.materials.ContainsKey(reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[0].textureId].ToLower()))
                            //{
                            //    throw new Exception("MaterialCache does not have texture " + reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[0].textureId].ToLower());
                            //}

                            //Commented out for maptexture hackfix

                            /*
                             * var layermats = new List<uint>();
                             * var alphalayermats = new List<int>();
                             *
                             * for (int li = 0; li < reader.adtfile.texChunks[c].layers.Count(); li++)
                             * {
                             *  if(reader.adtfile.texChunks[c].alphaLayer != null){
                             *      alphalayermats.Add(BLPLoader.GenerateAlphaTexture(reader.adtfile.texChunks[c].alphaLayer[li].layer));
                             *  }
                             *  layermats.Add((uint)cache.materials[reader.adtfile.textures.filenames[reader.adtfile.texChunks[c].layers[li].textureId].ToLower()]);
                             * }
                             *
                             * batch.materialID = layermats.ToArray();
                             * batch.alphaMaterialID = alphalayermats.ToArray();
                             *
                             */
                            var layermats = new List <uint>();
                            layermats.Add((uint)material.textureID);
                            batch.materialID = layermats.ToArray();
                            renderBatches.Add(batch);
                        }

                        List <Doodad> doodads = new List <Doodad>();

                        for (int mi = 0; mi < reader.adtfile.objects.models.entries.Count(); mi++)
                        {
                            Console.WriteLine("Loading model #" + mi);

                            var modelentry = reader.adtfile.objects.models.entries[mi];
                            var mmid       = reader.adtfile.objects.m2NameOffsets.offsets[modelentry.mmidEntry];

                            var modelfilename = "";
                            for (int mmi = 0; mmi < reader.adtfile.objects.m2Names.offsets.Count(); mmi++)
                            {
                                if (reader.adtfile.objects.m2Names.offsets[mmi] == mmid)
                                {
                                    modelfilename = reader.adtfile.objects.m2Names.filenames[mmi].ToLower();
                                }
                            }

                            var doodad = new Doodad();
                            doodad.filename = modelfilename;
                            doodad.position = new Vector3(-(modelentry.position.X - 17066), modelentry.position.Y, -(modelentry.position.Z - 17066));
                            doodad.rotation = new Vector3(modelentry.rotation.X, modelentry.rotation.Y, modelentry.rotation.Z);
                            doodad.scale    = modelentry.scale;
                            doodads.Add(doodad);

                            if (cache.doodadBatches.ContainsKey(modelfilename))
                            {
                                continue;
                            }

                            M2Loader.LoadM2(modelfilename, cache);
                        }

                        List <WorldModelBatch> worldModelBatches = new List <WorldModelBatch>();

                        // WMO loading goes here
                        for (int wmi = 0; wmi < reader.adtfile.objects.worldModels.entries.Count(); wmi++)
                        {
                            Console.WriteLine("Loading WMO #" + wmi);
                            string wmofilename = "";

                            var wmodelentry = reader.adtfile.objects.worldModels.entries[wmi];
                            var mwid        = reader.adtfile.objects.wmoNameOffsets.offsets[wmodelentry.mwidEntry];

                            for (int wmfi = 0; wmfi < reader.adtfile.objects.wmoNames.offsets.Count(); wmfi++)
                            {
                                if (reader.adtfile.objects.wmoNames.offsets[wmfi] == mwid)
                                {
                                    wmofilename = reader.adtfile.objects.wmoNames.filenames[wmfi].ToLower();
                                }
                            }

                            if (wmofilename.Length == 0)
                            {
                                throw new Exception("Unable to find filename for WMO!");
                            }

                            WorldModelBatch wmobatch = new WorldModelBatch();
                            wmobatch.position   = new Vector3(-(wmodelentry.position.X - 17066.666f), wmodelentry.position.Y, -(wmodelentry.position.Z - 17066.666f));
                            wmobatch.rotation   = new Vector3(wmodelentry.rotation.X, wmodelentry.rotation.Y, wmodelentry.rotation.Z);
                            wmobatch.worldModel = WMOLoader.LoadWMO(wmofilename, cache);
                            worldModelBatches.Add(wmobatch);
                        }

                        adt.renderBatches     = renderBatches.ToArray();
                        adt.doodads           = doodads.ToArray();
                        adt.worldModelBatches = worldModelBatches.ToArray();

                        int[]    indices  = indicelist.ToArray();
                        Vertex[] vertices = verticelist.ToArray();

                        Console.WriteLine("Vertices in array: " + vertices.Count()); //37120, correct

                        //indices = indicelist.ToArray();
                        Console.WriteLine("Indices in array: " + indices.Count()); //196608, should be 65.5k which is 196608 / 3. in triangles so its correct?

                        GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);
                        GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Count() * 11 * sizeof(float)), vertices, BufferUsageHint.StaticDraw);

                        GL.BindBuffer(BufferTarget.ElementArrayBuffer, adt.indiceBuffer);
                        GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(int)), indices, BufferUsageHint.StaticDraw);

                        int verticeBufferSize = 0;
                        int indiceBufferSize  = 0;

                        GL.BindBuffer(BufferTarget.ArrayBuffer, adt.vertexBuffer);
                        GL.GetBufferParameter(BufferTarget.ArrayBuffer, BufferParameterName.BufferSize, out verticeBufferSize);

                        GL.BindBuffer(BufferTarget.ArrayBuffer, adt.indiceBuffer);
                        GL.GetBufferParameter(BufferTarget.ElementArrayBuffer, BufferParameterName.BufferSize, out indiceBufferSize);

                        Console.WriteLine("Vertices in buffer: " + verticeBufferSize / 11 / sizeof(float));
                        Console.WriteLine("Indices in buffer: " + indiceBufferSize / sizeof(int));

                        adts.Add(adt);
                    }
                }
            }
        }
        public static Terrain LoadADT(string filename, CacheStorage cache, int shaderProgram, bool loadModels = false)
        {
            var adt = new WoWFormatLib.Structs.ADT.ADT();

            var result = new Terrain();

            //Load ADT from file
            if (WoWFormatLib.Utils.CASC.FileExists(filename))
            {
                var adtreader = new ADTReader();
                adtreader.LoadADT(filename);
                adt = adtreader.adtfile;
            }
            else
            {
                throw new Exception("ADT " + filename + " does not exist!");
            }

            var TileSize    = 1600.0f / 3.0f;   //533.333
            var ChunkSize   = TileSize / 16.0f; //33.333
            var UnitSize    = ChunkSize / 8.0f; //4.166666
            var MapMidPoint = 32.0f / ChunkSize;

            var verticelist = new List <Vertex>();
            var indicelist  = new List <int>();

            result.vao = GL.GenVertexArray();
            GL.BindVertexArray(result.vao);

            result.vertexBuffer = GL.GenBuffer();
            result.indiceBuffer = GL.GenBuffer();

            var materials = new List <Material>();

            if (adt.textures.filenames == null)
            {
                for (var ti = 0; ti < adt.diffuseTextureFileDataIDs.Count(); ti++)
                {
                    var material = new Material();
                    material.filename  = adt.diffuseTextureFileDataIDs[ti].ToString();
                    material.textureID = BLPLoader.LoadTexture(adt.diffuseTextureFileDataIDs[ti], cache);

                    if (adt.texParams != null && adt.texParams.Count() >= ti)
                    {
                        material.scale = (float)Math.Pow(2, (adt.texParams[ti].flags & 0xF0) >> 4);
                        if (adt.texParams[ti].height != 0.0 || adt.texParams[ti].offset != 1.0)
                        {
                            material.heightScale  = adt.texParams[ti].height;
                            material.heightOffset = adt.texParams[ti].offset;

                            if (!WoWFormatLib.Utils.CASC.FileExists(adt.heightTextureFileDataIDs[ti]))
                            {
                                Console.WriteLine("Height texture: " + adt.heightTextureFileDataIDs[ti] + " does not exist! Falling back to original texture (hack)..");
                                material.heightTexture = BLPLoader.LoadTexture(adt.diffuseTextureFileDataIDs[ti], cache);
                            }
                            else
                            {
                                material.heightTexture = BLPLoader.LoadTexture(adt.heightTextureFileDataIDs[ti], cache);
                            }
                        }
                        else
                        {
                            material.heightScale  = 0.0f;
                            material.heightOffset = 1.0f;
                        }
                    }
                    else
                    {
                        material.heightScale  = 0.0f;
                        material.heightOffset = 1.0f;
                        material.scale        = 1.0f;
                    }
                    materials.Add(material);
                }
            }
            else
            {
                for (var ti = 0; ti < adt.textures.filenames.Count(); ti++)
                {
                    var material = new Material();
                    material.filename  = adt.textures.filenames[ti];
                    material.textureID = BLPLoader.LoadTexture(adt.textures.filenames[ti], cache);

                    if (adt.texParams != null && adt.texParams.Count() >= ti)
                    {
                        material.scale = (float)Math.Pow(2, (adt.texParams[ti].flags & 0xF0) >> 4);
                        if (adt.texParams[ti].height != 0.0 || adt.texParams[ti].offset != 1.0)
                        {
                            material.heightScale  = adt.texParams[ti].height;
                            material.heightOffset = adt.texParams[ti].offset;

                            var heightName = adt.textures.filenames[ti].Replace(".blp", "_h.blp");
                            if (!WoWFormatLib.Utils.CASC.FileExists(heightName))
                            {
                                Console.WriteLine("Height texture: " + heightName + " does not exist! Falling back to original texture (hack)..");
                                material.heightTexture = BLPLoader.LoadTexture(adt.textures.filenames[ti], cache);
                            }
                            else
                            {
                                material.heightTexture = BLPLoader.LoadTexture(heightName, cache);
                            }
                        }
                        else
                        {
                            material.heightScale  = 0.0f;
                            material.heightOffset = 1.0f;
                        }
                    }
                    else
                    {
                        material.heightScale  = 0.0f;
                        material.heightOffset = 1.0f;
                        material.scale        = 1.0f;
                    }
                    materials.Add(material);
                }
            }


            var initialChunkY = adt.chunks[0].header.position.Y;
            var initialChunkX = adt.chunks[0].header.position.X;

            var renderBatches = new List <RenderBatch>();

            for (uint c = 0; c < adt.chunks.Count(); c++)
            {
                var chunk = adt.chunks[c];

                var off = verticelist.Count();

                var batch = new RenderBatch();

                batch.groupID = c;

                for (int i = 0, idx = 0; i < 17; i++)
                {
                    for (var j = 0; j < (((i % 2) != 0) ? 8 : 9); j++)
                    {
                        var v = new Vertex();
                        v.Normal = new Vector3(chunk.normals.normal_0[idx], chunk.normals.normal_1[idx], chunk.normals.normal_2[idx]);
                        if (chunk.vertexShading.red != null)
                        {
                            v.Color = new Vector4(chunk.vertexShading.blue[idx] / 255.0f, chunk.vertexShading.green[idx] / 255.0f, chunk.vertexShading.red[idx] / 255.0f, chunk.vertexShading.alpha[idx] / 255.0f);
                        }
                        else
                        {
                            v.Color = new Vector4(0.5f, 0.5f, 0.5f, 1.0f);
                        }

                        v.TexCoord = new Vector2((j + (((i % 2) != 0) ? 0.5f : 0f)) / 8f, (i * 0.5f) / 8f);

                        v.Position = new Vector3(chunk.header.position.X - (i * UnitSize * 0.5f), chunk.header.position.Y - (j * UnitSize), chunk.vertices.vertices[idx++] + chunk.header.position.Z);

                        if ((i % 2) != 0)
                        {
                            v.Position.Y -= 0.5f * UnitSize;
                        }

                        verticelist.Add(v);
                    }
                }

                result.startPos = verticelist[0];

                batch.firstFace = (uint)indicelist.Count();
                for (var j = 9; j < 145; j++)
                {
                    indicelist.AddRange(new int[] { off + j + 8, off + j - 9, off + j });
                    indicelist.AddRange(new int[] { off + j - 9, off + j - 8, off + j });
                    indicelist.AddRange(new int[] { off + j - 8, off + j + 9, off + j });
                    indicelist.AddRange(new int[] { off + j + 9, off + j + 8, off + j });
                    if ((j + 1) % (9 + 8) == 0)
                    {
                        j += 9;
                    }
                }
                batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace;

                var layermats      = new List <uint>();
                var alphalayermats = new List <int>();
                var layerscales    = new List <float>();
                var layerheights   = new List <int>();

                batch.heightScales  = new Vector4();
                batch.heightOffsets = new Vector4();

                for (var li = 0; li < adt.texChunks[c].layers.Count(); li++)
                {
                    if (adt.texChunks[c].alphaLayer != null)
                    {
                        alphalayermats.Add(BLPLoader.GenerateAlphaTexture(adt.texChunks[c].alphaLayer[li].layer));
                    }

                    layermats.Add((uint)cache.materials[adt.diffuseTextureFileDataIDs[adt.texChunks[c].layers[li].textureId]]);

                    var curMat = materials.Where(material => material.filename == adt.diffuseTextureFileDataIDs[adt.texChunks[c].layers[li].textureId].ToString()).Single();

                    layerscales.Add(curMat.scale);
                    layerheights.Add(curMat.heightTexture);

                    batch.heightScales[li]  = curMat.heightScale;
                    batch.heightOffsets[li] = curMat.heightOffset;
                }

                batch.materialID        = layermats.ToArray();
                batch.alphaMaterialID   = alphalayermats.ToArray();
                batch.scales            = layerscales.ToArray();
                batch.heightMaterialIDs = layerheights.ToArray();

                var indices  = indicelist.ToArray();
                var vertices = verticelist.ToArray();

                GL.BindBuffer(BufferTarget.ArrayBuffer, result.vertexBuffer);
                GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Count() * 12 * sizeof(float)), vertices, BufferUsageHint.StaticDraw);

                //var normalAttrib = GL.GetAttribLocation(shaderProgram, "normal");
                //GL.EnableVertexAttribArray(normalAttrib);
                //GL.VertexAttribPointer(normalAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 11, sizeof(float) * 0);

                var colorAttrib = GL.GetAttribLocation(shaderProgram, "color");
                GL.EnableVertexAttribArray(colorAttrib);
                GL.VertexAttribPointer(colorAttrib, 4, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 3);

                var texCoordAttrib = GL.GetAttribLocation(shaderProgram, "texCoord");
                GL.EnableVertexAttribArray(texCoordAttrib);
                GL.VertexAttribPointer(texCoordAttrib, 2, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 7);

                var posAttrib = GL.GetAttribLocation(shaderProgram, "position");
                GL.EnableVertexAttribArray(posAttrib);
                GL.VertexAttribPointer(posAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 9);

                GL.BindBuffer(BufferTarget.ElementArrayBuffer, result.indiceBuffer);
                GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(int)), indices, BufferUsageHint.StaticDraw);

                renderBatches.Add(batch);
            }

            var doodads           = new List <Doodad>();
            var worldModelBatches = new List <WorldModelBatch>();

            if (loadModels)
            {
                for (var mi = 0; mi < adt.objects.models.entries.Count(); mi++)
                {
                    Console.WriteLine("Loading model #" + mi);

                    var modelentry = adt.objects.models.entries[mi];
                    var mmid       = adt.objects.m2NameOffsets.offsets[modelentry.mmidEntry];

                    var modelfilename = "";
                    for (var mmi = 0; mmi < adt.objects.m2Names.offsets.Count(); mmi++)
                    {
                        if (adt.objects.m2Names.offsets[mmi] == mmid)
                        {
                            modelfilename = adt.objects.m2Names.filenames[mmi].ToLower();
                            break;
                        }
                    }

                    doodads.Add(new Doodad
                    {
                        filename = modelfilename,
                        position = new Vector3(-(modelentry.position.X - 17066), modelentry.position.Y, -(modelentry.position.Z - 17066)),
                        rotation = new Vector3(modelentry.rotation.X, modelentry.rotation.Y, modelentry.rotation.Z),
                        scale    = modelentry.scale
                    });

                    if (!cache.doodadBatches.ContainsKey(modelfilename))
                    {
                        M2Loader.LoadM2(modelfilename, cache, shaderProgram);
                    }
                }

                for (var wmi = 0; wmi < adt.objects.worldModels.entries.Count(); wmi++)
                {
                    var wmofilename = "";

                    var wmodelentry = adt.objects.worldModels.entries[wmi];
                    var mwid        = adt.objects.wmoNameOffsets.offsets[wmodelentry.mwidEntry];

                    for (var wmfi = 0; wmfi < adt.objects.wmoNames.offsets.Count(); wmfi++)
                    {
                        if (adt.objects.wmoNames.offsets[wmfi] == mwid)
                        {
                            wmofilename = adt.objects.wmoNames.filenames[wmfi].ToLower();
                            break;
                        }
                    }

                    if (wmofilename.Length == 0)
                    {
                        throw new Exception("Unable to find filename for WMO!");
                    }

                    if (!cache.worldModelBatches.ContainsKey(wmofilename))
                    {
                        WMOLoader.LoadWMO(wmofilename, cache, shaderProgram);
                    }

                    worldModelBatches.Add(new WorldModelBatch
                    {
                        position   = new Vector3(-(wmodelentry.position.X - 17066.666f), wmodelentry.position.Y, -(wmodelentry.position.Z - 17066.666f)),
                        rotation   = new Vector3(wmodelentry.rotation.X, wmodelentry.rotation.Y, wmodelentry.rotation.Z),
                        worldModel = cache.worldModelBatches[wmofilename]
                    });
                }
            }

            result.renderBatches     = renderBatches.ToArray();
            result.doodads           = doodads.ToArray();
            result.worldModelBatches = worldModelBatches.ToArray();

            cache.terrain.Add(filename, result);
            return(result);
        }
Beispiel #15
0
        private List <J3DRenderer.VertexFormatLayout> BuildVertexArraysFromFile()
        {
            List <J3DRenderer.VertexFormatLayout> finalData = new List <J3DRenderer.VertexFormatLayout>();


            //Now, let's try to get our data.
            for (uint i = 0; i < _file.Shapes.GetBatchCount(); i++)
            {
                J3DFormat.Batch batch = _file.Shapes.GetBatch(i);

                RenderBatch renderBatch = new RenderBatch();
                _renderList.Add(renderBatch);

                //Console.WriteLine("[{0}] Unk0: {5}, Attb: {6} Mtx Type: {1} #Packets {2}[{3}] Matrix Index: {4}", i, batch.MatrixType, batch.PacketCount, batch.PacketIndex, batch.FirstMatrixIndex, batch.Unknown0, batch.AttribOffset);

                uint attributeCount = 0;
                for (uint attribIndex = 0; attribIndex < 13; attribIndex++)
                {
                    J3DFormat.BatchAttribute attrib = _file.Shapes.GetAttribute(attribIndex, batch.AttribOffset);
                    if (attrib.AttribType == J3DFormat.ArrayTypes.NullAttr)
                    {
                        break;
                    }

                    attributeCount++;
                }

                for (ushort p = 0; p < batch.PacketCount; p++)
                {
                    RenderPacket renderPacket = new RenderPacket();
                    renderBatch.Packets.Add(renderPacket);

                    //Matrix Data
                    J3DFormat.PacketMatrixData pmd = _file.Shapes.GetPacketMatrixData((ushort)(batch.FirstMatrixIndex + p));
                    renderPacket.DrawIndexes = new ushort[pmd.Count];
                    for (ushort mtx = 0; mtx < pmd.Count; mtx++)
                    {
                        //Console.WriteLine("{4} {0} Packet: {1} Index: {2} PMD Unknown: {3}", i, p, _file.Shapes.GetMatrixTableIndex((ushort) (pmd.FirstIndex + mtx)), pmd.Unknown, mtx);
                        renderPacket.DrawIndexes[mtx] = _file.Shapes.GetMatrixTableIndex((ushort)(pmd.FirstIndex + mtx));
                    }

                    J3DFormat.BatchPacketLocation packetLoc = _file.Shapes.GetBatchPacketLocation((ushort)(batch.PacketIndex + p));
                    uint numPrimitiveBytesRead = packetLoc.Offset;
                    while (numPrimitiveBytesRead < packetLoc.Offset + packetLoc.PacketSize)
                    {
                        J3DFormat.BatchPrimitive primitive = _file.Shapes.GetPrimitive(numPrimitiveBytesRead);
                        numPrimitiveBytesRead += J3DFormat.BatchPrimitive.Size;

                        //Game pads the chunks out with zeros, so this is signal for early break.
                        if (primitive.Type == 0)
                        {
                            break;
                        }

                        var primList = new PrimitiveList();
                        primList.VertexCount = primitive.VertexCount;
                        primList.VertexStart = finalData.Count;
                        primList.DrawType    = primitive.Type == J3DFormat.PrimitiveTypes.TriangleStrip ? PrimitiveType.TriangleStrip : PrimitiveType.TriangleFan; //Todo: More support
                        renderPacket.PrimList.Add(primList);

                        for (int vert = 0; vert < primitive.VertexCount; vert++)
                        {
                            J3DRenderer.VertexFormatLayout newVertex = new J3DRenderer.VertexFormatLayout();
                            for (uint vertIndex = 0; vertIndex < attributeCount; vertIndex++)
                            {
                                var    batchAttrib = _file.Shapes.GetAttribute(vertIndex, batch.AttribOffset);
                                ushort curIndex    = _file.Shapes.GetPrimitiveIndex(numPrimitiveBytesRead, batchAttrib);

                                switch (batchAttrib.AttribType)
                                {
                                case J3DFormat.ArrayTypes.Position:
                                    newVertex.Position = _file.Vertexes.GetPosition(curIndex);
                                    break;

                                case J3DFormat.ArrayTypes.Normal:
                                    newVertex.Color = new Vector4(_file.Vertexes.GetNormal(curIndex, 14), 1);     //temp
                                    break;

                                case J3DFormat.ArrayTypes.Color0:
                                    newVertex.Color = _file.Vertexes.GetColor0(curIndex);
                                    break;

                                case J3DFormat.ArrayTypes.Tex0:
                                    newVertex.TexCoord = _file.Vertexes.GetTex0(curIndex, 8);
                                    break;

                                case J3DFormat.ArrayTypes.PositionMatrixIndex:
                                    //Console.WriteLine("B: {0} P: {1} Prim: {2} Vert{3} Index: {4}", i, p, renderPacket.PrimList.Count, vert, curIndex);
                                    primList.PosMatrixIndex.Add(curIndex);
                                    break;

                                default:
                                    Console.WriteLine("Unknown AttribType {0}, Index: {1}", batchAttrib.AttribType, curIndex);
                                    break;
                                }

                                numPrimitiveBytesRead += GetAttribElementSize(batchAttrib.DataType);
                            }

                            //Add our vertex to our list of Vertexes
                            finalData.Add(newVertex);
                        }

                        //Console.WriteLine("Batch {0} Prim {1} #Vertices with PosMtxIndex: {2}", i, p, primList.PosMatrixIndex.Count);
                    }
                }

                //Console.WriteLine("Finished batch {0}, triangleStrip count: {1}", i, _renderList.Count);
            }

            return(finalData);
        }
Beispiel #16
0
        public static CnkLOD LoadFromStream(string name, string displayName, MemoryStream stream)
        {
            CnkLOD       chunk        = new CnkLOD();
            BinaryReader binaryReader = new BinaryReader(stream);

            chunk.Name        = name;
            chunk.DisplayName = displayName;
            //Header
            byte[] magic = binaryReader.ReadBytes(4);

            if (magic[0] != 'C' ||
                magic[1] != 'N' ||
                magic[2] != 'K' /* ||
                                 * magic[3] != '1'*/)
            {
                return(null);
            }

            chunk.Version = binaryReader.ReadUInt32();

            if (!Enum.IsDefined(typeof(ChunkType), (int)chunk.Version))
            {
                Debug.LogWarning("Could not decode chunk " + name + ". Unknown cnk version " + chunk.Version);
                return(null);
            }

            chunk.ChunkType = (ChunkType)chunk.Version;

            chunk.DecompressedSize = binaryReader.ReadUInt32();
            chunk.CompressedSize   = binaryReader.ReadUInt32();

            //Decompression
            byte[] compressedBuffer   = binaryReader.ReadBytes((int)chunk.CompressedSize);
            byte[] decompressedBuffer = new byte[chunk.DecompressedSize];

            InflateReturnCode result = LzhamInterop.DecompressForgelightData(compressedBuffer, chunk.CompressedSize, decompressedBuffer, chunk.DecompressedSize);

            if (result != InflateReturnCode.LZHAM_Z_STREAM_END && result != InflateReturnCode.LZHAM_Z_OK)
            {
                //This chunk is invalid.
                return(null);
            }

            using (MemoryStream decompressedStream = new MemoryStream(decompressedBuffer))
            {
                binaryReader = new BinaryReader(decompressedStream);

                //Textures
                uint textureCount = binaryReader.ReadUInt32();
                chunk.Textures = new List <Texture>((int)textureCount);

                for (int i = 0; i < textureCount; i++)
                {
                    Texture texture = new Texture();

                    uint colorNxMapSize = binaryReader.ReadUInt32();
                    if (colorNxMapSize > 0)
                    {
                        texture.ColorNXMap = binaryReader.ReadBytes((int)colorNxMapSize).ToList();
                    }

                    uint specNyMapSize = binaryReader.ReadUInt32();
                    if (specNyMapSize > 0)
                    {
                        texture.SpecNyMap = binaryReader.ReadBytes((int)specNyMapSize).ToList();
                    }

                    uint extraData1Size = binaryReader.ReadUInt32();
                    if (extraData1Size > 0)
                    {
                        texture.ExtraData1 = binaryReader.ReadBytes((int)extraData1Size).ToList();
                    }

                    uint extraData2Size = binaryReader.ReadUInt32();
                    if (extraData2Size > 0)
                    {
                        texture.ExtraData2 = binaryReader.ReadBytes((int)extraData2Size).ToList();
                    }

                    uint extraData3Size = binaryReader.ReadUInt32();
                    if (extraData3Size > 0)
                    {
                        texture.ExtraData3 = binaryReader.ReadBytes((int)extraData3Size).ToList();
                    }

                    uint extraData4Size = binaryReader.ReadUInt32();
                    if (extraData4Size > 0)
                    {
                        texture.ExtraData4 = binaryReader.ReadBytes((int)extraData4Size).ToList();
                    }

                    chunk.Textures.Add(texture);
                }

                //Verts Per Side
                chunk.VertsPerSide = binaryReader.ReadUInt32();

                //Height Maps
                uint heightMapCount = binaryReader.ReadUInt32();

                int n = (int)(heightMapCount / 4);

                for (int i = 0; i < 4; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        Dictionary <int, HeightMap> entry;

                        if (!chunk.HeightMaps.ContainsKey(i))
                        {
                            entry = new Dictionary <int, HeightMap>();
                            chunk.HeightMaps[i] = entry;
                        }

                        else
                        {
                            entry = chunk.HeightMaps[i];
                        }

                        HeightMap heightMapData = new HeightMap();
                        heightMapData.Val1 = binaryReader.ReadInt16();
                        heightMapData.Val2 = binaryReader.ReadByte();
                        heightMapData.Val3 = binaryReader.ReadByte();

                        entry[j] = heightMapData;
                    }
                }

                //Indices
                uint indexCount = binaryReader.ReadUInt32();
                chunk.Indices = new List <ushort>((int)indexCount);

                for (int i = 0; i < indexCount; i++)
                {
                    chunk.Indices.Add(binaryReader.ReadUInt16());
                }

                //Verts
                uint vertCount = binaryReader.ReadUInt32();
                chunk.Vertices = new List <Vertex>((int)vertCount);

                for (int i = 0; i < vertCount; i++)
                {
                    Vertex vertex = new Vertex();

                    vertex.X          = binaryReader.ReadInt16();
                    vertex.Y          = binaryReader.ReadInt16();
                    vertex.HeightFar  = binaryReader.ReadInt16();
                    vertex.HeightNear = binaryReader.ReadInt16();
                    vertex.Color      = binaryReader.ReadUInt32();

                    chunk.Vertices.Add(vertex);
                }

                //TODO HACK - Daybreak, why are some chunks (that have a version 2 header) actually version 1?
                long offset = binaryReader.BaseStream.Position;
                try
                {
                    //Render Batches
                    uint renderBatchCount = binaryReader.ReadUInt32();
                    chunk.RenderBatches = new List <RenderBatch>((int)renderBatchCount);

                    for (int i = 0; i < renderBatchCount; i++)
                    {
                        RenderBatch renderBatch = new RenderBatch();

                        if (chunk.ChunkType == ChunkType.H1Z1_Planetside2V2)
                        {
                            renderBatch.Unknown = binaryReader.ReadUInt32();
                        }

                        renderBatch.IndexOffset  = binaryReader.ReadUInt32();
                        renderBatch.IndexCount   = binaryReader.ReadUInt32();
                        renderBatch.VertexOffset = binaryReader.ReadUInt32();
                        renderBatch.VertexCount  = binaryReader.ReadUInt32();

                        chunk.RenderBatches.Add(renderBatch);
                    }

                    //Optimized Draw
                    uint optimizedDrawCount = binaryReader.ReadUInt32();
                    chunk.OptimizedDraws = new List <OptimizedDraw>((int)optimizedDrawCount);

                    for (int i = 0; i < optimizedDrawCount; i++)
                    {
                        OptimizedDraw optimizedDraw = new OptimizedDraw();
                        optimizedDraw.Data = binaryReader.ReadBytes(320).ToList();

                        chunk.OptimizedDraws.Add(optimizedDraw);
                    }

                    //Unknown Data
                    uint unknownShort1Count = binaryReader.ReadUInt32();
                    chunk.UnknownShorts1 = new List <ushort>((int)unknownShort1Count);

                    for (int i = 0; i < unknownShort1Count; i++)
                    {
                        chunk.UnknownShorts1.Add(binaryReader.ReadUInt16());
                    }

                    //Unknown Data
                    uint unknownVectors1Count = binaryReader.ReadUInt32();
                    chunk.UnknownVectors1 = new List <Vector3>((int)unknownVectors1Count);

                    for (int i = 0; i < unknownVectors1Count; i++)
                    {
                        chunk.UnknownVectors1.Add(new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()));
                    }

                    //Tile Occluder Info
                    uint tileOccluderCount = binaryReader.ReadUInt32();
                    chunk.TileOccluderInfos = new List <TileOccluderInfo>((int)tileOccluderCount);

                    for (int i = 0; i < tileOccluderCount; i++)
                    {
                        TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                        tileOccluderInfo.Data = binaryReader.ReadBytes(64).ToList();

                        chunk.TileOccluderInfos.Add(tileOccluderInfo);
                    }
                }
                catch (Exception)
                {
                    binaryReader.BaseStream.Position = offset;

                    //Render Batches
                    uint renderBatchCount = binaryReader.ReadUInt32();
                    chunk.RenderBatches = new List <RenderBatch>((int)renderBatchCount);

                    for (int i = 0; i < renderBatchCount; i++)
                    {
                        RenderBatch renderBatch = new RenderBatch();

                        renderBatch.IndexOffset  = binaryReader.ReadUInt32();
                        renderBatch.IndexCount   = binaryReader.ReadUInt32();
                        renderBatch.VertexOffset = binaryReader.ReadUInt32();
                        renderBatch.VertexCount  = binaryReader.ReadUInt32();

                        chunk.RenderBatches.Add(renderBatch);
                    }

                    //Optimized Draw
                    uint optimizedDrawCount = binaryReader.ReadUInt32();
                    chunk.OptimizedDraws = new List <OptimizedDraw>((int)optimizedDrawCount);

                    for (int i = 0; i < optimizedDrawCount; i++)
                    {
                        OptimizedDraw optimizedDraw = new OptimizedDraw();
                        optimizedDraw.Data = binaryReader.ReadBytes(320).ToList();

                        chunk.OptimizedDraws.Add(optimizedDraw);
                    }

                    //Unknown Data
                    uint unknownShort1Count = binaryReader.ReadUInt32();
                    chunk.UnknownShorts1 = new List <ushort>((int)unknownShort1Count);

                    for (int i = 0; i < unknownShort1Count; i++)
                    {
                        chunk.UnknownShorts1.Add(binaryReader.ReadUInt16());
                    }

                    //Unknown Data
                    uint unknownVectors1Count = binaryReader.ReadUInt32();
                    chunk.UnknownVectors1 = new List <Vector3>((int)unknownVectors1Count);

                    for (int i = 0; i < unknownVectors1Count; i++)
                    {
                        chunk.UnknownVectors1.Add(new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()));
                    }

                    //Tile Occluder Info
                    uint tileOccluderCount = binaryReader.ReadUInt32();
                    chunk.TileOccluderInfos = new List <TileOccluderInfo>((int)tileOccluderCount);

                    for (int i = 0; i < tileOccluderCount; i++)
                    {
                        TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                        tileOccluderInfo.Data = binaryReader.ReadBytes(64).ToList();

                        chunk.TileOccluderInfos.Add(tileOccluderInfo);
                    }
                }
            }

            return(chunk);
        }
Beispiel #17
0
        static void ReadMOBA(BinaryReader br, WMOGroup group, uint size)
        {
            // Render batches. Records of 24 bytes.
            group.Batches = new RenderBatch[size/24];

            for (int i = 0; i < group.Batches.Length; i++)
            {
                var batch = new RenderBatch
                                {
                                    BottomX = br.ReadInt16(),
                                    BottomY = br.ReadInt16(),
                                    BottomZ = br.ReadInt16(),
                                    TopX = br.ReadInt16(),
                                    TopY = br.ReadInt16(),
                                    TopZ = br.ReadInt16(),
                                    StartIndex = br.ReadInt32(),
                                    IndexCount = br.ReadUInt16(),
                                    VertexStart = br.ReadUInt16(),
                                    VertexEnd = br.ReadUInt16(),
                                    Byte_13 = br.ReadByte(),
                                    TextureIndex = br.ReadByte()
                                };

                group.Batches[i] = batch;
            }
        }
Beispiel #18
0
        /// <summary>
        /// Initializes a new instance of the <see cref="OcclusionBuffer"/> class with the specified
        /// buffer size.
        /// </summary>
        /// <param name="graphicsService">The graphics service.</param>
        /// <param name="width">The width of the occlusion buffer.</param>
        /// <param name="height">The height of the occlusion buffer.</param>
        /// <param name="bufferSize">
        /// The size of the internal triangle buffer (= max number of occluder triangles that can be
        /// rendered in a single draw call). Needs to be large enough to store the most complex 
        /// occluder.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="graphicsService"/> is <see langword="null"/>.
        /// </exception>
        public OcclusionBuffer(IGraphicsService graphicsService, int width, int height, int bufferSize)
        {
            if (graphicsService == null)
            throw new ArgumentNullException("graphicsService");

              // For simplicity only accept power-of-two formats.
              if (!MathHelper.IsPowerOf2(width) && !MathHelper.IsPowerOf2(height))
            throw new ArgumentException("Width and height of occlusion buffer expected to be a power of two.");

              // The current texture atlas layout assumes that width ≥ height.
              if (width < height)
            throw new ArgumentException("Width expected to be greater than or equal to the height of the occlusion buffer.");

              var graphicsDevice = graphicsService.GraphicsDevice;
              if (bufferSize < 1)
            throw new ArgumentOutOfRangeException("bufferSize", "The buffer size needs to be creater than 1.");
              if (bufferSize >= graphicsDevice.GetMaxPrimitivesPerCall())
            throw new ArgumentOutOfRangeException("bufferSize", "The buffer size exceeds the max number of primitives supported by the current graphics device.");

              // ----- RenderBatch handles occluders.
              // bufferSize is the max number of triangles per draw call.

              // Vertex buffer size:
              // - In the worst case n triangles need n * 3 vertices.
              // - The max size is limited to 65536 because 16-bit indices are used.
              var vertices = new Vector3F[Math.Min(bufferSize * 3, ushort.MaxValue + 1)];

              // Index buffer size: number of triangles * 3
              var indices = new ushort[bufferSize * 3];

              _renderBatch = new RenderBatch<Vector3F, ushort>(
            graphicsDevice,
            VertexPosition.VertexDeclaration,
            vertices, true,
            indices, true);

              _effect = graphicsService.Content.Load<Effect>("DigitalRune/OcclusionCulling");
              _parameterClampAabbMinimum = _effect.Parameters["ClampAabbMinimum"];
              _parameterClampAabbMaximum = _effect.Parameters["ClampAabbMaximum"];
              _parameterCameraViewProj = _effect.Parameters["CameraViewProj"];
              _parameterCameraNear = _effect.Parameters["CameraNear"];
              _parameterCameraFar = _effect.Parameters["CameraFar"];
              _parameterCameraPosition = _effect.Parameters["CameraPosition"];
              _parameterNormalizationFactor = _effect.Parameters["NormalizationFactor"];
              _parameterLightViewProj = _effect.Parameters["LightViewProj"];
              _parameterLightToCamera = _effect.Parameters["LightToCamera"];
              _parameterHzbSize = _effect.Parameters["HzbSize"];
              _parameterTargetSize = _effect.Parameters["TargetSize"];
              _parameterAtlasSize = _effect.Parameters["AtlasSize"];
              _parameterTexelOffset = _effect.Parameters["TexelOffset"];
              _parameterHalfTexelOffset = _effect.Parameters["HalfTexelOffset"];
              _parameterMaxLevel = _effect.Parameters["MaxLevel"];
              _parameterHzbTexture = _effect.Parameters["HzbTexture"];
              _parameterLightHzbTexture = _effect.Parameters["LightHzb"];
              _parameterDebugLevel = _effect.Parameters["DebugLevel"];
              _parameterDebugMinimum = _effect.Parameters["DebugMinimum"];
              _parameterDebugMaximum = _effect.Parameters["DebugMaximum"];
              _techniqueOccluder = _effect.Techniques["Occluder"];
              _techniqueDownsample = _effect.Techniques["Downsample"];
              _techniqueCopy = _effect.Techniques["Copy"];
              _techniqueQuery = _effect.Techniques["Query"];
              _techniqueVisualize = _effect.Techniques["Visualize"];

              _occlusionProxies = new List<IOcclusionProxy>();
              _sceneNodes = new List<SceneNode>();

              // Store delegate methods to avoid garbage.
              _updateOcclusionProxies = UpdateOcclusionProxies;
              _updateOcclusionProxy = UpdateOcclusionProxy;

              _splitVolume = new PerspectiveViewVolume();
              _orthographicCameraNode = new CameraNode(new Camera(new OrthographicProjection()));

              _shadowCasters = new List<SceneNode>();

            /*
              // By default, enable multithreading on multi-core systems.
            #if WP7 || UNITY
              // Cannot access Environment.ProcessorCount in phone app. (Security issue.)
              EnableMultithreading = false;
            #else
              // Enable multithreading by default if the current system has multiple processors.
              EnableMultithreading = Environment.ProcessorCount > 1;

              // Multithreading works but Parallel.For of Xamarin.Android/iOS is very inefficient.
              if (GlobalSettings.PlatformID == PlatformID.Android || GlobalSettings.PlatformID == PlatformID.iOS)
            EnableMultithreading = false;
            #endif
            */
              // Disable multithreading by default. Multithreading causes massive lags in the
              // XNA version, but the MonoGame version is not affected!?
              EnableMultithreading = false;

              // For best performance: Enable progressive shadow caster culling.
              ProgressiveShadowCasterCulling = true;

              Statistics = new OcclusionCullingStatistics();

              InitializeBuffers(graphicsDevice, width, height);
        }
Beispiel #19
0
        BatchInfo GetCreateBatchInfo(ResourceHandle<Image> imageHandle)
        {
            var hId = imageHandle.Id;
            if (!batches.ContainsKey(hId))
            {
                var batch = new RenderBatch();
                batch.SetGeometryBuffer(gb);
                batch.SetRenderLayer(RenderLayer.Overlays);
                batch.SetPrimitiveType(PrimitiveType.Quads);

                var mat = GetCreateMaterial(imageHandle);
                batch.SetMaterial(mat);

                var bInfo = new BatchInfo {Batch = batch};
                batches[hId] = bInfo;
            }

            return batches[hId];
        }
Beispiel #20
0
            public static LoadError LoadFromStream(Stream stream, out RenderBatch renderBatch)
            {
                BinaryReader binaryReader = new BinaryReader(stream, Encoding.Default, true);

                renderBatch = new RenderBatch();
                renderBatch.IndexOffset = binaryReader.ReadUInt32();
                renderBatch.IndexCount = binaryReader.ReadUInt32();
                renderBatch.VertexOffset = binaryReader.ReadUInt32();
                renderBatch.VertexCount = binaryReader.ReadUInt32();

                return LoadError.None;
            }
        public bool InitializeFromStream(string name, string displayName, MemoryStream stream)
        {
            using (BinaryReader binaryReader = new BinaryReader(stream))
            {
                Name        = name;
                DisplayName = displayName;

                //Header
                byte[] magic = binaryReader.ReadBytes(4);

                if (magic[0] != 'C' ||
                    magic[1] != 'N' ||
                    magic[2] != 'K' /* ||
                                     * magic[3] != '1'*/)
                {
                    return(false);
                }

                Version = binaryReader.ReadUInt32();

                if (!Enum.IsDefined(typeof(ChunkType), (int)Version))
                {
                    Debug.LogWarning("Could not decode chunk " + name + ". Unknown cnk version " + Version);
                    return(false);
                }

                ChunkType = (ChunkType)Version;

                DecompressedSize = binaryReader.ReadUInt32();
                CompressedSize   = binaryReader.ReadUInt32();

                // Decompression
                // Make sure our buffers are large enough.
                if (CompressedBuffer.Length < CompressedSize)
                {
                    Array.Resize(ref CompressedBuffer, (int)CompressedSize);
                }

                if (DecompressedBuffer.Length < DecompressedSize)
                {
                    Array.Resize(ref DecompressedBuffer, (int)DecompressedSize);
                }

                // Read the compressed buffer.
                binaryReader.Read(CompressedBuffer, 0, (int)CompressedSize);

                // Perform decompression using Lzham.
                InflateReturnCode result = LzhamInterop.DecompressForgelightData(CompressedBuffer, CompressedSize, DecompressedBuffer, DecompressedSize);

                if (result != InflateReturnCode.LZHAM_Z_STREAM_END && result != InflateReturnCode.LZHAM_Z_OK)
                {
                    //This chunk is invalid, or something went wrong.
                    return(false);
                }
            }

            using (MemoryStream decompressedStream = new MemoryStream(DecompressedBuffer, 0, (int)DecompressedSize))
            {
                using (BinaryReader binaryReader = new BinaryReader(decompressedStream))
                {
                    //Textures
                    uint textureCount = binaryReader.ReadUInt32();

                    for (int i = 0; i < textureCount; i++)
                    {
                        Texture texture = new Texture();

                        uint colorNxMapSize = binaryReader.ReadUInt32();
                        if (colorNxMapSize > 0)
                        {
                            texture.ColorNXMap = binaryReader.ReadBytes((int)colorNxMapSize).ToList();
                        }

                        uint specNyMapSize = binaryReader.ReadUInt32();
                        if (specNyMapSize > 0)
                        {
                            texture.SpecNyMap = binaryReader.ReadBytes((int)specNyMapSize).ToList();
                        }

                        uint extraData1Size = binaryReader.ReadUInt32();
                        if (extraData1Size > 0)
                        {
                            texture.ExtraData1 = binaryReader.ReadBytes((int)extraData1Size).ToList();
                        }

                        uint extraData2Size = binaryReader.ReadUInt32();
                        if (extraData2Size > 0)
                        {
                            texture.ExtraData2 = binaryReader.ReadBytes((int)extraData2Size).ToList();
                        }

                        uint extraData3Size = binaryReader.ReadUInt32();
                        if (extraData3Size > 0)
                        {
                            texture.ExtraData3 = binaryReader.ReadBytes((int)extraData3Size).ToList();
                        }

                        uint extraData4Size = binaryReader.ReadUInt32();
                        if (extraData4Size > 0)
                        {
                            texture.ExtraData4 = binaryReader.ReadBytes((int)extraData4Size).ToList();
                        }

                        Textures.Add(texture);
                    }

                    //Verts Per Side
                    VertsPerSide = binaryReader.ReadUInt32();

                    //Height Maps
                    uint heightMapCount = binaryReader.ReadUInt32();

                    int n = (int)(heightMapCount / 4);

                    for (int i = 0; i < 4; i++)
                    {
                        for (int j = 0; j < n; j++)
                        {
                            Dictionary <int, HeightMap> entry;

                            if (!HeightMaps.ContainsKey(i))
                            {
                                entry         = new Dictionary <int, HeightMap>();
                                HeightMaps[i] = entry;
                            }

                            else
                            {
                                entry = HeightMaps[i];
                            }

                            HeightMap heightMapData = new HeightMap();
                            heightMapData.Val1 = binaryReader.ReadInt16();
                            heightMapData.Val2 = binaryReader.ReadByte();
                            heightMapData.Val3 = binaryReader.ReadByte();

                            entry[j] = heightMapData;
                        }
                    }

                    //Indices
                    uint indexCount = binaryReader.ReadUInt32();

                    for (int i = 0; i < indexCount; i++)
                    {
                        Indices.Add(binaryReader.ReadUInt16());
                    }

                    //Verts
                    uint vertCount = binaryReader.ReadUInt32();

                    for (int i = 0; i < vertCount; i++)
                    {
                        Vertex vertex = new Vertex();

                        vertex.X          = binaryReader.ReadInt16();
                        vertex.Y          = binaryReader.ReadInt16();
                        vertex.HeightFar  = binaryReader.ReadInt16();
                        vertex.HeightNear = binaryReader.ReadInt16();
                        vertex.Color      = binaryReader.ReadUInt32();

                        Vertices.Add(vertex);
                    }

                    //TODO HACK - Daybreak, why are some chunks (that have a version 2 header) actually version 1?
                    long offset = binaryReader.BaseStream.Position;
                    try
                    {
                        //Render Batches
                        uint renderBatchCount = binaryReader.ReadUInt32();

                        for (int i = 0; i < renderBatchCount; i++)
                        {
                            RenderBatch renderBatch = new RenderBatch();

                            if (ChunkType == ChunkType.H1Z1_Planetside2V2)
                            {
                                renderBatch.Unknown = binaryReader.ReadUInt32();
                            }

                            renderBatch.IndexOffset  = binaryReader.ReadUInt32();
                            renderBatch.IndexCount   = binaryReader.ReadUInt32();
                            renderBatch.VertexOffset = binaryReader.ReadUInt32();
                            renderBatch.VertexCount  = binaryReader.ReadUInt32();

                            RenderBatches.Add(renderBatch);
                        }

                        //Optimized Draw
                        uint optimizedDrawCount = binaryReader.ReadUInt32();

                        for (int i = 0; i < optimizedDrawCount; i++)
                        {
                            OptimizedDraw optimizedDraw = new OptimizedDraw();
                            optimizedDraw.Data = binaryReader.ReadBytes(320).ToList();

                            OptimizedDraws.Add(optimizedDraw);
                        }

                        //Unknown Data
                        uint unknownShort1Count = binaryReader.ReadUInt32();

                        for (int i = 0; i < unknownShort1Count; i++)
                        {
                            UnknownShorts1.Add(binaryReader.ReadUInt16());
                        }

                        //Unknown Data
                        uint unknownVectors1Count = binaryReader.ReadUInt32();

                        for (int i = 0; i < unknownVectors1Count; i++)
                        {
                            UnknownVectors1.Add(new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(),
                                                            binaryReader.ReadSingle()));
                        }

                        //Tile Occluder Info
                        uint tileOccluderCount = binaryReader.ReadUInt32();

                        if (tileOccluderCount > 16)
                        {
                            throw new ArgumentOutOfRangeException();
                        }

                        for (int i = 0; i < tileOccluderCount; i++)
                        {
                            TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                            tileOccluderInfo.Data = binaryReader.ReadBytes(64).ToList();

                            TileOccluderInfos.Add(tileOccluderInfo);
                        }
                    }
                    catch (Exception)
                    {
                        // Some of these may have been populated from the "try".
                        RenderBatches.Clear();
                        OptimizedDraws.Clear();
                        UnknownShorts1.Clear();
                        UnknownVectors1.Clear();
                        TileOccluderInfos.Clear();

                        binaryReader.BaseStream.Position = offset;

                        //Render Batches
                        uint renderBatchCount = binaryReader.ReadUInt32();

                        for (int i = 0; i < renderBatchCount; i++)
                        {
                            RenderBatch renderBatch = new RenderBatch();

                            renderBatch.IndexOffset  = binaryReader.ReadUInt32();
                            renderBatch.IndexCount   = binaryReader.ReadUInt32();
                            renderBatch.VertexOffset = binaryReader.ReadUInt32();
                            renderBatch.VertexCount  = binaryReader.ReadUInt32();

                            RenderBatches.Add(renderBatch);
                        }

                        //Optimized Draw
                        uint optimizedDrawCount = binaryReader.ReadUInt32();

                        for (int i = 0; i < optimizedDrawCount; i++)
                        {
                            OptimizedDraw optimizedDraw = new OptimizedDraw();
                            optimizedDraw.Data = binaryReader.ReadBytes(320).ToList();

                            OptimizedDraws.Add(optimizedDraw);
                        }

                        //Unknown Data
                        uint unknownShort1Count = binaryReader.ReadUInt32();

                        for (int i = 0; i < unknownShort1Count; i++)
                        {
                            UnknownShorts1.Add(binaryReader.ReadUInt16());
                        }

                        //Unknown Data
                        uint unknownVectors1Count = binaryReader.ReadUInt32();

                        for (int i = 0; i < unknownVectors1Count; i++)
                        {
                            UnknownVectors1.Add(new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(),
                                                            binaryReader.ReadSingle()));
                        }

                        //Tile Occluder Info
                        uint tileOccluderCount = binaryReader.ReadUInt32();

                        if (tileOccluderCount > 16)
                        {
                            return(false);
                        }

                        for (int i = 0; i < tileOccluderCount; i++)
                        {
                            TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                            tileOccluderInfo.Data = binaryReader.ReadBytes(64).ToList();

                            TileOccluderInfos.Add(tileOccluderInfo);
                        }
                    }
                }
            }

            return(true);
        }
Beispiel #22
0
        public static void ExportADT(uint wdtFileDataID, byte tileX, byte tileY, BackgroundWorker exportworker = null)
        {
            if (exportworker == null)
            {
                exportworker = new BackgroundWorker();
                exportworker.WorkerReportsProgress = true;
            }

            var outdir = "export";

            var customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();

            customCulture.NumberFormat.NumberDecimalSeparator    = ".";
            System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;

            var MaxSize      = 51200 / 3.0;
            var TileSize     = MaxSize / 32.0;
            var ChunkSize    = TileSize / 16.0;
            var UnitSize     = ChunkSize / 8.0;
            var UnitSizeHalf = UnitSize / 2.0;

            var wdtFilename = "world/maps/azeroth/azeroth.wdt";

            var mapName = Path.GetFileNameWithoutExtension(wdtFilename);
            var file    = "world/maps/" + mapName + "/" + mapName + "_" + tileX.ToString() + "_" + tileY.ToString() + ".adt";

            var reader = new ADTReader();

            reader.LoadADT(wdtFileDataID, tileX, tileY, true, wdtFilename);

            if (reader.adtfile.chunks == null)
            {
                Logger.WriteLine("ADT OBJ Exporter: File {0} has no chunks, skipping export!", file);
                return;
            }

            Logger.WriteLine("ADT OBJ Exporter: Starting export of {0}..", file);

            Directory.CreateDirectory(Path.Combine(outdir, Path.GetDirectoryName(file)));

            exportworker.ReportProgress(0, "Loading ADT " + file);

            var renderBatches = new List <RenderBatch>();
            var verticelist   = new List <Vertex>();
            var indicelist    = new List <int>();
            var materials     = new Dictionary <int, string>();

            var bakeQuality = "none";

            // Calculate ADT offset in world coordinates
            var adtStartX = ((reader.adtfile.x - 32) * TileSize) * -1;
            var adtStartY = ((reader.adtfile.y - 32) * TileSize) * -1;

            // Calculate first chunk offset in world coordinates
            var initialChunkX = adtStartY + (reader.adtfile.chunks[0].header.indexX * ChunkSize) * -1;
            var initialChunkY = adtStartX + (reader.adtfile.chunks[0].header.indexY * ChunkSize) * -1;

            uint ci = 0;

            for (var x = 0; x < 16; x++)
            {
                double xOfs = x / 16d;
                for (var y = 0; y < 16; y++)
                {
                    double yOfs = y / 16d;

                    var genx = (initialChunkX + (ChunkSize * x) * -1);
                    var geny = (initialChunkY + (ChunkSize * y) * -1);

                    var chunk = reader.adtfile.chunks[ci];

                    var off = verticelist.Count();

                    var batch = new RenderBatch();

                    for (int i = 0, idx = 0; i < 17; i++)
                    {
                        bool isSmallRow = (i % 2) != 0;
                        int  rowLength  = isSmallRow ? 8 : 9;

                        for (var j = 0; j < rowLength; j++)
                        {
                            var v = new Vertex();

                            v.Normal = new Vector3D
                            {
                                X = (double)chunk.normals.normal_0[idx] / 127,
                                Y = (double)chunk.normals.normal_2[idx] / 127,
                                Z = (double)chunk.normals.normal_1[idx] / 127
                            };

                            var px = geny - (j * UnitSize);
                            var py = chunk.vertices.vertices[idx++] + chunk.header.position.Z;
                            var pz = genx - (i * UnitSizeHalf);

                            v.Position = new Vector3D
                            {
                                X = px,
                                Y = py,
                                Z = pz
                            };

                            if ((i % 2) != 0)
                            {
                                v.Position.X = (px - UnitSizeHalf);
                            }

                            double ofs = j;
                            if (isSmallRow)
                            {
                                ofs += 0.5;
                            }

                            if (bakeQuality == "high")
                            {
                                double tx = ofs / 8d;
                                double ty = 1 - (i / 16d);
                                v.TexCoord = new Vector2D {
                                    X = tx, Y = ty
                                };
                            }
                            else
                            {
                                double tx = -(v.Position.X - initialChunkY) / TileSize;
                                double ty = (v.Position.Z - initialChunkX) / TileSize;

                                v.TexCoord = new Vector2D {
                                    X = tx, Y = ty
                                };
                            }
                            verticelist.Add(v);
                        }
                    }

                    batch.firstFace = (uint)indicelist.Count();

                    // Stupid C# and its structs
                    var holesHighRes = new byte[8];
                    holesHighRes[0] = chunk.header.holesHighRes_0;
                    holesHighRes[1] = chunk.header.holesHighRes_1;
                    holesHighRes[2] = chunk.header.holesHighRes_2;
                    holesHighRes[3] = chunk.header.holesHighRes_3;
                    holesHighRes[4] = chunk.header.holesHighRes_4;
                    holesHighRes[5] = chunk.header.holesHighRes_5;
                    holesHighRes[6] = chunk.header.holesHighRes_6;
                    holesHighRes[7] = chunk.header.holesHighRes_7;

                    for (int j = 9, xx = 0, yy = 0; j < 145; j++, xx++)
                    {
                        if (xx >= 8)
                        {
                            xx = 0; ++yy;
                        }
                        var isHole = true;

                        // Check if chunk is using low-res holes
                        if ((chunk.header.flags & 0x10000) == 0)
                        {
                            // Calculate current hole number
                            var currentHole = (int)Math.Pow(2,
                                                            Math.Floor(xx / 2f) * 1f +
                                                            Math.Floor(yy / 2f) * 4f);

                            // Check if current hole number should be a hole
                            if ((chunk.header.holesLowRes & currentHole) == 0)
                            {
                                isHole = false;
                            }
                        }

                        else
                        {
                            // Check if current section is a hole
                            if (((holesHighRes[yy] >> xx) & 1) == 0)
                            {
                                isHole = false;
                            }
                        }

                        if (!isHole)
                        {
                            indicelist.AddRange(new int[] { off + j + 8, off + j - 9, off + j });
                            indicelist.AddRange(new int[] { off + j - 9, off + j - 8, off + j });
                            indicelist.AddRange(new int[] { off + j - 8, off + j + 9, off + j });
                            indicelist.AddRange(new int[] { off + j + 9, off + j + 8, off + j });

                            // Generates quads instead of 4x triangles
                            //indicelist.AddRange(new int[] { off + j + 8, off + j - 9, off + j - 8 });
                            //indicelist.AddRange(new int[] { off + j - 8, off + j + 9, off + j + 8 });
                        }

                        if ((j + 1) % (9 + 8) == 0)
                        {
                            j += 9;
                        }
                    }

                    if (bakeQuality == "high")
                    {
                        materials.Add((int)ci + 1, Path.GetFileNameWithoutExtension(file).Replace(" ", "") + "_" + ci);
                        batch.materialID = ci + 1;
                    }
                    else
                    {
                        if (!materials.ContainsKey(1))
                        {
                            materials.Add(1, Path.GetFileNameWithoutExtension(file).Replace(" ", ""));
                        }
                        batch.materialID = (uint)materials.Count();
                    }

                    batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace;

                    var layermats = new List <uint>();


                    renderBatches.Add(batch);
                    ci++;
                }
            }

            exportworker.ReportProgress(75, "Exporting terrain textures..");

            if (bakeQuality != "none")
            {
                var mtlsw = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".mtl"));

                //No idea how MTL files really work yet. Needs more investigation.
                foreach (var material in materials)
                {
                    mtlsw.WriteLine("newmtl " + material.Value.Replace(" ", ""));
                    mtlsw.WriteLine("Ka 1.000000 1.000000 1.000000");
                    mtlsw.WriteLine("Kd 0.640000 0.640000 0.640000");
                    mtlsw.WriteLine("map_Ka " + material.Value.Replace(" ", "") + ".png");
                    mtlsw.WriteLine("map_Kd " + material.Value.Replace(" ", "") + ".png");
                }

                mtlsw.Close();
            }

            exportworker.ReportProgress(85, "Exporting terrain geometry..");

            var indices = indicelist.ToArray();

            var adtname = Path.GetFileNameWithoutExtension(file);

            var objsw = new StreamWriter(Path.Combine(outdir, Path.GetDirectoryName(file), Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".obj"));

            objsw.WriteLine("# Written by Marlamin's WoW OBJExporter. Original file: " + file);
            if (bakeQuality != "none")
            {
                objsw.WriteLine("mtllib " + Path.GetFileNameWithoutExtension(file).Replace(" ", "") + ".mtl");
            }

            var verticeCounter = 1;
            var chunkCounter   = 1;

            foreach (var vertex in verticelist)
            {
                //objsw.WriteLine("# C" + chunkCounter + ".V" + verticeCounter);
                objsw.WriteLine("v " + vertex.Position.X.ToString("R") + " " + vertex.Position.Y.ToString("R") + " " + vertex.Position.Z.ToString("R"));
                objsw.WriteLine("vt " + vertex.TexCoord.X + " " + vertex.TexCoord.Y);
                objsw.WriteLine("vn " + vertex.Normal.X.ToString("R") + " " + vertex.Normal.Y.ToString("R") + " " + vertex.Normal.Z.ToString("R"));
                verticeCounter++;
                if (verticeCounter == 146)
                {
                    chunkCounter++;
                    verticeCounter = 1;
                }
            }

            if (bakeQuality != "high")
            {
                objsw.WriteLine("g " + adtname.Replace(" ", ""));
                objsw.WriteLine("usemtl " + materials[1]);
                objsw.WriteLine("s 1");
            }

            for (int rbi = 0; rbi < renderBatches.Count(); rbi++)
            {
                var renderBatch = renderBatches[rbi];
                var i           = renderBatch.firstFace;
                if (bakeQuality == "high" && materials.ContainsKey((int)renderBatch.materialID))
                {
                    objsw.WriteLine("g " + adtname.Replace(" ", "") + "_" + rbi);
                    objsw.WriteLine("usemtl " + materials[(int)renderBatch.materialID]);
                }
                while (i < (renderBatch.firstFace + renderBatch.numFaces))
                {
                    objsw.WriteLine("f " +
                                    (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + "/" + (indices[i + 2] + 1) + " " +
                                    (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + "/" + (indices[i + 1] + 1) + " " +
                                    (indices[i] + 1) + "/" + (indices[i] + 1) + "/" + (indices[i] + 1));
                    i = i + 3;
                }
            }

            objsw.Close();

            Logger.WriteLine("ADT OBJ Exporter: Finished with export of {0}..", file);
        }
 public void Apply(RenderTreeDiff tree, RenderBatch batch)
 {
     //List<int> removedIndex = new List<int>();
     //List<View>
     //List<StyleSheet> deferedStyleSheet = new List<StyleSheet>();
     CurrentNode = InitialNode;
     foreach (var edit in tree.Edits)
     {
         var frame = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
         ProcessTree(edit, batch, edit.ReferenceFrameIndex, edit.Type == RenderTreeEditType.PrependFrame ? (frame.ElementSubtreeLength == 0 ? 1 : frame.ElementSubtreeLength) :1);
         //ProcessTree(edit, batch, edit.ReferenceFrameIndex, frame.ElementSubtreeLength == 0 ? 1 : frame.ElementSubtreeLength);
         //int subtreeIndex = 0;
         //do
         //{
         //    switch (edit.Type)
         //    {
         //        case RenderTreeEditType.PrependFrame:
         //            {
         //                switch (frame.FrameType)
         //                {
         //                    case RenderTreeFrameType.Component:
         //                        {
         //                            var childRenderer = new ComponentRenderer(frame.Component, WebViewRenderer, this);
         //                            WebViewRenderer.Renderers[frame.ComponentId] = childRenderer;
         //                        }
         //                        break;
         //                    case RenderTreeFrameType.Element:
         //                        {
         //                            WebViewRenderer.DOMManager.CreateElement(Sequences.ToArray(), frame.Sequence, frame.ElementName);
         //                            Sequences.Push(frame.Sequence);
         //                        }
         //                        break;
         //                    case RenderTreeFrameType.Attribute:
         //                        {
         //                            WebViewRenderer.DOMManager.SetAttribute(Sequences.ToArray(), frame.AttributeName, frame.AttributeValue);
         //                        }
         //                        break;
         //                    case RenderTreeFrameType.Text:
         //                        WebViewRenderer.DOMManager.InsertText(Sequences.ToArray(), frame.Sequence, frame.TextContent);
         //                        break;
         //                    case RenderTreeFrameType.Markup:
         //                        WebViewRenderer.DOMManager.InsertMarkup(Sequences.ToArray(), frame.Sequence, frame.MarkupContent);
         //                        break;
         //                    case RenderTreeFrameType.Region:
         //                        Sequences.Push(frame.Sequence);
         //                        int sequenceSubTrees = frame.RegionSubtreeLength;
         //                        break;
         //                    default:
         //                        throw new NotImplementedException($"Invalid Frame type: {frame.FrameType}");
         //                }
         //            }
         //            break;
         //        case RenderTreeEditType.UpdateText:
         //            {
         //                WebViewRenderer.DOMManager.InsertText(Sequences.ToArray(), frame.Sequence, frame.TextContent);
         //            }
         //            break;
         //        case RenderTreeEditType.RemoveFrame:
         //            {
         //                WebViewRenderer.DOMManager.RemoveAt(Sequences.ToArray(), edit.SiblingIndex);
         //            }
         //            break;
         //        case RenderTreeEditType.UpdateMarkup:
         //            {
         //                WebViewRenderer.DOMManager.InsertText(Sequences.ToArray(), frame.Sequence, frame.TextContent);
         //            }
         //            break;
         //        case RenderTreeEditType.SetAttribute:
         //            {
         //                WebViewRenderer.DOMManager.SetAttribute(Sequences.ToArray(), frame.AttributeName, frame.AttributeValue);
         //            }
         //            break;
         //        case RenderTreeEditType.RemoveAttribute:
         //            {
         //                WebViewRenderer.DOMManager.RemoveAttribute(Sequences.ToArray(), frame.AttributeName);
         //            }
         //            break;
         //        case RenderTreeEditType.StepIn:
         //            break;
         //        case RenderTreeEditType.StepOut:
         //            break;
         //        case RenderTreeEditType.PermutationListEntry:
         //        case RenderTreeEditType.PermutationListEnd:
         //        default:
         //            throw new NotImplementedException($"Invalid edit type: {edit.Type}");
         //    }
         //    subtreeIndex++;
         //    if (batch.ReferenceFrames.Array[edit.ReferenceFrameIndex].ElementSubtreeLength > subtreeIndex)
         //        continue;
         //    break;
         //} while (true);
     }
 }
 private int ApplyPrependFrame(RenderBatch batch, int componentId, int siblingIndex, RenderTreeFrame[] frames, int frameIndex)
 {
     ref var frame = ref frames[frameIndex];
        void ProcessTree(RenderTreeEdit edit, RenderBatch batch, int startIndex, int subLength)
        {
            for (int i = 0; i < subLength; i++)
            {
                int currentIndex = startIndex + i;
                var frame        = batch.ReferenceFrames.Array[currentIndex];
                switch (edit.Type)
                {
                case RenderTreeEditType.PrependFrame:
                {
                    switch (frame.FrameType)
                    {
                    case RenderTreeFrameType.Component:
                    {
                        CurrentNode = WebViewRenderer.DOMBuilder.CreateMarkerElement(CurrentNode, frame.Sequence, frame.Component.GetType().Name);
                        //Sequences.Push(frame.Sequence);
                        var childRenderer = new ComponentRenderer(frame.Component, WebViewRenderer, this);
                        WebViewRenderer.Renderers[frame.ComponentId] = childRenderer;
                        //we dont need to process the subtree of components as the Renderer will process it again
                        //ProcessTree(edit, batch, currentIndex + 1, frame.ElementSubtreeLength - 1);
                        i += frame.ComponentSubtreeLength - 1;
                        //Sequences.Pop();
                        CurrentNode = WebViewRenderer.DOMBuilder.Parent(CurrentNode);
                    }
                    break;

                    case RenderTreeFrameType.Element:
                    {
                        CurrentNode = WebViewRenderer.DOMBuilder.CreateElement(CurrentNode, frame.Sequence, frame.ElementName);
                        //Sequences.Push(frame.Sequence);
                        ProcessTree(edit, batch, currentIndex + 1, frame.ElementSubtreeLength - 1);
                        i += frame.ElementSubtreeLength - 1;
                        //Sequences.Pop();
                        CurrentNode = WebViewRenderer.DOMBuilder.Parent(CurrentNode);
                    }
                    break;

                    case RenderTreeFrameType.Attribute:
                    {
                        if (frame.AttributeValue is EventCallback callback)
                        {
                            WebViewRenderer.DOMBuilder.SetEvent(CurrentNode, frame.Sequence, frame.AttributeName, callback, frame.AttributeEventUpdatesAttributeName);
                        }
                        else
                        {
                            WebViewRenderer.DOMBuilder.SetAttribute(CurrentNode, frame.Sequence, frame.AttributeName, frame.AttributeValue);
                        }
                    }
                    break;

                    case RenderTreeFrameType.Text:
                        WebViewRenderer.DOMBuilder.InsertText(CurrentNode, frame.Sequence, frame.TextContent);
                        break;

                    case RenderTreeFrameType.Markup:
                    {
                        WebViewRenderer.DOMBuilder.InsertMarkup(CurrentNode, frame.Sequence, frame.MarkupContent);
                    }
                    break;

                    case RenderTreeFrameType.Region:
                    {
                        CurrentNode = WebViewRenderer.DOMBuilder.CreateMarkerElement(CurrentNode, frame.Sequence, frame.AttributeName);
                        //Sequences.Push(frame.Sequence);
                        ProcessTree(edit, batch, currentIndex + 1, frame.RegionSubtreeLength - 1);
                        i += frame.RegionSubtreeLength - 1;
                        //Sequences.Pop();
                        CurrentNode = WebViewRenderer.DOMBuilder.Parent(CurrentNode);
                    }
                    break;

                    case RenderTreeFrameType.ElementReferenceCapture:
                        ElementReference reference = new ElementReference(CurrentNode.ToString());
                        //WebViewRenderer.DOMBuilder.Reference();
                        frame.ElementReferenceCaptureAction(reference);
                        break;

                    case RenderTreeFrameType.None:
                        break;

                    default:
                        throw new NotImplementedException($"Invalid Frame type: {frame.FrameType}");
                    }
                }
                break;

                case RenderTreeEditType.UpdateText:
                {
                    WebViewRenderer.DOMBuilder.UpdateText(CurrentNode, frame.Sequence, frame.TextContent);
                }
                break;

                case RenderTreeEditType.RemoveFrame:
                {
                    WebViewRenderer.DOMBuilder.RemoveAt(CurrentNode, edit.SiblingIndex);
                }
                break;

                case RenderTreeEditType.UpdateMarkup:
                {
                    WebViewRenderer.DOMBuilder.UpdateMarkup(CurrentNode, frame.Sequence, frame.TextContent);
                }
                break;

                case RenderTreeEditType.SetAttribute:
                {
                    var node = WebViewRenderer.DOMBuilder.Child(CurrentNode, edit.SiblingIndex);
                    if (frame.AttributeValue is EventCallback callback)
                    {
                        WebViewRenderer.DOMBuilder.SetEvent(node, frame.Sequence, frame.AttributeName, callback, frame.AttributeEventUpdatesAttributeName);
                    }
                    else
                    {
                        WebViewRenderer.DOMBuilder.SetAttribute(node, frame.Sequence, frame.AttributeName, frame.AttributeValue);
                    }
                    //WebViewRenderer.DOMManager.SetAttribute(CurrentNode, frame.Sequence, frame.AttributeName, frame.AttributeValue);
                }
                break;

                case RenderTreeEditType.RemoveAttribute:
                {
                    WebViewRenderer.DOMBuilder.RemoveAttribute(CurrentNode, frame.Sequence, frame.AttributeName);
                }
                break;

                case RenderTreeEditType.StepIn:
                    CurrentNode = WebViewRenderer.DOMBuilder.Child(CurrentNode, edit.SiblingIndex);
                    break;

                case RenderTreeEditType.StepOut:
                    CurrentNode = WebViewRenderer.DOMBuilder.Parent(CurrentNode);
                    break;

                case RenderTreeEditType.PermutationListEntry:
                case RenderTreeEditType.PermutationListEnd:
                default:
                    throw new NotImplementedException($"Invalid edit type: {edit.Type}");
                }
            }
        }
 protected override void UpdateDisplay(RenderBatch renderBatch)
 {
     LatestBatchReferenceFrames = renderBatch.ReferenceFrames.ToArray();
 }
Beispiel #27
0
 private int ApplyPrependFrame(RenderBatch batch, int componentId, int siblingIndex, RenderTreeFrame[] frames, int frameIndex, HashSet <int> processedComponentIds)
 {
     ref var frame = ref frames[frameIndex];
Beispiel #28
0
        private void ApplyEdits(RenderBatch batch, ContainerNode parent, int childIndex, ArrayBuilderSegment <RenderTreeEdit> edits)
        {
            var currentDepth             = 0;
            var childIndexAtCurrentDepth = childIndex;
            var permutations             = new List <PermutationListEntry>();

            for (var editIndex = edits.Offset; editIndex < edits.Offset + edits.Count; editIndex++)
            {
                var edit = edits.Array[editIndex];
                switch (edit.Type)
                {
                case RenderTreeEditType.PrependFrame:
                {
                    var frame        = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
                    var siblingIndex = edit.SiblingIndex;
                    InsertFrame(batch, parent, childIndexAtCurrentDepth + siblingIndex, batch.ReferenceFrames.Array, frame, edit.ReferenceFrameIndex);
                    break;
                }

                case RenderTreeEditType.RemoveFrame:
                {
                    var siblingIndex = edit.SiblingIndex;
                    parent.RemoveLogicalChild(childIndexAtCurrentDepth + siblingIndex);
                    break;
                }

                case RenderTreeEditType.SetAttribute:
                {
                    var frame        = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
                    var siblingIndex = edit.SiblingIndex;
                    var node         = parent.Children[childIndexAtCurrentDepth + siblingIndex];
                    if (node is ElementNode element)
                    {
                        ApplyAttribute(batch, element, frame);
                    }
                    else
                    {
                        throw new Exception("Cannot set attribute on non-element child");
                    }
                    break;
                }

                case RenderTreeEditType.RemoveAttribute:
                {
                    // Note that we don't have to dispose the info we track about event handlers here, because the
                    // disposed event handler IDs are delivered separately (in the 'disposedEventHandlerIds' array)
                    var siblingIndex = edit.SiblingIndex;
                    var node         = parent.Children[childIndexAtCurrentDepth + siblingIndex];
                    if (node is ElementNode element)
                    {
                        var attributeName = edit.RemovedAttributeName;

                        // First try to remove any special property we use for this attribute
                        if (!TryApplySpecialProperty(batch, element, attributeName, default))
                        {
                            // If that's not applicable, it's a regular DOM attribute so remove that
                            element.RemoveAttribute(attributeName);
                        }
                    }
                    else
                    {
                        throw new Exception("Cannot remove attribute from non-element child");
                    }
                    break;
                }

                case RenderTreeEditType.UpdateText:
                {
                    var frame        = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
                    var siblingIndex = edit.SiblingIndex;
                    var node         = parent.Children[childIndexAtCurrentDepth + siblingIndex];
                    if (node is TextNode textNode)
                    {
                        textNode.TextContent = frame.TextContent;
                    }
                    else
                    {
                        throw new Exception("Cannot set text content on non-text child");
                    }
                    break;
                }


                case RenderTreeEditType.UpdateMarkup:
                {
                    var frame        = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
                    var siblingIndex = edit.SiblingIndex;
                    parent.RemoveLogicalChild(childIndexAtCurrentDepth + siblingIndex);
                    InsertMarkup(parent, childIndexAtCurrentDepth + siblingIndex, frame);
                    break;
                }

                case RenderTreeEditType.StepIn:
                {
                    var siblingIndex = edit.SiblingIndex;
                    parent = (ContainerNode)parent.Children[childIndexAtCurrentDepth + siblingIndex];
                    currentDepth++;
                    childIndexAtCurrentDepth = 0;
                    break;
                }

                case RenderTreeEditType.StepOut:
                {
                    parent = parent.Parent;
                    currentDepth--;
                    childIndexAtCurrentDepth = currentDepth == 0 ? childIndex : 0;         // The childIndex is only ever nonzero at zero depth
                    break;
                }

                case RenderTreeEditType.PermutationListEntry:
                {
                    permutations.Add(new PermutationListEntry(childIndexAtCurrentDepth + edit.SiblingIndex, childIndexAtCurrentDepth + edit.MoveToSiblingIndex));
                    break;
                }

                case RenderTreeEditType.PermutationListEnd:
                {
                    throw new NotSupportedException();
                    //permuteLogicalChildren(parent, permutations!);
                    //permutations.Clear();
                    //break;
                }

                default:
                {
                    throw new Exception($"Unknown edit type: '{edit.Type}'");
                }
                }
            }
        }
        public static Cnk0 LoadFromStream(string name, string displayName, MemoryStream stream)
        {
            Cnk0         chunk        = new Cnk0();
            BinaryReader binaryReader = new BinaryReader(stream);

            chunk.Name        = name;
            chunk.DisplayName = displayName;
            //Header
            byte[] magic = binaryReader.ReadBytes(4);

            if (magic[0] != 'C' ||
                magic[1] != 'N' ||
                magic[2] != 'K' ||
                magic[3] != '0')
            {
                return(null);
            }

            chunk.Version = binaryReader.ReadUInt32();

            if (!Enum.IsDefined(typeof(ChunkType), (int)chunk.Version))
            {
                Debug.LogWarning("Could not decode chunk " + name + ". Unknown cnk version " + chunk.Version);
                return(null);
            }

            chunk.ChunkType = (ChunkType)chunk.Version;

            chunk.DecompressedSize = binaryReader.ReadUInt32();
            chunk.CompressedSize   = binaryReader.ReadUInt32();

            //Decompression
            byte[] compressedBuffer   = binaryReader.ReadBytes((int)chunk.CompressedSize);
            byte[] decompressedBuffer = new byte[chunk.DecompressedSize];

            InflateReturnCode result = LzhamInterop.DecompressForgelightData(compressedBuffer, chunk.CompressedSize, decompressedBuffer, chunk.DecompressedSize);

            if (result != InflateReturnCode.LZHAM_Z_STREAM_END && result != InflateReturnCode.LZHAM_Z_OK)
            {
                //This chunk is invalid.
                return(null);
            }

            using (MemoryStream decompressedStream = new MemoryStream(decompressedBuffer))
            {
                binaryReader = new BinaryReader(decompressedStream);

                //Tiles
                uint tileCount = binaryReader.ReadUInt32();
                chunk.Tiles = new List <Tile>((int)tileCount);

                for (int i = 0; i < tileCount; i++)
                {
                    Tile tile = new Tile();

                    tile.X           = binaryReader.ReadInt32();
                    tile.Y           = binaryReader.ReadInt32();
                    tile.UnknownInt1 = binaryReader.ReadInt32();
                    tile.UnknownInt2 = binaryReader.ReadInt32();

                    uint ecosCount = binaryReader.ReadUInt32();

                    if (ecosCount > 0)
                    {
                        tile.Ecos = new List <Tile.Eco>((int)ecosCount);

                        for (int j = 0; j < ecosCount; j++)
                        {
                            Tile.Eco eco = new Tile.Eco();

                            eco.ID = binaryReader.ReadUInt32();

                            uint florasCount = binaryReader.ReadUInt32();
                            eco.Floras = new List <Tile.Eco.Flora>((int)florasCount);

                            for (int k = 0; k < florasCount; k++)
                            {
                                Tile.Eco.Flora flora = new Tile.Eco.Flora();

                                uint layersCount = binaryReader.ReadUInt32();
                                flora.Layers = new List <Tile.Eco.Flora.Layer>((int)layersCount);

                                for (int l = 0; l < layersCount; l++)
                                {
                                    Tile.Eco.Flora.Layer layer = new Tile.Eco.Flora.Layer();

                                    layer.UnknownUint1 = binaryReader.ReadUInt32();
                                    layer.UnknownUint2 = binaryReader.ReadUInt32();

                                    flora.Layers.Add(layer);
                                }

                                eco.Floras.Add(flora);
                            }

                            tile.Ecos.Add(eco);
                        }
                    }

                    tile.Index       = binaryReader.ReadUInt32();
                    tile.UnknownInt3 = binaryReader.ReadUInt32();

                    uint imageSize = binaryReader.ReadUInt32();
                    if (imageSize > 0)
                    {
                        tile.ImageData = binaryReader.ReadBytes((int)imageSize).ToList();
                    }

                    uint layerTexturesCount = binaryReader.ReadUInt32();
                    if (layerTexturesCount > 0)
                    {
                        tile.LayerTextures = binaryReader.ReadBytes((int)layerTexturesCount).ToList();
                    }

                    chunk.Tiles.Add(tile);
                }

                //Unknown Data
                chunk.UnknownInt1 = binaryReader.ReadInt32();

                uint unknownCount = binaryReader.ReadUInt32();
                chunk.UnknownArray1 = new List <Unknown1>((int)unknownCount);

                for (int i = 0; i < unknownCount; i++)
                {
                    Unknown1 unknown1 = new Unknown1();

                    unknown1.Height       = binaryReader.ReadInt16();
                    unknown1.UnknownByte1 = binaryReader.ReadByte();
                    unknown1.UnknownByte2 = binaryReader.ReadByte();

                    chunk.UnknownArray1.Add(unknown1);
                }

                //Indices
                uint indexCount = binaryReader.ReadUInt32();
                chunk.Indices = new List <ushort>((int)indexCount);

                for (int i = 0; i < indexCount; i++)
                {
                    chunk.Indices.Add(binaryReader.ReadUInt16());
                }

                //Verts
                uint vertCount = binaryReader.ReadUInt32();
                chunk.Vertices = new List <Vertex>((int)vertCount);

                for (int i = 0; i < vertCount; i++)
                {
                    Vertex vertex = new Vertex();

                    vertex.X          = binaryReader.ReadInt16();
                    vertex.Y          = binaryReader.ReadInt16();
                    vertex.HeightFar  = binaryReader.ReadInt16();
                    vertex.HeightNear = binaryReader.ReadInt16();
                    vertex.Color1     = binaryReader.ReadUInt32();
                    vertex.Color2     = binaryReader.ReadUInt32();

                    chunk.Vertices.Add(vertex);
                }

                //TODO HACK - Daybreak, why are some chunks (that have a version 2 header) actually version 1?
                long offset = binaryReader.BaseStream.Position;
                try
                {
                    //Render Batches
                    uint renderBatchCount = binaryReader.ReadUInt32();
                    chunk.RenderBatches = new List <RenderBatch>((int)renderBatchCount);

                    for (int i = 0; i < renderBatchCount; i++)
                    {
                        RenderBatch renderBatch = new RenderBatch();

                        if (chunk.ChunkType == ChunkType.H1Z1_Planetside2V2)
                        {
                            renderBatch.Unknown = binaryReader.ReadUInt32();
                        }

                        renderBatch.IndexOffset  = binaryReader.ReadUInt32();
                        renderBatch.IndexCount   = binaryReader.ReadUInt32();
                        renderBatch.VertexOffset = binaryReader.ReadUInt32();
                        renderBatch.VertexCount  = binaryReader.ReadUInt32();

                        chunk.RenderBatches.Add(renderBatch);
                    }

                    //Optimized Draw
                    uint optimizedDrawCount = binaryReader.ReadUInt32();
                    chunk.OptimizedDraws = new List <OptimizedDraw>((int)optimizedDrawCount);

                    for (int i = 0; i < optimizedDrawCount; i++)
                    {
                        OptimizedDraw optimizedDraw = new OptimizedDraw();
                        optimizedDraw.Data = binaryReader.ReadBytes(320).ToList();

                        chunk.OptimizedDraws.Add(optimizedDraw);
                    }

                    //Unknown Data
                    uint unknownShort1Count = binaryReader.ReadUInt32();
                    chunk.UnknownShorts1 = new List <ushort>((int)unknownShort1Count);

                    for (int i = 0; i < unknownShort1Count; i++)
                    {
                        chunk.UnknownShorts1.Add(binaryReader.ReadUInt16());
                    }

                    //Unknown Data
                    uint unknownVectors1Count = binaryReader.ReadUInt32();
                    chunk.UnknownVectors1 = new List <Vector3>((int)unknownVectors1Count);

                    for (int i = 0; i < unknownVectors1Count; i++)
                    {
                        chunk.UnknownVectors1.Add(new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()));
                    }

                    //Tile Occluder Info
                    uint tileOccluderCount = binaryReader.ReadUInt32();
                    chunk.TileOccluderInfos = new List <TileOccluderInfo>((int)tileOccluderCount);

                    for (int i = 0; i < tileOccluderCount; i++)
                    {
                        TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                        tileOccluderInfo.Data = binaryReader.ReadBytes(64).ToList();

                        chunk.TileOccluderInfos.Add(tileOccluderInfo);
                    }
                }
                catch (EndOfStreamException)
                {
                    binaryReader.BaseStream.Position = offset;

                    //Render Batches
                    uint renderBatchCount = binaryReader.ReadUInt32();
                    chunk.RenderBatches = new List <RenderBatch>((int)renderBatchCount);

                    for (int i = 0; i < renderBatchCount; i++)
                    {
                        RenderBatch renderBatch = new RenderBatch();

                        renderBatch.IndexOffset  = binaryReader.ReadUInt32();
                        renderBatch.IndexCount   = binaryReader.ReadUInt32();
                        renderBatch.VertexOffset = binaryReader.ReadUInt32();
                        renderBatch.VertexCount  = binaryReader.ReadUInt32();

                        chunk.RenderBatches.Add(renderBatch);
                    }

                    //Optimized Draw
                    uint optimizedDrawCount = binaryReader.ReadUInt32();
                    chunk.OptimizedDraws = new List <OptimizedDraw>((int)optimizedDrawCount);

                    for (int i = 0; i < optimizedDrawCount; i++)
                    {
                        OptimizedDraw optimizedDraw = new OptimizedDraw();
                        optimizedDraw.Data = binaryReader.ReadBytes(320).ToList();

                        chunk.OptimizedDraws.Add(optimizedDraw);
                    }

                    //Unknown Data
                    uint unknownShort1Count = binaryReader.ReadUInt32();
                    chunk.UnknownShorts1 = new List <ushort>((int)unknownShort1Count);

                    for (int i = 0; i < unknownShort1Count; i++)
                    {
                        chunk.UnknownShorts1.Add(binaryReader.ReadUInt16());
                    }

                    //Unknown Data
                    uint unknownVectors1Count = binaryReader.ReadUInt32();
                    chunk.UnknownVectors1 = new List <Vector3>((int)unknownVectors1Count);

                    for (int i = 0; i < unknownVectors1Count; i++)
                    {
                        chunk.UnknownVectors1.Add(new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()));
                    }

                    //Tile Occluder Info
                    uint tileOccluderCount = binaryReader.ReadUInt32();
                    chunk.TileOccluderInfos = new List <TileOccluderInfo>((int)tileOccluderCount);

                    for (int i = 0; i < tileOccluderCount; i++)
                    {
                        TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                        tileOccluderInfo.Data = binaryReader.ReadBytes(64).ToList();

                        chunk.TileOccluderInfos.Add(tileOccluderInfo);
                    }
                }
            }

            return(chunk);
        }
Beispiel #30
0
        public bool Deserialize(BinaryStream stream, AssetManager assetManager)
        {
            // Header
            string magic = stream.ReadString(3);

            Assert.AreEqual(MAGIC, magic, "Chunk header mismatch!");

            int lodLevel = Convert.ToInt32(stream.ReadString(1));

            Assert.AreNotEqual(0, lodLevel, "Use the CNK0 serializer for LOD0 terrain chunks.");

            Version = stream.ReadUInt32();

            if (!Enum.IsDefined(typeof(ChunkType), (int)Version))
            {
                Debug.LogWarning("Could not decode chunk " + Name + ". Unknown cnk version " + Version);
                return(false);
            }

            ChunkType = (ChunkType)Version;

            DecompressedSize = stream.ReadUInt32();
            CompressedSize   = stream.ReadUInt32();

            // Read the compressed buffer.
            stream.ReadBytes(CompressedBuffer, (int)CompressedSize);

            // Decompression
            // Make sure our buffer is large enough.
            DecompressedBuffer.PrepareBuffer((int)DecompressedSize);

            // Perform decompression using Lzham.
            InflateReturnCode result = LzhamInterop.DecompressForgelightData(CompressedBuffer.Data, CompressedSize, DecompressedBuffer.Data, DecompressedSize);

            if (result != InflateReturnCode.LZHAM_Z_STREAM_END && result != InflateReturnCode.LZHAM_Z_OK)
            {
                //This chunk is invalid, or something went wrong.
                return(false);
            }

            using (MemoryStream decompressedStream = new MemoryStream(DecompressedBuffer.Data, 0, (int)DecompressedSize))
            {
                //Textures
                uint textureCount = decompressedStream.ReadUInt32();
                Textures.PrepareBuffer((int)textureCount);

                for (int i = 0; i < textureCount; i++)
                {
                    Texture texture = Textures[i];

                    if (texture == null)
                    {
                        texture     = new Texture();
                        Textures[i] = texture;
                    }

                    uint colorNxMapSize = decompressedStream.ReadUInt32();
                    texture.ColorNXMap = assetManager.CreateAsset <Dds>(decompressedStream.ReadBytes((int)colorNxMapSize));

                    uint specNyMapSize = decompressedStream.ReadUInt32();
                    texture.SpecNyMap = assetManager.CreateAsset <Dds>(decompressedStream.ReadBytes((int)specNyMapSize));

                    uint extraData1Size = decompressedStream.ReadUInt32();
                    decompressedStream.ReadBytes(texture.ExtraData1, (int)extraData1Size);

                    uint extraData2Size = decompressedStream.ReadUInt32();
                    decompressedStream.ReadBytes(texture.ExtraData2, (int)extraData2Size);

                    uint extraData3Size = decompressedStream.ReadUInt32();
                    decompressedStream.ReadBytes(texture.ExtraData3, (int)extraData3Size);

                    uint extraData4Size = decompressedStream.ReadUInt32();
                    decompressedStream.ReadBytes(texture.ExtraData4, (int)extraData4Size);
                }

                //Verts Per Side
                VertsPerSide = decompressedStream.ReadUInt32();

                //Height Maps
                uint heightMapCount = decompressedStream.ReadUInt32();

                int n = (int)(heightMapCount / 4);

                for (int i = 0; i < 4; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        Dictionary <int, HeightMap> entry;

                        if (!HeightMaps.ContainsKey(i))
                        {
                            entry         = new Dictionary <int, HeightMap>();
                            HeightMaps[i] = entry;
                        }

                        else
                        {
                            entry = HeightMaps[i];
                        }

                        HeightMap heightMapData = new HeightMap();
                        heightMapData.Val1 = decompressedStream.ReadInt16();
                        heightMapData.Val2 = decompressedStream.Read1Byte();
                        heightMapData.Val3 = decompressedStream.Read1Byte();

                        entry[j] = heightMapData;
                    }
                }

                //Indices
                uint indexCount = decompressedStream.ReadUInt32();

                for (int i = 0; i < indexCount; i++)
                {
                    Indices.Add(decompressedStream.ReadUInt16());
                }

                //Verts
                uint vertCount = decompressedStream.ReadUInt32();

                for (int i = 0; i < vertCount; i++)
                {
                    Vertex vertex = new Vertex();

                    vertex.X          = decompressedStream.ReadInt16();
                    vertex.Y          = decompressedStream.ReadInt16();
                    vertex.HeightFar  = decompressedStream.ReadInt16();
                    vertex.HeightNear = decompressedStream.ReadInt16();
                    vertex.Color      = decompressedStream.ReadUInt32();

                    Vertices.Add(vertex);
                }

                //TODO HACK - Daybreak, why are some chunks (that have a version 2 header) actually version 1?
                long offset = decompressedStream.Position;
                try
                {
                    //Render Batches
                    uint renderBatchCount = decompressedStream.ReadUInt32();

                    for (int i = 0; i < renderBatchCount; i++)
                    {
                        RenderBatch renderBatch = new RenderBatch();

                        if (ChunkType == ChunkType.H1Z1_Planetside2V2)
                        {
                            renderBatch.Unknown = decompressedStream.ReadUInt32();
                        }

                        renderBatch.IndexOffset  = decompressedStream.ReadUInt32();
                        renderBatch.IndexCount   = decompressedStream.ReadUInt32();
                        renderBatch.VertexOffset = decompressedStream.ReadUInt32();
                        renderBatch.VertexCount  = decompressedStream.ReadUInt32();

                        RenderBatches.Add(renderBatch);
                    }

                    //Optimized Draw
                    uint optimizedDrawCount = decompressedStream.ReadUInt32();

                    for (int i = 0; i < optimizedDrawCount; i++)
                    {
                        OptimizedDraw optimizedDraw = new OptimizedDraw();
                        optimizedDraw.Data = decompressedStream.ReadBytes(320).ToList();

                        OptimizedDraws.Add(optimizedDraw);
                    }

                    //Unknown Data
                    uint unknownShort1Count = decompressedStream.ReadUInt32();

                    for (int i = 0; i < unknownShort1Count; i++)
                    {
                        UnknownShorts1.Add(decompressedStream.ReadUInt16());
                    }

                    //Unknown Data
                    uint unknownVectors1Count = decompressedStream.ReadUInt32();

                    for (int i = 0; i < unknownVectors1Count; i++)
                    {
                        UnknownVectors1.Add(new Vector3(decompressedStream.ReadSingle(), decompressedStream.ReadSingle(),
                                                        decompressedStream.ReadSingle()));
                    }

                    //Tile Occluder Info
                    uint tileOccluderCount = decompressedStream.ReadUInt32();

                    if (tileOccluderCount > 16)
                    {
                        throw new ArgumentOutOfRangeException();
                    }

                    for (int i = 0; i < tileOccluderCount; i++)
                    {
                        TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                        tileOccluderInfo.Data = decompressedStream.ReadBytes(64).ToList();

                        TileOccluderInfos.Add(tileOccluderInfo);
                    }
                }
                catch (Exception)
                {
                    // Some of these may have been populated from the "try".
                    RenderBatches.Clear();
                    OptimizedDraws.Clear();
                    UnknownShorts1.Clear();
                    UnknownVectors1.Clear();
                    TileOccluderInfos.Clear();

                    decompressedStream.Position = offset;

                    //Render Batches
                    uint renderBatchCount = decompressedStream.ReadUInt32();

                    for (int i = 0; i < renderBatchCount; i++)
                    {
                        RenderBatch renderBatch = new RenderBatch();

                        renderBatch.IndexOffset  = decompressedStream.ReadUInt32();
                        renderBatch.IndexCount   = decompressedStream.ReadUInt32();
                        renderBatch.VertexOffset = decompressedStream.ReadUInt32();
                        renderBatch.VertexCount  = decompressedStream.ReadUInt32();

                        RenderBatches.Add(renderBatch);
                    }

                    //Optimized Draw
                    uint optimizedDrawCount = decompressedStream.ReadUInt32();

                    for (int i = 0; i < optimizedDrawCount; i++)
                    {
                        OptimizedDraw optimizedDraw = new OptimizedDraw();
                        optimizedDraw.Data = decompressedStream.ReadBytes(320).ToList();

                        OptimizedDraws.Add(optimizedDraw);
                    }

                    //Unknown Data
                    uint unknownShort1Count = decompressedStream.ReadUInt32();

                    for (int i = 0; i < unknownShort1Count; i++)
                    {
                        UnknownShorts1.Add(decompressedStream.ReadUInt16());
                    }

                    //Unknown Data
                    uint unknownVectors1Count = decompressedStream.ReadUInt32();

                    for (int i = 0; i < unknownVectors1Count; i++)
                    {
                        UnknownVectors1.Add(new Vector3(decompressedStream.ReadSingle(), decompressedStream.ReadSingle(),
                                                        decompressedStream.ReadSingle()));
                    }

                    //Tile Occluder Info
                    uint tileOccluderCount = decompressedStream.ReadUInt32();

                    if (tileOccluderCount > 16)
                    {
                        return(false);
                    }

                    for (int i = 0; i < tileOccluderCount; i++)
                    {
                        TileOccluderInfo tileOccluderInfo = new TileOccluderInfo();
                        tileOccluderInfo.Data = decompressedStream.ReadBytes(64).ToList();

                        TileOccluderInfos.Add(tileOccluderInfo);
                    }
                }
            }

            return(true);
        }
Beispiel #31
0
        public static LoadError LoadFromStream(Stream stream, out Cnk0 cnk0)
        {
            if (stream == null)
            {
                cnk0 = null;
                return(LoadError.NullStream);
            }

            BinaryReader binaryReader = new BinaryReader(stream);

            //header
            char[] magic = binaryReader.ReadChars(4);

            if (magic[0] != 'C' ||
                magic[1] != 'N' ||
                magic[2] != 'K' ||
                magic[3] != '0')
            {
                cnk0 = null;
                return(LoadError.BadHeader);
            }

            int version = binaryReader.ReadInt32();

            if (version != VERSION)
            {
                cnk0 = null;
                return(LoadError.VersionMismatch);
            }

            uint uncompressedSize = binaryReader.ReadUInt32();
            uint compressedSize   = binaryReader.ReadUInt32();

            byte[] inputBuffer = binaryReader.ReadBytes((int)compressedSize);

            binaryReader.Close();

            byte[] outputBuffer = new byte[uncompressedSize];

            Lzham.ZStream zStream = new Lzham.ZStream();
            Lzham.ZInflateInit2(zStream, 20);
            zStream.AvailableInputBytes  = compressedSize;
            zStream.AvailableOutputBytes = uncompressedSize;

            GCHandle inputBufferGCHandle  = GCHandle.Alloc(inputBuffer, GCHandleType.Pinned);
            GCHandle outputBufferGCHandle = GCHandle.Alloc(outputBuffer, GCHandleType.Pinned);

            zStream.NextInputByte  = inputBufferGCHandle.AddrOfPinnedObject();
            zStream.NextOutputByte = outputBufferGCHandle.AddrOfPinnedObject();

            Lzham.ZInflate(zStream, (int)Lzham.ZFlush.Finish);
            Lzham.ZInflateEnd(zStream);

            inputBufferGCHandle.Free();
            outputBufferGCHandle.Free();

            MemoryStream memoryStream = new MemoryStream(outputBuffer);

            binaryReader = new BinaryReader(memoryStream);

            cnk0 = new Cnk0();

            //tiles
            uint tileCount = binaryReader.ReadUInt32();

            cnk0.Tiles = new Tile[tileCount];

            for (uint i = 0; i < tileCount; ++i)
            {
                Tile tile;

                if (Tile.LoadFromStream(memoryStream, out tile) != Tile.LoadError.None)
                {
                    cnk0 = null;
                    return(LoadError.BadTile);
                }

                cnk0.Tiles[i] = tile;
            }

            //unknown block
            uint unknown0 = binaryReader.ReadUInt32();
            uint unknown1 = binaryReader.ReadUInt32();

            binaryReader.BaseStream.Seek(unknown1 * 4, SeekOrigin.Current);

            //indices
            uint indexCount = binaryReader.ReadUInt32();

            cnk0.Indices = new ushort[indexCount];

            for (int i = 0; i < indexCount; ++i)
            {
                cnk0.Indices[i] = binaryReader.ReadUInt16();
            }

            //vertices
            uint vertexCount = binaryReader.ReadUInt32();

            cnk0.Vertices = new Vertex[vertexCount];

            for (int i = 0; i < vertexCount; ++i)
            {
                Vertex vertex;

                if (Vertex.LoadFromStream(binaryReader.BaseStream, out vertex) != Vertex.LoadError.None)
                {
                    cnk0 = null;
                    return(LoadError.BadVertex);
                }

                cnk0.Vertices[i] = vertex;
            }

            //render batches
            uint renderBatchCount = binaryReader.ReadUInt32();

            cnk0.RenderBatches = new RenderBatch[renderBatchCount];

            for (uint i = 0; i < renderBatchCount; ++i)
            {
                RenderBatch renderBatch;
                if (RenderBatch.LoadFromStream(binaryReader.BaseStream, out renderBatch) != RenderBatch.LoadError.None)
                {
                    cnk0 = null;
                    return(LoadError.BadRenderBatch);
                }

                cnk0.RenderBatches[i] = renderBatch;
            }

            binaryReader.Close();

            return(LoadError.None);
        }
 internal protected override void UpdateDisplay(RenderBatch renderBatch)
 {
 }
Beispiel #33
0
        public static Terrain LoadADT(string filename, CacheStorage cache, int shaderProgram)
        {
            WoWFormatLib.Structs.ADT.ADT adt = new WoWFormatLib.Structs.ADT.ADT();

            Terrain result = new Terrain();

            //Load ADT from file
            if (WoWFormatLib.Utils.CASC.cascHandler.FileExists(filename))
            {
                var adtreader = new ADTReader();
                adtreader.LoadADT(filename);
                adt = adtreader.adtfile;
            }
            else
            {
                throw new Exception("ADT " + filename + " does not exist!");
            }

            float TileSize    = 1600.0f / 3.0f;   //533.333
            float ChunkSize   = TileSize / 16.0f; //33.333
            float UnitSize    = ChunkSize / 8.0f; //4.166666
            float MapMidPoint = 32.0f / ChunkSize;

            List <Vertex> verticelist = new List <Vertex>();
            List <Int32>  indicelist  = new List <Int32>();

            result.vao = GL.GenVertexArray();
            GL.BindVertexArray(result.vao);

            result.vertexBuffer = GL.GenBuffer();
            result.indiceBuffer = GL.GenBuffer();

            List <Material> materials = new List <Material>();

            for (int ti = 0; ti < adt.textures.filenames.Count(); ti++)
            {
                Material material = new Material();
                material.filename  = adt.textures.filenames[ti];
                material.textureID = BLPLoader.LoadTexture(adt.textures.filenames[ti], cache);

                if (adt.texParams != null && adt.texParams.Count() >= ti)
                {
                    material.scale = (float)Math.Pow(2, (adt.texParams[ti].flags & 0xF0) >> 4);
                    if (adt.texParams[ti].height != 0.0 || adt.texParams[ti].offset != 1.0)
                    {
                        material.heightScale  = adt.texParams[ti].height;
                        material.heightOffset = adt.texParams[ti].offset;

                        var heightName = adt.textures.filenames[ti].Replace(".blp", "_h.blp");
                        if (!WoWFormatLib.Utils.CASC.cascHandler.FileExists(heightName))
                        {
                            Console.WriteLine("Height texture: " + heightName + " does not exist! Falling back to original texture (hack)..");
                            material.heightTexture = BLPLoader.LoadTexture(adt.textures.filenames[ti], cache);
                        }
                        else
                        {
                            material.heightTexture = BLPLoader.LoadTexture(heightName, cache);
                        }
                    }
                    else
                    {
                        material.heightScale  = 0.0f;
                        material.heightOffset = 1.0f;
                    }
                }
                else
                {
                    material.heightScale  = 0.0f;
                    material.heightOffset = 1.0f;
                    material.scale        = 1.0f;
                }
                materials.Add(material);
            }

            var initialChunkY = adt.chunks[0].header.position.Y;
            var initialChunkX = adt.chunks[0].header.position.X;

            List <RenderBatch> renderBatches = new List <RenderBatch>();

            for (uint c = 0; c < adt.chunks.Count(); c++)
            {
                var chunk = adt.chunks[c];

                int off = verticelist.Count();

                RenderBatch batch = new RenderBatch();

                batch.groupID = c;

                for (int i = 0, idx = 0; i < 17; i++)
                {
                    for (int j = 0; j < (((i % 2) != 0) ? 8 : 9); j++)
                    {
                        Vertex v = new Vertex();
                        v.Normal = new Vector3(chunk.normals.normal_0[idx], chunk.normals.normal_1[idx], chunk.normals.normal_2[idx]);
                        if (chunk.vertexShading.red != null)
                        {
                            v.Color = new Vector4(chunk.vertexShading.blue[idx] / 255.0f, chunk.vertexShading.green[idx] / 255.0f, chunk.vertexShading.red[idx] / 255.0f, chunk.vertexShading.alpha[idx] / 255.0f);
                        }
                        else
                        {
                            v.Color = new Vector4(0.5f, 0.5f, 0.5f, 1.0f);
                        }

                        v.TexCoord = new Vector2((j + (((i % 2) != 0) ? 0.5f : 0f)) / 8f, (i * 0.5f) / 8f);

                        v.Position = new Vector3(chunk.header.position.X - (i * UnitSize * 0.5f), chunk.header.position.Y - (j * UnitSize), chunk.vertices.vertices[idx++] + chunk.header.position.Z);

                        if ((i % 2) != 0)
                        {
                            v.Position.Y -= 0.5f * UnitSize;
                        }

                        verticelist.Add(v);
                    }
                }

                result.startPos = verticelist[0];

                batch.firstFace = (uint)indicelist.Count();
                for (int j = 9; j < 145; j++)
                {
                    indicelist.AddRange(new Int32[] { off + j + 8, off + j - 9, off + j });
                    indicelist.AddRange(new Int32[] { off + j - 9, off + j - 8, off + j });
                    indicelist.AddRange(new Int32[] { off + j - 8, off + j + 9, off + j });
                    indicelist.AddRange(new Int32[] { off + j + 9, off + j + 8, off + j });
                    if ((j + 1) % (9 + 8) == 0)
                    {
                        j += 9;
                    }
                }
                batch.numFaces = (uint)(indicelist.Count()) - batch.firstFace;

                var layermats      = new List <uint>();
                var alphalayermats = new List <int>();
                var layerscales    = new List <float>();
                var layerheights   = new List <int>();

                batch.heightScales  = new Vector4();
                batch.heightOffsets = new Vector4();

                for (int li = 0; li < adt.texChunks[c].layers.Count(); li++)
                {
                    if (adt.texChunks[c].alphaLayer != null)
                    {
                        alphalayermats.Add(BLPLoader.GenerateAlphaTexture(adt.texChunks[c].alphaLayer[li].layer));
                    }
                    layermats.Add((uint)cache.materials[adt.textures.filenames[adt.texChunks[c].layers[li].textureId].ToLower()]);

                    var curMat = materials.Where(material => material.filename == adt.textures.filenames[adt.texChunks[c].layers[li].textureId]).Single();

                    layerscales.Add(curMat.scale);
                    layerheights.Add(curMat.heightTexture);

                    batch.heightScales[li]  = curMat.heightScale;
                    batch.heightOffsets[li] = curMat.heightOffset;
                }

                batch.materialID        = layermats.ToArray();
                batch.alphaMaterialID   = alphalayermats.ToArray();
                batch.scales            = layerscales.ToArray();
                batch.heightMaterialIDs = layerheights.ToArray();

                int[]    indices  = indicelist.ToArray();
                Vertex[] vertices = verticelist.ToArray();

                GL.BindBuffer(BufferTarget.ArrayBuffer, result.vertexBuffer);
                GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Count() * 12 * sizeof(float)), vertices, BufferUsageHint.StaticDraw);

                //var normalAttrib = GL.GetAttribLocation(shaderProgram, "normal");
                //GL.EnableVertexAttribArray(normalAttrib);
                //GL.VertexAttribPointer(normalAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 11, sizeof(float) * 0);

                var colorAttrib = GL.GetAttribLocation(shaderProgram, "color");
                GL.EnableVertexAttribArray(colorAttrib);
                GL.VertexAttribPointer(colorAttrib, 4, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 3);

                var texCoordAttrib = GL.GetAttribLocation(shaderProgram, "texCoord");
                GL.EnableVertexAttribArray(texCoordAttrib);
                GL.VertexAttribPointer(texCoordAttrib, 2, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 7);

                var posAttrib = GL.GetAttribLocation(shaderProgram, "position");
                GL.EnableVertexAttribArray(posAttrib);
                GL.VertexAttribPointer(posAttrib, 3, VertexAttribPointerType.Float, false, sizeof(float) * 12, sizeof(float) * 9);

                GL.BindBuffer(BufferTarget.ElementArrayBuffer, result.indiceBuffer);
                GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Length * sizeof(int)), indices, BufferUsageHint.StaticDraw);

                renderBatches.Add(batch);
            }

            result.renderBatches = renderBatches.ToArray();
            //result.doodads = doodads.ToArray();
            //result.worldModelBatches = worldModelBatches.ToArray();

            cache.terrain.Add(filename, result);
            return(result);
        }