Ejemplo n.º 1
0
        public static void Draw(
            RenderTarget2D finalRenderTarget,
            Color?clearColor,
            MeshBatch batch,
            Material material)
        {
            var graphicsDevice = Core.Instance.GraphicsDevice;

            graphicsDevice.SetRenderTarget(finalRenderTarget);
            if (clearColor != null)
            {
                graphicsDevice.Clear(clearColor.Value);
            }

            // material?.OnPreRender();
#if SPRITE_BATCH
            SpriteBatch.Begin(
                SpriteSortMode.Deferred,
                material?.BlendState ?? BlendState.AlphaBlend,
                material?.SamplerState ?? Graphic.DefaultSamplerState,
                material?.DepthStencilState ?? DepthStencilState.None,
                RasterizerState.CullNone,
                material?.Effect);
#else
            graphicsDevice.BlendState        = material?.BlendState ?? BlendState.Opaque;
            graphicsDevice.SamplerStates[0]  = material?.SamplerState ?? DefaultSamplerState;
            graphicsDevice.DepthStencilState = material?.DepthStencilState ?? DepthStencilState.None;

            var orthographic = Matrix.CreateOrthographicOffCenter(
                0,
                graphicsDevice.Viewport.Width,
                graphicsDevice.Viewport.Height,
                0,
                0,
                -1);

            SpriteEffect.SetMatrixTransform(ref orthographic);
#endif

            foreach (var mesh in batch.Meshes)
            {
#if SPRITE_BATCH
#else
                SpriteEffect.CurrentTechnique.Passes[0].Apply();

                if (material?.Effect != null)
                {
                    foreach (var pass in material.Effect.CurrentTechnique.Passes)
                    {
                        pass.Apply();
                    }
                }
#endif
                mesh.Draw(SpriteBatch);
            }
#if SPRITE_BATCH
            SpriteBatch.End();
#else
#endif
        }
        private void BuildStaticMeshBatch()
        {
            if (GeometryState == EStateType.Dynamic)
            {
                return;
            }

            if (StaticMesh != null)
            {
                MeshBatchCacheID = new int[StaticMesh.subMeshCount];

                for (int Index = 0; Index < StaticMesh.subMeshCount; Index++)
                {
                    FMeshBatch MeshBatch;
                    MeshBatch.Visible             = Visible;
                    MeshBatch.BoundBox            = BoundBox;
                    MeshBatch.CastShadow          = (int)CastShadow;
                    MeshBatch.MotionType          = (int)MotionVector;
                    MeshBatch.RenderLayer         = RenderLayer;
                    MeshBatch.SubmeshIndex        = Index;
                    MeshBatch.Mesh                = GetWorld().WorldMeshList.Add(StaticMesh);
                    MeshBatch.Material            = GetWorld().WorldMaterialList.Add(Materials[Index]);
                    MeshBatch.Priority            = RenderPriority + Materials[Index].renderQueue;
                    MeshBatch.Matrix_LocalToWorld = Matrix_LocalToWorld;
                    //MeshBatch.CustomPrimitiveData = new float4x4(GetCustomPrimitiveData(0), GetCustomPrimitiveData(4), GetCustomPrimitiveData(8), GetCustomPrimitiveData(12));

                    MeshBatchCacheID[Index] = MeshBatch.GetHashCode(this.GetInstanceID() + this.transform.GetHashCode() + this.gameObject.name.GetHashCode());
                    GetWorld().GetMeshBatchColloctor().AddStaticMeshBatch(MeshBatch, MeshBatchCacheID[Index]);
                }
            }
        }
Ejemplo n.º 3
0
        public void DrawInto(float width, float height, Color color, float depth, MeshBatch target)
        {
            var destination = new RectangleF(0, 0, width, height);

            destination.Location -= this.Origin;
            target.Draw(Graphic.PixelTexture, destination, Graphic.PixelTexture.Bounds, this.Color ?? color, depth);
        }
Ejemplo n.º 4
0
        public override void Render(MeshBatch meshBatch, Matrix transform)
        {
            meshBatch.Draw(model, transform);
            return;

            for (int i = 0; i < model.Meshes.Count; i++)
            {
                for (int j = 0; j < model.Meshes[i].MeshParts.Count; j++)
                {
                    ModelMeshPart mp = model.Meshes[i].MeshParts[j];

                    if (mp.PrimitiveCount > 0)
                    {
                        Effect effect = model.Meshes[i].Effects[j];
                        effect.SetWorldAndInvTransp(model.Meshes[i].ParentBone.Transform * transform);

                        DrawM.gDevice.SetVertexBuffer(mp.VertexBuffer);
                        DrawM.gDevice.Indices = mp.IndexBuffer;


                        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                        {
                            pass.Apply();
                            //if the error appears here export with "Std" settings
                            DrawM.gDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
                                                                mp.VertexOffset,
                                                                mp.StartIndex,
                                                                mp.PrimitiveCount);
                        }
                    }
                }
            }
        }
Ejemplo n.º 5
0
 public override void Render(MeshBatch meshBatch, Matrix transform)
 {
     for (int i = 0; i < meshes.Count; i++)
     {
         meshes[i].Render(meshBatch, transform);
     }
 }
Ejemplo n.º 6
0
 public override void Render(MeshBatch meshBatch, Vector3 pos)
 {
     for (int i = 0; i < meshes.Count; i++)
     {
         meshes[i].Render(meshBatch, pos);
     }
 }
Ejemplo n.º 7
0
        public static Mesh GenerateMesh()
        {
            Vector3[] meshVerts =
            {
                new Vector3(-.5f, -.5f, -.5f),
                new Vector3(.5f,  -.5f, -.5f),
                new Vector3(.5f,   .5f, -.5f),
                new Vector3(-.5f,  .5f, -.5f),
                new Vector3(-.5f, -.5f,  .5f),
                new Vector3(.5f,  -.5f,  .5f),
                new Vector3(.5f,   .5f,  .5f),
                new Vector3(-.5f,  .5f,  .5f),
            };

            Color[] meshColors =
            {
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f)
            };

            int[] meshIndexes =
            {
                //front
                0, 3, 7,
                0, 7, 4,
                //back
                1, 6, 2,
                6, 1, 5,
                //left
                0, 1, 2,
                0, 2, 3,
                //right
                4, 6, 5,
                6, 4, 7,
                //top
                2, 6, 3,
                6, 7, 3,
                //bottom
                0, 5, 1,
                0, 4, 5
            };


            Mesh      newMesh   = new Mesh();
            MeshBatch meshBatch = new MeshBatch();

            meshBatch.Vertices = meshVerts;
            meshBatch.Indexes  = meshIndexes;
            meshBatch.Color0   = meshColors;
            newMesh.SubMeshes.Add(meshBatch);

            return(newMesh);
        }
Ejemplo n.º 8
0
        public static Mesh GenerateMesh()
        {
            Vector3[] meshVerts =
            {
                new Vector3(-.5f, -.5f, -.5f), // Bot - Back Left
                new Vector3(.5f,  -.5f, -.5f), // Bot - Back Right
                new Vector3(.5f,   .5f, -.5f), // Top - Back Right
                new Vector3(-.5f,  .5f, -.5f), // Top - Back Left
                new Vector3(-.5f, -.5f, .5f),  // Bot - Front Left
                new Vector3(.5f,  -.5f, .5f),  // Bot - Front Right
                new Vector3(.5f,   .5f, .5f),  // Top - Front Right
                new Vector3(-.5f,  .5f, .5f),  // Top - Front left
            };

            Color[] meshColors =
            {
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f)
            };

            int[] meshIndexes =
            {
                // Top
                3, 2,
                2, 6,
                6, 7,
                7, 3,

                // Bottom
                0, 1,
                1, 5,
                5, 4,
                4, 0,

                // Supports
                0, 3,
                1, 2,
                5, 6,
                4, 7
            };


            Mesh      newMesh   = new Mesh();
            MeshBatch meshBatch = new MeshBatch();

            meshBatch.Vertices     = meshVerts;
            meshBatch.Indexes      = meshIndexes;
            meshBatch.PrimitveType = OpenTK.Graphics.OpenGL.PrimitiveType.Lines;
            meshBatch.Color0       = meshColors;
            newMesh.SubMeshes.Add(meshBatch);

            return(newMesh);
        }
Ejemplo n.º 9
0
        public static Mesh GenerateMesh()
        {
            Vector3[] meshVerts =
            {
                new Vector3(-.5f, -.5f,  -.5f), // Bot - Back Left
                new Vector3(.5f, -.5f,  -.5f), // Bot - Back Right
                new Vector3(.5f, .5f,  -.5f),  // Top - Back Right
                new Vector3(-.5f, .5f,  -.5f), // Top - Back Left
                new Vector3(-.5f, -.5f,  .5f), // Bot - Front Left
                new Vector3(.5f, -.5f,  .5f), // Bot - Front Right
                new Vector3(.5f, .5f,  .5f), // Top - Front Right
                new Vector3(-.5f, .5f,  .5f), // Top - Front left
            };

            Color[] meshColors =
            {
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f)
            };

            int[] meshIndexes =
            {
                // Top
                3, 2,
                2, 6,
                6, 7,
                7, 3,

                // Bottom
                0, 1,
                1, 5,
                5, 4,
                4, 0,

                // Supports
                0, 3,
                1, 2,
                5, 6,
                4, 7
            };

            Mesh newMesh = new Mesh();
            MeshBatch meshBatch = new MeshBatch();
            meshBatch.Vertices = meshVerts;
            meshBatch.Indexes = meshIndexes;
            meshBatch.PrimitveType = OpenTK.Graphics.OpenGL.PrimitiveType.Lines;
            meshBatch.Color0 = meshColors;
            newMesh.SubMeshes.Add(meshBatch);

            return newMesh;
        }
Ejemplo n.º 10
0
        public static Mesh GenerateMesh()
        {
            Vector3[] meshVerts =
            {
                new Vector3(-.5f, -.5f,  -.5f),
                new Vector3(.5f, -.5f,  -.5f),
                new Vector3(.5f, .5f,  -.5f),
                new Vector3(-.5f, .5f,  -.5f),
                new Vector3(-.5f, -.5f,  .5f),
                new Vector3(.5f, -.5f,  .5f),
                new Vector3(.5f, .5f,  .5f),
                new Vector3(-.5f, .5f,  .5f),
            };

            Color[] meshColors =
            {
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f),
                new Color(1f, 1f, 1f, 1f)
            };

            int[] meshIndexes =
            {
                //front
                0, 3, 7,
                0, 7, 4,
                //back
                1, 6, 2,
                6, 1, 5,
                //left
                0, 1, 2,
                0, 2, 3,
                //right
                4, 6, 5,
                6, 4, 7,
                //top
                2, 6, 3,
                6, 7, 3,
                //bottom
                0, 5, 1,
                0, 4, 5
            };

            Mesh newMesh = new Mesh();
            MeshBatch meshBatch = new MeshBatch();
            meshBatch.Vertices = meshVerts;
            meshBatch.Indexes = meshIndexes;
            meshBatch.Color0 = meshColors;
            newMesh.SubMeshes.Add(meshBatch);

            return newMesh;
        }
Ejemplo n.º 11
0
 /// <summary>
 /// Disposes all batches (including those in the reusable pool).
 /// </summary>
 public void Dispose()
 {
     foreach (MeshBatch batch in _batches)
     {
         batch.Dispose();
     }
     _batches.Clear();
     _batchPool.Purge();
     _currentBatch   = null;
     OnBatchComplete = null;
 }
Ejemplo n.º 12
0
        /// <summary>
        /// Finishes the current batch, i.e. call the 'onComplete' callback on the batch and
        /// prepares initialization of a new one.
        /// </summary>
        public void FinishBatch()
        {
            MeshBatch meshBatch = _currentBatch;

            if (meshBatch != null)
            {
                _currentBatch     = null;
                _currentStyleType = null;

                OnBatchComplete?.Invoke(meshBatch);
            }
        }
Ejemplo n.º 13
0
        private void DrawBatch(MeshBatch meshBatch)
        {
            PushState();

            State.BlendMode = meshBatch.BlendMode;
            State.ModelviewMatrix.Identity();
            State.Alpha = 1.0f;

            meshBatch.Render(this);

            PopState();
        }
Ejemplo n.º 14
0
        public void Put(MeshBatch meshBatch)
        {
            Type             styleType = meshBatch.Style.Type;
            List <MeshBatch> batchList = _batchLists[styleType];

            if (batchList == null)
            {
                batchList = new List <MeshBatch>();
                _batchLists[styleType] = batchList;
            }

            meshBatch.Clear();
            batchList.Add(meshBatch);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Clears all batches and adds them to a pool so they can be reused later.
        /// </summary>
        public void Clear()
        {
            int numBatches = _batches.Count;

            for (int i = 0; i < numBatches; ++i)
            {
                _batchPool.Put(_batches[i]);
            }

            _batches.Clear();
            _currentBatch     = null;
            _currentStyleType = null;
            _cacheToken.Reset();
        }
Ejemplo n.º 16
0
        public override void Render(MeshBatch meshBatch, Matrix transform)//TODO: implement meshBatch
        {
            Matrix newWorld = world;

            //newWorld  *= Matrix.CreateRotationX(-MathHelper.PiOver2) * Matrix.CreateRotationY(-MathHelper.PiOver2);
            newWorld *= transform;

            effect.SetWorldAndInvTransp(newWorld);

            if (diffuseMapIntensity != 0)
            {
                effect.Parameters["Texture"].SetValue(diffuseMap);
            }
            if (normalMapIntensity != 0)
            {
                effect.Parameters["NormalMap"].SetValue(normalMap);
            }
            if (specularMapIntensity != 0)
            {
                effect.Parameters["SpecularMap"].SetValue(specularMap);
            }
            if (glossMapIntensity != 0)
            {
                effect.Parameters["GlossMap"].SetValue(glossMap);
            }

            effect.Parameters["useMipMap"].SetValue(mipMap);
            effect.Parameters["diffuseMapIntensity"].SetValue(diffuseMapIntensity);
            effect.Parameters["normalMapIntensity"].SetValue(normalMapIntensity);
            effect.Parameters["specularMapIntensity"].SetValue(specularMapIntensity);
            effect.Parameters["glossMapIntensity"].SetValue(glossMapIntensity);
            effect.Parameters["specularBaseIntensity"].SetValue(specularBaseIntensity);
            effect.Parameters["glossBaseIntensity"].SetValue(glossBaseIntensity);

            DrawM.gDevice.SetVertexBuffer(vertexBuffer);
            DrawM.gDevice.Indices = indexBuffer;

            //effect.Parameters["WorldInverseTranspose"].SetValue(Matrix.Transpose(Matrix.Invert(mpEffect.World)));
            //effect.Parameters["WorldViewProjection"].SetValue(mpEffect.World * Game1.camera.view * Game1.camera.projection);

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();

                DrawM.gDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
                                                    0,
                                                    0,
                                                    vertexBuffer.VertexCount / 3);
            }
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Adds a mesh to the current batch, or to a new one if the current one does not support
        /// it. Whenever the batch changes, <code>onBatchComplete</code> is called for the previous
        /// one.
        /// </summary>
        /// <param name="mesh">The mesh to add to the current(or new) batch.</param>
        /// <param name="state">The render state from which to take the current settings for alpha,
        ///                    modelview matrix, and blend mode.</param>
        /// <param name="subset">The subset of the mesh you want to add, or<code>null</code> for
        ///                    the complete mesh.</param>
        /// <param name="ignoreTransformations">When enabled, the mesh's vertices will be added
        ///                    without transforming them in any way (no matter the value of the
        ///                    state's <code>modelviewMatrix</code></param>
        public void AddMesh(Mesh mesh, RenderState state, MeshSubset subset = null,
                            bool ignoreTransformations = false)
        {
            if (subset == null)
            {
                subset             = SMeshSubset;
                subset.VertexId    = subset.IndexId = 0;
                subset.NumVertices = mesh.NumVertices;
                subset.NumIndices  = mesh.NumIndices;
            }
            else
            {
                if (subset.NumVertices < 0)
                {
                    subset.NumVertices = mesh.NumVertices - subset.VertexId;
                }
                if (subset.NumIndices < 0)
                {
                    subset.NumIndices = mesh.NumIndices - subset.IndexId;
                }
            }

            if (subset.NumVertices > 0)
            {
                if (_currentBatch == null || !_currentBatch.CanAddMesh(mesh, subset.NumVertices))
                {
                    FinishBatch();

                    _currentStyleType       = mesh.Style.Type;
                    _currentBatch           = _batchPool.GetBatch(_currentStyleType);
                    _currentBatch.BlendMode = state != null ? state.BlendMode : mesh.BlendMode;
                    _cacheToken.SetTo(_batches.Count);
                    _batches.Add(_currentBatch);
                }

                Matrix2D matrix = state != null ? state._modelviewMatrix : null;
                float    alpha  = state != null ? state.Alpha : 1.0f;

                _currentBatch.AddMesh(mesh, matrix, alpha, subset, ignoreTransformations);
                _cacheToken.VertexID += subset.NumVertices;
                _cacheToken.IndexID  += subset.NumIndices;
            }
        }
Ejemplo n.º 18
0
        public TextField(float width, float height, string text = "", TextFormat format = null)
        {
            _text    = text != null ? text : "";
            _hitArea = Rectangle.Create(0, 0, width, height);
            _requiresRecomposition = true;
            _compositor            = DefaultCompositor;
            _options = new TextOptions();

            _format = format != null?format.Clone() : new TextFormat();

            _format.ChangeEvent += SetRequiresRecomposition;

            _meshBatch               = new MeshBatch();
            _meshBatch.Touchable     = false;
            _meshBatch.PixelSnapping = true;
            AddChild(_meshBatch);

            SparrowSharp.ContextCreated += SetRequiresRecomposition;
        }
Ejemplo n.º 19
0
        /** Draws text into a QuadBatch. */
        public void FillMeshBatch(MeshBatch meshBatch, float width, float height, string text,
                                  TextFormat format, TextOptions options = null)
        {
            List <CharLocation> charLocations = ArrangeChars(
                width, height, text, format, options);
            int numChars = charLocations.Count;

            _helperImage.Color = format.Color;

            for (int i = 0; i < numChars; ++i)
            {
                CharLocation charLocation = charLocations[i];
                _helperImage.Texture = charLocation.Char.Texture;
                _helperImage.ReadjustSize();
                _helperImage.X     = charLocation.X;
                _helperImage.Y     = charLocation.Y;
                _helperImage.Scale = charLocation.Scale;
                meshBatch.AddMesh(_helperImage);
            }
        }
Ejemplo n.º 20
0
 public override void Render(MeshBatch meshBatch, Matrix transform)
 {
     model.Render(meshBatch, transform);
 }
Ejemplo n.º 21
0
 public override void Render(MeshBatch meshBatch, Vector3 pos)
 {
     Render(meshBatch, Matrix.CreateTranslation(pos));
 }
Ejemplo n.º 22
0
        public override void DrawInto(float width, float height, Color color, float depth, MeshBatch target)
        {
            var source      = this.SourceRect;
            var destination = new RectangleF(
                -(this.Origin?.X ?? source.Width / 2),
                -(this.Origin?.Y ?? source.Height / 2),
                source.Width,
                source.Height);

            var repeatX = width / this.SourceRect.Width;
            var repeatY = height / this.SourceRect.Height;

            for (var x = 0; x < repeatX; x++)
            {
                for (var y = 0; y < repeatY; y++)
                {
                    var destination1 = destination;
                    destination1.Location += new Vector2(x * this.SourceRect.Width, y * this.SourceRect.Height);
                    target.Draw(this.Texture2D, destination1, source, color, depth);
                }
            }
        }
Ejemplo n.º 23
0
        public Mesh LoadFromStream(EndianBinaryReader reader)
        {
            MeshVertexAttributeHolder vertexData = null;
            SceneNode        rootNode            = new SceneNode();
            List <Texture2D> textureList         = new List <Texture2D>();
            List <WEditor.Common.Nintendo.J3D.Material> materialList = null;
            List <SkeletonBone> joints    = new List <SkeletonBone>();
            DrawInfo            drawInfo  = null;
            Envelopes           envelopes = null;

            Mesh j3dMesh = new Mesh();

            // Read the Header
            int magic = reader.ReadInt32(); // J3D1, J3D2, etc

            if (magic != 1244873778)
            {
                WLog.Warning(LogCategory.ModelLoading, null, "Attempted to load model with invalid magic, ignoring!");
                return(null);
            }

            int j3dType       = reader.ReadInt32(); // BMD3 (models) BDL4 (models), jpa1 (particles), bck1 (animations), etc.
            int totalFileSize = reader.ReadInt32();
            int chunkCount    = reader.ReadInt32();

            // Skip over an unused tag (consistent in all files) and some padding.
            reader.ReadBytes(16);

            for (int i = 0; i < chunkCount; i++)
            {
                long chunkStart = reader.BaseStream.Position;

                string tagName   = reader.ReadString(4);
                int    chunkSize = reader.ReadInt32();

                switch (tagName)
                {
                // INFO - Vertex Count, Scene Hierarchy
                case "INF1":
                    rootNode = LoadINF1FromFile(rootNode, reader, chunkStart);
                    break;

                // VERTEX - Stores vertex arrays for pos/normal/color0/tex0 etc. Contains VertexAttributes which describe
                // how this data is stored/laid out.
                case "VTX1":
                    vertexData = LoadVTX1FromFile(reader, chunkStart, chunkSize);
                    break;

                // ENVELOPES - Defines vertex weights for skinning.
                case "EVP1":
                    envelopes = LoadEVP1FromStream(reader, chunkStart);
                    break;

                // DRAW (Skeletal Animation Data) - Stores which matrices are weighted, and which are used directly.
                case "DRW1":
                    drawInfo = LoadDRW1FromStream(reader, chunkStart);
                    break;

                // JOINTS - Stores the skeletal joints (position, rotation, scale, etc.)
                case "JNT1":
                    joints = LoadJNT1SectionFromStream(reader, chunkStart);
                    break;

                // SHAPE - Face/Triangle information for model.
                case "SHP1":
                    LoadSHP1SectionFromFile(vertexData, j3dMesh, reader, chunkStart);
                    break;

                // MATERIAL - Stores materials (which describes how textures, etc. are drawn)
                case "MAT3":
                    materialList = LoadMAT3SectionFromStream(reader, chunkStart, chunkSize);
                    break;

                // TEXTURES - Stores binary texture images.
                case "TEX1":
                    textureList = LoadTEX1FromFile(reader, chunkStart);
                    break;

                // MODEL - Seems to be bypass commands for Materials and invokes GX registers directly.
                case "MDL3":
                    break;
                }

                reader.BaseStream.Position = chunkStart + chunkSize;
            }

            // Resolve the texture indexes into actual textures now that we've loaded the TEX1 section.
            foreach (Material mat in materialList)
            {
                for (int i = 0; i < mat.TextureIndexes.Length; i++)
                {
                    short index = mat.TextureIndexes[i];
                    if (index < 0)
                    {
                        continue;
                    }

                    mat.Textures[i] = textureList[index];
                }
            }

            // loltests
            for (int i = 0; i < materialList.Count; i++)
            {
                materialList[i].VtxDesc = j3dMesh.SubMeshes[0].GetVertexDescription();
                Shader shader = TEVShaderGenerator.GenerateShader(materialList[i]);
                materialList[i].Shader = shader;
            }

            // We're going to do something a little crazy - we're going to read the scene view and apply textures to meshes (for now)
            Material curMat = null;

            AssignMaterialsToMeshRecursive(rootNode, j3dMesh, ref curMat, materialList);


            List <SkeletonBone> skeleton = new List <SkeletonBone>();

            BuildSkeletonRecursive(rootNode, skeleton, joints, 0);

            j3dMesh.Skeleton  = skeleton;
            j3dMesh.BindPoses = envelopes.inverseBindPose;

            // Let's do some ugly post-processing here to see if we can't resolve all of the cross-references and turn it into
            // a normal computer-readable format that we can digest in our RenderSytem.
            {
                for (int i = 0; i < j3dMesh.SubMeshes.Count; i++)
                {
                    MeshBatch batch = j3dMesh.SubMeshes[i];
                    batch.BoneWeights = new BoneWeight[batch.Vertices.Length];

                    for (int j = 0; j < batch.PositionMatrixIndexs.Count; j++)
                    {
                        // Okay so this is where it gets more complicated. The PMI gives us an index into the MatrixTable for the packet, which we
                        // resolve and call "drawIndexes" - however we have to divide the number they give us by three for some reason, so that is
                        // already done and now our drawIndexes array should be one-index-for-every-vertex-in-batch and it should be the index into
                        // the draw section we need.
                        ushort drw1Index = batch.drawIndexes[j];

                        // The drw1Index can be set as 0xFFFF - if so, this means that you need to use the dr1Index of the previous one.
                        // until it is no longer 0xFFFF.
                        int counter = 0;
                        while (drw1Index == 0xFFFF)
                        {
                            drw1Index = batch.drawIndexes[j - counter];
                            counter++;
                        }


                        bool       isWeighted = drawInfo.IsWeighted[drw1Index];
                        BoneWeight weight     = new BoneWeight();

                        if (isWeighted)
                        {
                            // Something on this doesn't work for models that actually specify a PositionMatrixIndex.
                            // So... some math is off somewhere and I don't know where for the moment.
                            ushort numBonesAffecting = envelopes.numBonesAffecting[drw1Index];
                            weight.BoneIndexes = new ushort[numBonesAffecting];
                            weight.BoneWeights = new float[numBonesAffecting];

                            // "Much WTFs"
                            ushort offset = 0;
                            for (ushort e = 0; e < envelopes.indexRemap[drw1Index]; e++)
                            {
                                offset += envelopes.numBonesAffecting[e];
                            }

                            offset *= 2;
                            Matrix4 finalTransform = Matrix4.Identity;
                            for (ushort k = 0; k < numBonesAffecting; k++)
                            {
                                ushort boneIndex  = envelopes.indexRemap[offset + (k * 0x2)];
                                float  boneWeight = envelopes.weights[(offset / 2) + k];

                                weight.BoneIndexes[k] = boneIndex;
                                weight.BoneWeights[k] = boneWeight;

                                // This was apaprently a partial thought I never finished or got working in the old one? :S
                            }
                        }
                        else
                        {
                            // If the vertex isn't weighted, we just use the position from the bone matrix.
                            SkeletonBone joint       = skeleton[drawInfo.Indexes[drw1Index]];
                            Matrix4      translation = Matrix4.CreateTranslation(joint.Translation);
                            Matrix4      rotation    = Matrix4.CreateFromQuaternion(joint.Rotation);
                            Matrix4      finalMatrix = rotation * translation;

                            // Move the mesh by transforming the position by this much.

                            // I think we can just assign full weight to the first bone index and call it good.
                            weight.BoneIndexes = new[] { drawInfo.Indexes[drw1Index] };
                            weight.BoneWeights = new[] { 1f };
                        }

                        batch.BoneWeights[j] = weight;
                    }
                }
            }

            return(j3dMesh);
        }
Ejemplo n.º 24
0
        private static void LoadSHP1SectionFromFile(MeshVertexAttributeHolder vertexData, Mesh j3dMesh, EndianBinaryReader reader, long chunkStart)
        {
            short batchCount           = reader.ReadInt16();
            short padding              = reader.ReadInt16();
            int   batchOffset          = reader.ReadInt32();
            int   unknownTableOffset   = reader.ReadInt32(); // Another one of those 0->(n-1) counters. I think all sections have it? Might be part of the way they used inheritance to write files.
            int   alwaysZero           = reader.ReadInt32(); Trace.Assert(alwaysZero == 0);
            int   attributeOffset      = reader.ReadInt32();
            int   matrixTableOffset    = reader.ReadInt32();
            int   primitiveDataOffset  = reader.ReadInt32();
            int   matrixDataOffset     = reader.ReadInt32();
            int   packetLocationOffset = reader.ReadInt32();

            // Batches can have different attributes (ie: some have pos, some have normal, some have texcoords, etc.) they're split by batches,
            // where everything in the batch uses the same set of vertex attributes. Each batch then has several packets, which are a collection
            // of primitives.
            for (int b = 0; b < batchCount; b++)
            {
                MeshBatch meshBatch = new MeshBatch();
                j3dMesh.SubMeshes.Add(meshBatch);
                int overallVertexCount = 0;
                meshBatch.PrimitveType = OpenTK.Graphics.OpenGL.PrimitiveType.TriangleStrip; // HackHack, this varies per primitive.
                // We need to look on each primitive and convert them to trianglestrips, most are TS some are TF's.

                // We re-use the list struct here to dynamically add paired pos/col/tex as we load them
                // then we convert them into arrays for the MeshBatch afterwards.
                MeshVertexAttributeHolder meshVertexData = new MeshVertexAttributeHolder();

                // chunkStart + batchOffset gets you the position where the batches are listed
                // 0x28 * b gives you the right batch - a batch is 0x28 in length
                reader.BaseStream.Position = chunkStart + batchOffset + (0x28 * b);
                long batchStart = reader.BaseStream.Position;

                byte matrixType = reader.ReadByte();
                Trace.Assert(reader.ReadByte() == 0xFF); // Padding
                ushort packetCount          = reader.ReadUInt16();
                ushort batchAttributeOffset = reader.ReadUInt16();
                ushort firstMatrixIndex     = reader.ReadUInt16();
                ushort firstPacketIndex     = reader.ReadUInt16();
                ushort unknownpadding       = reader.ReadUInt16(); Trace.Assert(unknownpadding == 0xFFFF);

                float   boundingSphereDiameter = reader.ReadSingle();
                Vector3 boundingBoxMin         = new Vector3();
                boundingBoxMin.X = reader.ReadSingle();
                boundingBoxMin.Y = reader.ReadSingle();
                boundingBoxMin.Z = reader.ReadSingle();

                Vector3 boundingBoxMax = new Vector3();
                boundingBoxMax.X = reader.ReadSingle();
                boundingBoxMax.Y = reader.ReadSingle();
                boundingBoxMax.Z = reader.ReadSingle();


                // We need to figure out how many primitive attributes there are in the SHP1 section. This can differ from the number of
                // attributes in the VTX1 section, as the SHP1 can also include things like PositionMatrixIndex, so the count can be different.
                // This also varies *per batch* as not all batches will have the things like PositionMatrixIndex.
                reader.BaseStream.Position = chunkStart + attributeOffset + batchAttributeOffset;
                var batchAttributes = new List <ShapeAttribute>();
                do
                {
                    ShapeAttribute attribute = new ShapeAttribute();
                    attribute.ArrayType = (VertexArrayType)reader.ReadInt32();
                    attribute.DataType  = (VertexDataType)reader.ReadInt32();

                    if (attribute.ArrayType == VertexArrayType.NullAttr)
                    {
                        break;
                    }

                    batchAttributes.Add(attribute);
                } while (true);


                for (ushort p = 0; p < packetCount; p++)
                {
                    // Packet Location
                    reader.BaseStream.Position  = chunkStart + packetLocationOffset;
                    reader.BaseStream.Position += (firstPacketIndex + p) * 0x8; // A Packet Location is 0x8 long, so we skip ahead to the right one.

                    int packetSize   = reader.ReadInt32();
                    int packetOffset = reader.ReadInt32();

                    // Read the matrix data for this packet
                    reader.BaseStream.Position = chunkStart + matrixDataOffset + (firstMatrixIndex + p) * 0x08;
                    ushort matrixUnknown0   = reader.ReadUInt16();
                    ushort matrixCount      = reader.ReadUInt16();
                    uint   matrixFirstIndex = reader.ReadUInt32();

                    // Skip ahead to the actual data.
                    reader.BaseStream.Position = chunkStart + matrixTableOffset + (matrixFirstIndex * 0x2);
                    List <ushort> matrixTable = new List <ushort>();
                    for (int m = 0; m < matrixCount; m++)
                    {
                        matrixTable.Add(reader.ReadUInt16());
                    }

                    // Jump the read head to the location of the primitives for this packet.
                    reader.BaseStream.Position = chunkStart + primitiveDataOffset + packetOffset;
                    int numVertexesAtPacketStart = meshVertexData.PositionMatrixIndexes.Count;

                    uint numPrimitiveBytesRead = 0;
                    while (numPrimitiveBytesRead < packetSize)
                    {
                        // Jump to the primitives
                        // Primitives
                        GXPrimitiveType type = (GXPrimitiveType)reader.ReadByte();
                        // Game pads the chunks out with zeros, so this is the signal for an early break;
                        if (type == 0 || numPrimitiveBytesRead >= packetSize)
                        {
                            break;
                        }

                        ushort vertexCount = reader.ReadUInt16();

                        meshBatch.PrimitveType = type == GXPrimitiveType.TriangleStrip ? OpenTK.Graphics.OpenGL.PrimitiveType.TriangleStrip : OpenTK.Graphics.OpenGL.PrimitiveType.TriangleFan;
                        //if (type != GXPrimitiveType.TriangleStrip)
                        //{
                        //    WLog.Warning(LogCategory.ModelLoading, null, "Unsupported GXPrimitiveType {0}", type);
                        //}

                        numPrimitiveBytesRead += 0x3; // Advance us by 3 for the Primitive header.

                        for (int v = 0; v < vertexCount; v++)
                        {
                            meshVertexData.Indexes.Add(overallVertexCount);
                            overallVertexCount++;

                            // Iterate through the attribute types. I think the actual vertices are stored in interleaved format,
                            // ie: there's say 13 vertexes but those 13 vertexes will have a pos/color/tex index listed after it
                            // depending on the overall attributes of the file.
                            for (int attrib = 0; attrib < batchAttributes.Count; attrib++)
                            {
                                // Jump to primitive location
                                //reader.BaseStream.Position = chunkStart + primitiveDataOffset + numPrimitiveBytesRead + packetOffset;

                                // Now that we know how big the vertex type is stored in (either a Signed8 or a Signed16) we can read that much data
                                // and then we can use that index and index into
                                int  val          = 0;
                                uint numBytesRead = 0;
                                switch (batchAttributes[attrib].DataType)
                                {
                                case VertexDataType.Signed8:
                                    val          = reader.ReadByte();
                                    numBytesRead = 1;
                                    break;

                                case VertexDataType.Signed16:
                                    val          = reader.ReadInt16();
                                    numBytesRead = 2;
                                    break;

                                default:
                                    WLog.Warning(LogCategory.ModelLoading, null, "Unknown Batch Index Type: {0}", batchAttributes[attrib].DataType);
                                    break;
                                }

                                // Now that we know what the index is, we can retrieve it from the appropriate array
                                // and stick it into our vertex. The J3D format removes all duplicate vertex attributes
                                // so we need to re-duplicate them here so that we can feed them to a PC GPU in a normal fashion.
                                switch (batchAttributes[attrib].ArrayType)
                                {
                                case VertexArrayType.Position:
                                    meshVertexData.Position.Add(vertexData.Position[val]);
                                    break;

                                case VertexArrayType.PositionMatrixIndex:
                                    meshVertexData.PositionMatrixIndexes.Add(val);
                                    break;

                                case VertexArrayType.Normal:
                                    meshVertexData.Normal.Add(vertexData.Normal[val]);
                                    break;

                                case VertexArrayType.Color0:
                                    meshVertexData.Color0.Add(vertexData.Color0[val]);
                                    break;

                                case VertexArrayType.Color1:
                                    meshVertexData.Color1.Add(vertexData.Color1[val]);
                                    break;

                                case VertexArrayType.Tex0:
                                    meshVertexData.Tex0.Add(vertexData.Tex0[val]);
                                    break;

                                case VertexArrayType.Tex1:
                                    meshVertexData.Tex1.Add(vertexData.Tex1[val]);
                                    break;

                                case VertexArrayType.Tex2:
                                    meshVertexData.Tex2.Add(vertexData.Tex2[val]);
                                    break;

                                case VertexArrayType.Tex3:
                                    meshVertexData.Tex3.Add(vertexData.Tex3[val]);
                                    break;

                                case VertexArrayType.Tex4:
                                    meshVertexData.Tex4.Add(vertexData.Tex4[val]);
                                    break;

                                case VertexArrayType.Tex5:
                                    meshVertexData.Tex5.Add(vertexData.Tex5[val]);
                                    break;

                                case VertexArrayType.Tex6:
                                    meshVertexData.Tex6.Add(vertexData.Tex6[val]);
                                    break;

                                case VertexArrayType.Tex7:
                                    meshVertexData.Tex7.Add(vertexData.Tex7[val]);
                                    break;

                                default:
                                    WLog.Warning(LogCategory.ModelLoading, null, "Unsupported attribType {0}", batchAttributes[attrib].ArrayType);
                                    break;
                                }

                                numPrimitiveBytesRead += numBytesRead;
                            }

                            // Gonna try a weird hack, where if the mesh doesn't have PMI values, we're going to use just use the packet index into the matrixtable
                            // so that all meshes always have PMI values, to abstract out the ones that don't seem to (but still have matrixtable) junk. It's a guess
                            // here.
                            if (batchAttributes.Find(x => x.ArrayType == VertexArrayType.PositionMatrixIndex) == null)
                            {
                                meshVertexData.PositionMatrixIndexes.Add(p);
                            }
                        }

                        // After we write a primitive, write a special null-terminator which signifies the GPU to do a primitive restart for the next tri-strip.
                        meshVertexData.Indexes.Add(0xFFFF);
                    }

                    // The Matrix Table is per-packet, so we need to reach into the the matrix table after processing each packet
                    // and transform the indexes. Yuck. Yay.
                    for (int j = numVertexesAtPacketStart; j < meshVertexData.PositionMatrixIndexes.Count; j++)
                    {
                        // Yes you divide this by 3. No, no one knows why. $20 to the person who figures out why.
                        meshBatch.drawIndexes.Add(matrixTable[meshVertexData.PositionMatrixIndexes[j] / 3]);
                    }
                }

                meshBatch.Vertices             = meshVertexData.Position.ToArray();
                meshBatch.Color0               = meshVertexData.Color0.ToArray();
                meshBatch.Color1               = meshVertexData.Color1.ToArray();
                meshBatch.TexCoord0            = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord1            = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord2            = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord3            = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord4            = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord5            = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord6            = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord7            = meshVertexData.Tex0.ToArray();
                meshBatch.Indexes              = meshVertexData.Indexes.ToArray();
                meshBatch.PositionMatrixIndexs = meshVertexData.PositionMatrixIndexes; // This should be obsolete as they should be transformed already.
            }
        }
Ejemplo n.º 25
0
 public void FillMeshBatch(MeshBatch meshBatch, float width, float height, string text,
                           TextFormat format, TextOptions options = null)
 {
 }
Ejemplo n.º 26
0
 public void ClearMeshBatch(MeshBatch meshBatch)
 {
 }
Ejemplo n.º 27
0
        public void Draw(TiledMapComponent map, float layerDepth, MeshBatch batch, Matrix transformMatrix)
        {
            if (map.TiledMap.Orientation != TiledMapOrientation.Orthogonal)
            {
                throw new NotImplementedException();
            }

            for (var i = 0; i < map.TiledMap.Layers.Count; i++)
            {
                if (!map.TiledMap.Layers[i].Visible ||
                    (map.LayerIndicesToRender != null && !map.LayerIndicesToRender.Contains(i)))
                {
                    continue;
                }

                var layer = (TiledTileLayer)map.TiledMap.Layers[i];
                for (var y = 0; y < layer.Height; y++)
                {
                    for (var x = 0; x < layer.Width; x++)
                    {
                        var tile = layer.GetTile(x, y);
                        if (tile == null)
                        {
                            continue;
                        }

                        if (tile.TileSet == null || tile.TileSetTile == null || tile.OldId != tile.Id)
                        {
                            tile.OldId             = tile.Id;
                            tile.TileSet           = map.TiledMap.TileSets.First(a => a.Tiles.Any(b => b.Id + a.FirstGid == tile.Id));
                            tile.TileSetTile       = tile.TileSet.Tiles.First(b => b.Id + tile.TileSet.FirstGid == tile.Id);
                            tile.RenderTileSetTile = tile.TileSetTile;
                            tile.CurrentFrame      = 0;
                            tile.ElapsedTime       = 0;
                        }

                        // for the y position, we need to take into account if the tile is larger than the tileHeight and shift. Tiled uses
                        // a bottom-left coordinate system and MonoGame a top-left
                        var tx       = x * map.TiledMap.TileWidth;
                        var ty       = y * map.TiledMap.TileHeight;
                        var rotation = 0f;

                        var spriteEffects = SpriteEffects.None;
                        if (tile.FlippedHorizonally)
                        {
                            spriteEffects |= SpriteEffects.FlipHorizontally;
                        }
                        if (tile.FlippedVertically)
                        {
                            spriteEffects |= SpriteEffects.FlipVertically;
                        }
                        if (tile.FlippedDiagonally)
                        {
                            if (tile.FlippedHorizonally && tile.FlippedVertically)
                            {
                                spriteEffects ^= SpriteEffects.FlipVertically;
                                rotation       = MathHelper.PiOver2;
                                tx            += map.TiledMap.TileHeight + (tile.RenderTileSetTile.SourceRect.Height - map.TiledMap.TileHeight);
                                ty            -= (tile.RenderTileSetTile.SourceRect.Width - map.TiledMap.TileWidth);
                            }
                            else if (tile.FlippedHorizonally)
                            {
                                spriteEffects ^= SpriteEffects.FlipVertically;
                                rotation       = -MathHelper.PiOver2;
                                ty            += map.TiledMap.TileHeight;
                            }
                            else if (tile.FlippedVertically)
                            {
                                spriteEffects ^= SpriteEffects.FlipHorizontally;
                                rotation       = MathHelper.PiOver2;
                                tx            += map.TiledMap.TileWidth + (tile.RenderTileSetTile.SourceRect.Height - map.TiledMap.TileHeight);
                                ty            += (map.TiledMap.TileWidth - tile.RenderTileSetTile.SourceRect.Width);
                            }
                            else
                            {
                                spriteEffects ^= SpriteEffects.FlipHorizontally;
                                rotation       = -MathHelper.PiOver2;
                                ty            += map.TiledMap.TileHeight;
                            }
                        }

                        // if we had no rotations (diagonal flipping) shift our y-coord to account for any non-tileSized tiles to account for
                        // Tiled being bottom-left origin
                        if (rotation == 0)
                        {
                            ty += map.TiledMap.TileHeight - tile.RenderTileSetTile.SourceRect.Height;
                        }

                        var destRect = tile.RenderTileSetTile.SourceRect;
                        destRect.Location = new Point(0, 0);

                        var meshItem = batch.Draw(tile.TileSet.ImageTexture, destRect, tile.RenderTileSetTile.SourceRect, Color.White, layerDepth);
                        meshItem.RotateMesh(rotation);
                        meshItem.ApplyEffectToMesh(spriteEffects);
                        meshItem.MoveMesh(new Vector3(tx + layer.Offset.X, ty + layer.Offset.Y, 0));
                        meshItem.ApplyTransformMesh(transformMatrix);
                    }
                }
            }
        }
Ejemplo n.º 28
0
 public void DrawInto(Color color, float depth, MeshBatch target)
 {
     this.DrawInto(this.SourceRect.Width, this.SourceRect.Height, color, depth, target);
 }
Ejemplo n.º 29
0
 public void DrawInto(Color color, float depth, MeshBatch target)
 {
     this.DrawInto(1, 1, color, depth, target);
 }
Ejemplo n.º 30
0
        public virtual void DrawInto(float width, float height, Color color, float depth, MeshBatch target)
        {
            var source      = this.SourceRect;
            var destination = new RectangleF(
                -(this.Origin?.X ?? this.SourceRect.Width),
                -(this.Origin?.Y ?? this.SourceRect.Height),
                width,
                height);

            target.Draw(this.Texture2D, destination, source, color, depth);
        }
Ejemplo n.º 31
0
        public override void DrawInto(float width, float height, Color color, float depth, MeshBatch target)
        {
            var scale = new Vector2(width / this.SourceRect.Width, height / this.SourceRect.Height);

            var rects       = new List <Tuple <Rectangle, Rectangle> >();
            var sourceRects = this.NinePatchRects;

            GenerateNinePatchRects(
                this.SourceRect,
                this.destinationRects,
                (int)(this.Left / scale.X),
                (int)(this.Right / scale.X),
                (int)(this.Top / scale.Y),
                (int)(this.Bottom / scale.Y));

            for (var i = 0; i < 9; i++)
            {
                var source      = sourceRects[i];
                var destination = this.destinationRects[i];
                destination.Location -= this.SourceRect.Location + (this.Origin?.ToPoint() ?? this.SourceRect.Center);
                destination.Width     = (int)(destination.Width * width / this.SourceRect.Width);
                destination.Height    = (int)(destination.Height * height / this.SourceRect.Height);
                rects.Add(new Tuple <Rectangle, Rectangle>(source, destination));
            }

            for (var i = 0; i < rects.Count; i++)
            {
                var rect        = rects[i];
                var source      = rect.Item1;
                var destination = rect.Item2;

                target.Draw(this.Texture2D, destination, source, color, depth);
            }
        }
Ejemplo n.º 32
0
        private static void LoadSHP1SectionFromFile(MeshVertexAttributeHolder vertexData, Mesh j3dMesh, EndianBinaryReader reader, long chunkStart)
        {
            short batchCount = reader.ReadInt16();
            short padding = reader.ReadInt16();
            int batchOffset = reader.ReadInt32();
            int unknownTableOffset = reader.ReadInt32(); // Another one of those 0->(n-1) counters. I think all sections have it? Might be part of the way they used inheritance to write files.
            int alwaysZero = reader.ReadInt32(); Trace.Assert(alwaysZero == 0);
            int attributeOffset = reader.ReadInt32();
            int matrixTableOffset = reader.ReadInt32();
            int primitiveDataOffset = reader.ReadInt32();
            int matrixDataOffset = reader.ReadInt32();
            int packetLocationOffset = reader.ReadInt32();

            // Batches can have different attributes (ie: some have pos, some have normal, some have texcoords, etc.) they're split by batches,
            // where everything in the batch uses the same set of vertex attributes. Each batch then has several packets, which are a collection
            // of primitives.
            for (int b = 0; b < batchCount; b++)
            {
                MeshBatch meshBatch = new MeshBatch();
                j3dMesh.SubMeshes.Add(meshBatch);
                int overallVertexCount = 0;
                meshBatch.PrimitveType = OpenTK.Graphics.OpenGL.PrimitiveType.TriangleStrip; // HackHack, this varies per primitive.
                // We need to look on each primitive and convert them to trianglestrips, most are TS some are TF's.

                // We re-use the list struct here to dynamically add paired pos/col/tex as we load them
                // then we convert them into arrays for the MeshBatch afterwards.
                MeshVertexAttributeHolder meshVertexData = new MeshVertexAttributeHolder();

                // chunkStart + batchOffset gets you the position where the batches are listed
                // 0x28 * b gives you the right batch - a batch is 0x28 in length
                reader.BaseStream.Position = chunkStart + batchOffset + (0x28 * b);
                long batchStart = reader.BaseStream.Position;

                byte matrixType = reader.ReadByte();
                Trace.Assert(reader.ReadByte() == 0xFF); // Padding
                ushort packetCount = reader.ReadUInt16();
                ushort batchAttributeOffset = reader.ReadUInt16();
                ushort firstMatrixIndex = reader.ReadUInt16();
                ushort firstPacketIndex = reader.ReadUInt16();
                ushort unknownpadding = reader.ReadUInt16(); Trace.Assert(unknownpadding == 0xFFFF);

                float boundingSphereDiameter = reader.ReadSingle();
                Vector3 boundingBoxMin = new Vector3();
                boundingBoxMin.X = reader.ReadSingle();
                boundingBoxMin.Y = reader.ReadSingle();
                boundingBoxMin.Z = reader.ReadSingle();

                Vector3 boundingBoxMax = new Vector3();
                boundingBoxMax.X = reader.ReadSingle();
                boundingBoxMax.Y = reader.ReadSingle();
                boundingBoxMax.Z = reader.ReadSingle();

                // We need to figure out how many primitive attributes there are in the SHP1 section. This can differ from the number of
                // attributes in the VTX1 section, as the SHP1 can also include things like PositionMatrixIndex, so the count can be different.
                // This also varies *per batch* as not all batches will have the things like PositionMatrixIndex.
                reader.BaseStream.Position = chunkStart + attributeOffset + batchAttributeOffset;
                var batchAttributes = new List<ShapeAttribute>();
                do
                {
                    ShapeAttribute attribute = new ShapeAttribute();
                    attribute.ArrayType = (VertexArrayType)reader.ReadInt32();
                    attribute.DataType = (VertexDataType)reader.ReadInt32();

                    if (attribute.ArrayType == VertexArrayType.NullAttr)
                        break;

                    batchAttributes.Add(attribute);

                } while (true);

                for (ushort p = 0; p < packetCount; p++)
                {
                    // Packet Location
                    reader.BaseStream.Position = chunkStart + packetLocationOffset;
                    reader.BaseStream.Position += (firstPacketIndex + p) * 0x8; // A Packet Location is 0x8 long, so we skip ahead to the right one.

                    int packetSize = reader.ReadInt32();
                    int packetOffset = reader.ReadInt32();

                    // Read the matrix data for this packet
                    reader.BaseStream.Position = chunkStart + matrixDataOffset + (firstMatrixIndex + p) * 0x08;
                    ushort matrixUnknown0 = reader.ReadUInt16();
                    ushort matrixCount = reader.ReadUInt16();
                    uint matrixFirstIndex = reader.ReadUInt32();

                    // Skip ahead to the actual data.
                    reader.BaseStream.Position = chunkStart + matrixTableOffset + (matrixFirstIndex * 0x2);
                    List<ushort> matrixTable = new List<ushort>();
                    for (int m = 0; m < matrixCount; m++)
                    {
                        matrixTable.Add(reader.ReadUInt16());
                    }

                    // Jump the read head to the location of the primitives for this packet.
                    reader.BaseStream.Position = chunkStart + primitiveDataOffset + packetOffset;
                    int numVertexesAtPacketStart = meshVertexData.PositionMatrixIndexes.Count;

                    uint numPrimitiveBytesRead = 0;
                    while (numPrimitiveBytesRead < packetSize)
                    {
                        // Jump to the primitives
                        // Primitives
                        GXPrimitiveType type = (GXPrimitiveType)reader.ReadByte();
                        // Game pads the chunks out with zeros, so this is the signal for an early break;
                        if (type == 0 || numPrimitiveBytesRead >= packetSize)
                            break;

                        ushort vertexCount = reader.ReadUInt16();

                        meshBatch.PrimitveType = type == GXPrimitiveType.TriangleStrip ? OpenTK.Graphics.OpenGL.PrimitiveType.TriangleStrip : OpenTK.Graphics.OpenGL.PrimitiveType.TriangleFan;
                        //if (type != GXPrimitiveType.TriangleStrip)
                        //{
                        //    WLog.Warning(LogCategory.ModelLoading, null, "Unsupported GXPrimitiveType {0}", type);
                        //}

                        numPrimitiveBytesRead += 0x3; // Advance us by 3 for the Primitive header.

                        for (int v = 0; v < vertexCount; v++)
                        {
                            meshVertexData.Indexes.Add(overallVertexCount);
                            overallVertexCount++;

                            // Iterate through the attribute types. I think the actual vertices are stored in interleaved format,
                            // ie: there's say 13 vertexes but those 13 vertexes will have a pos/color/tex index listed after it
                            // depending on the overall attributes of the file.
                            for (int attrib = 0; attrib < batchAttributes.Count; attrib++)
                            {
                                // Jump to primitive location
                                //reader.BaseStream.Position = chunkStart + primitiveDataOffset + numPrimitiveBytesRead + packetOffset;

                                // Now that we know how big the vertex type is stored in (either a Signed8 or a Signed16) we can read that much data
                                // and then we can use that index and index into
                                int val = 0;
                                uint numBytesRead = 0;
                                switch (batchAttributes[attrib].DataType)
                                {
                                    case VertexDataType.Signed8:
                                        val = reader.ReadByte();
                                        numBytesRead = 1;
                                        break;
                                    case VertexDataType.Signed16:
                                        val = reader.ReadInt16();
                                        numBytesRead = 2;
                                        break;
                                    default:
                                        WLog.Warning(LogCategory.ModelLoading, null, "Unknown Batch Index Type: {0}", batchAttributes[attrib].DataType);
                                        break;
                                }

                                // Now that we know what the index is, we can retrieve it from the appropriate array
                                // and stick it into our vertex. The J3D format removes all duplicate vertex attributes
                                // so we need to re-duplicate them here so that we can feed them to a PC GPU in a normal fashion.
                                switch (batchAttributes[attrib].ArrayType)
                                {
                                    case VertexArrayType.Position:
                                        meshVertexData.Position.Add(vertexData.Position[val]);
                                        break;
                                    case VertexArrayType.PositionMatrixIndex:
                                        meshVertexData.PositionMatrixIndexes.Add(val);
                                        break;
                                    case VertexArrayType.Normal:
                                        meshVertexData.Normal.Add(vertexData.Normal[val]);
                                        break;
                                    case VertexArrayType.Color0:
                                        meshVertexData.Color0.Add(vertexData.Color0[val]);
                                        break;
                                    case VertexArrayType.Color1:
                                        meshVertexData.Color1.Add(vertexData.Color1[val]);
                                        break;
                                    case VertexArrayType.Tex0:
                                        meshVertexData.Tex0.Add(vertexData.Tex0[val]);
                                        break;
                                    case VertexArrayType.Tex1:
                                        meshVertexData.Tex1.Add(vertexData.Tex1[val]);
                                        break;
                                    case VertexArrayType.Tex2:
                                        meshVertexData.Tex2.Add(vertexData.Tex2[val]);
                                        break;
                                    case VertexArrayType.Tex3:
                                        meshVertexData.Tex3.Add(vertexData.Tex3[val]);
                                        break;
                                    case VertexArrayType.Tex4:
                                        meshVertexData.Tex4.Add(vertexData.Tex4[val]);
                                        break;
                                    case VertexArrayType.Tex5:
                                        meshVertexData.Tex5.Add(vertexData.Tex5[val]);
                                        break;
                                    case VertexArrayType.Tex6:
                                        meshVertexData.Tex6.Add(vertexData.Tex6[val]);
                                        break;
                                    case VertexArrayType.Tex7:
                                        meshVertexData.Tex7.Add(vertexData.Tex7[val]);
                                        break;
                                    default:
                                        WLog.Warning(LogCategory.ModelLoading, null, "Unsupported attribType {0}", batchAttributes[attrib].ArrayType);
                                        break;
                                }

                                numPrimitiveBytesRead += numBytesRead;
                            }

                            // Gonna try a weird hack, where if the mesh doesn't have PMI values, we're going to use just use the packet index into the matrixtable
                            // so that all meshes always have PMI values, to abstract out the ones that don't seem to (but still have matrixtable) junk. It's a guess
                            // here.
                            if (batchAttributes.Find(x => x.ArrayType == VertexArrayType.PositionMatrixIndex) == null)
                            {
                                meshVertexData.PositionMatrixIndexes.Add(p);
                            }
                        }

                        // After we write a primitive, write a special null-terminator which signifies the GPU to do a primitive restart for the next tri-strip.
                        meshVertexData.Indexes.Add(0xFFFF);
                    }

                    // The Matrix Table is per-packet, so we need to reach into the the matrix table after processing each packet
                    // and transform the indexes. Yuck. Yay.
                    for (int j = numVertexesAtPacketStart; j < meshVertexData.PositionMatrixIndexes.Count; j++)
                    {
                        // Yes you divide this by 3. No, no one knows why. $20 to the person who figures out why.
                        meshBatch.drawIndexes.Add(matrixTable[meshVertexData.PositionMatrixIndexes[j] / 3]);
                    }
                }

                meshBatch.Vertices = meshVertexData.Position.ToArray();
                meshBatch.Color0 = meshVertexData.Color0.ToArray();
                meshBatch.Color1 = meshVertexData.Color1.ToArray();
                meshBatch.TexCoord0 = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord1 = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord2 = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord3 = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord4 = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord5 = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord6 = meshVertexData.Tex0.ToArray();
                meshBatch.TexCoord7 = meshVertexData.Tex0.ToArray();
                meshBatch.Indexes = meshVertexData.Indexes.ToArray();
                meshBatch.PositionMatrixIndexs = meshVertexData.PositionMatrixIndexes; // This should be obsolete as they should be transformed already.
            }
        }
Ejemplo n.º 33
0
        private void Generate()
        {
            var tempPath = GetTempPath();

            if (!Directory.Exists(tempPath))
            {
                Directory.CreateDirectory(tempPath);
            }
            var tempFiles = Directory.GetFiles(tempPath);

            foreach (var file in tempFiles)
            {
                File.Delete(file);
            }

            var filesPng  = Directory.GetFiles(_pngSource.Text, "*.png");
            var filesJpeg = Directory.GetFiles(_pngSource.Text, "*.jpeg");
            var filesJpg  = Directory.GetFiles(_pngSource.Text, "*.jpg");
            var filesList = new List <string>();

            filesList.AddRange(filesPng);
            filesList.AddRange(filesJpeg);
            filesList.AddRange(filesJpg);
            var files = filesList.ToArray();

            foreach (var file in files)
            {
                //var copy = Path.Combine(tempPath, Path.GetFileName(file));

                var name = Path.GetFileNameWithoutExtension(file);

                if (name.EndsWith("bump"))
                {
                    using (var source = new Bitmap(file))
                        using (var bitmap = CreateNormalMap(source))
                            SaveMipmap(bitmap, tempPath, name);
                }
                else
                {
                    using (var bitmap = new Bitmap(file))
                    {
                        using (var targetStream = File.Create(Path.Combine(tempPath, Path.GetFileNameWithoutExtension(file) + ".raw")))
                            using (var writer = new BinaryWriter(targetStream))
                            {
                                SaveUncompressedRaw(bitmap, writer, 2048);
                            }
                        //SaveMipmap(bitmap, tempPath, name);
                    }
                }
            }
            files = Directory.GetFiles(_pngSource.Text, "*.obj");
            var meshes = new List <Mesh>();

            foreach (var file in files)
            {
                var name = Path.GetFileNameWithoutExtension(file);
                using (var stringReader = new StreamReader(file))
                {
                    var localMeshes = ConvertObjToBinary(stringReader, tempPath, name);
                    foreach (var localMesh in localMeshes)
                    {
                        meshes.Add(localMesh);
                    }
                }
            }

            var meshBatch = new MeshBatch(meshes.ToArray());

            using (var stream = File.Create(Path.Combine(tempPath, "batch_vb_big.3d")))
                using (var writer = new BinaryWriter(stream))
                    meshBatch.WriteVertices(writer, true);
            using (var stream = File.Create(Path.Combine(tempPath, "batch_vb_lit.3d")))
                using (var writer = new BinaryWriter(stream))
                    meshBatch.WriteVertices(writer, false);

            using (var stream = File.Create(Path.Combine(tempPath, "batch_ib_big.3d")))
                using (var writer = new BinaryWriter(stream))
                    meshBatch.WriteIndices(writer, true);
            using (var stream = File.Create(Path.Combine(tempPath, "batch_ib_lit.3d")))
                using (var writer = new BinaryWriter(stream))
                    meshBatch.WriteIndices(writer, false);

            using (var stream = File.Create(Path.Combine(tempPath, "batch_transforms_big.3d")))
                using (var writer = new BinaryWriter(stream))
                    meshBatch.WriteTransforms(writer, true);
            using (var stream = File.Create(Path.Combine(tempPath, "batch_transforms_lit.3d")))
                using (var writer = new BinaryWriter(stream))
                    meshBatch.WriteTransforms(writer, false);

            files = Directory.GetFiles(tempPath, "*.png");
            foreach (var file in files)
            {
                if (!ExecuteCommand(_etc1Tool.Text, "\"" + file + "\""))
                {
                    return;
                }
                Application.DoEvents();
            }

            files = Directory.GetFiles(_targetFolder.Text, "*.pkm");
            foreach (var file in files)
            {
                File.Delete(file);
                Application.DoEvents();
            }

            files = Directory.GetFiles(_targetFolder.Text, "*.3d");
            foreach (var file in files)
            {
                File.Delete(file);
                Application.DoEvents();
            }

            files = Directory.GetFiles(tempPath, "*.pkm");
            foreach (var file in files)
            {
                var copy = Path.Combine(_targetFolder.Text, Path.GetFileName(file));
                File.Copy(file, copy, true);
                Application.DoEvents();
            }

            files = Directory.GetFiles(tempPath, "*.raw");
            foreach (var file in files)
            {
                var copy = Path.Combine(_targetFolder.Text, Path.GetFileName(file));
                File.Copy(file, copy, true);
                Application.DoEvents();
            }

            files = Directory.GetFiles(tempPath, "*.3d");
            foreach (var file in files)
            {
                var copy = Path.Combine(_targetFolder.Text, Path.GetFileName(file));
                File.Copy(file, copy, true);
                Application.DoEvents();
            }
        }