public static string GeneratePixelShader(MDL0ObjectNode obj)
        {
            Reset();

            MDL0MaterialNode mat = obj.UsableMaterialNode;
            MDL0ShaderNode shader = mat.ShaderNode;

            //w("#version 330\n");

            foreach (MDL0MaterialRefNode r in mat.Children)
                w("uniform sampler2D Texture{0};", r.Index);

            for (int i = 0; i < obj._uvSet.Length; i++)
                if (obj._uvSet[i] != null)
                    w("in vec2 UVSet{0};", i);
            for (int i = 0; i < obj._colorSet.Length; i++)
                if (obj._colorSet[i] != null)
                    w("in vec2 ColorSet{0};", i);

            w("out vec4 out_color;\n");

            //w("uniform vec4 C1Amb;\n");
            //w("uniform vec4 C2Amb;\n");
            //w("uniform vec4 C1Mat;\n");
            //w("uniform vec4 C2Mat;\n");

            Start();

            foreach (MDL0MaterialRefNode r in mat.Children)
                if (r.TextureCoordId >= 0)
                    w("vec4 tex{0}col = texture2D(Texture{0}, UVSet{1}.st);\n", r.Index, r.TextureCoordId);

            //w("vec4 creg0 = vec4(0.0, 0.0, 0.0, 0.0);\n");
            //w("vec4 creg1 = vec4(0.0, 0.0, 0.0, 0.0);\n");
            //w("vec4 creg2 = vec4(0.0, 0.0, 0.0, 0.0);\n");
            //w("vec4 prev = vec4(0.0, 0.0, 0.0, 0.0);\n");

            //foreach (TEVStage stage in shader.Children)
            //    if (stage.Index < mat.ActiveShaderStages)
            //        w(stage.Write(mat, obj));
            //    else break;

            //if (shader._stages > 0)
            //{
            //    w("prev.rgb = {0};\n", tevCOutputTable[(int)((TEVStage)shader.Children[shader.Children.Count - 1]).ColorRegister]);
            //    w("prev.a = {0};\n", tevAOutputTable[(int)((TEVStage)shader.Children[shader.Children.Count - 1]).AlphaRegister]);
            //}

            w("out_color = tex0col;");

            Finish();

            return tempShader;
        }
Example #2
0
        private void RecursiveGetInfluencedObjects(ref List <MDL0ObjectNode> changed)
        {
            foreach (IMatrixNodeUser user in Users)
            {
                if (user is MDL0ObjectNode)
                {
                    MDL0ObjectNode o = user as MDL0ObjectNode;

                    if (!changed.Contains(o))
                    {
                        changed.Add(o);
                    }
                }
                else if (user is Vertex3)
                {
                    Vertex3        v = user as Vertex3;
                    MDL0ObjectNode o = v.Parent as MDL0ObjectNode;

                    if (!changed.Contains(o))
                    {
                        changed.Add(o);
                    }
                }
            }

            foreach (MDL0ObjectNode o in _singleBindObjects)
            {
                if (!changed.Contains(o))
                {
                    changed.Add(o);
                }
            }

            foreach (MDL0BoneNode bone in Children)
            {
                bone.RecursiveGetInfluencedObjects(ref changed);
            }
        }
 private void lstPolygons_SelectedValueChanged(object sender, EventArgs e)
 {
     _targetObject = _selectedPolygon = lstObjects.SelectedItem as MDL0ObjectNode;
     TargetTexRef = _selectedPolygon != null && _selectedTexture != null ? _selectedPolygon.UsableMaterialNode.FindChild(_selectedTexture.Name, true) as MDL0MaterialRefNode : null;
     _mainWindow.SelectedPolygonChanged(this, null);
     overObjPnl.Invalidate();
     overTexPnl.Invalidate();
 }
        public void RenderObject(MDL0ObjectNode p, TKContext ctx, ModelPanel mainWindow, float maxDrawPriority)
        {
            if (p._render)
            {
                if (_dontRenderOffscreen)
                {
                    Vector3 min = new Vector3(float.MaxValue);
                    Vector3 max = new Vector3(float.MinValue);

                    if (p._manager != null)
                        foreach (Vertex3 vertex in p._manager._vertices)
                        {
                            Vector3 v = mainWindow.Project(vertex.WeightedPosition);

                            min.Min(v);
                            max.Max(v);
                        }

                    if (max._x < 0 || min._x > mainWindow.Size.Width ||
                        max._y < 0 || min._y > mainWindow.Size.Height)
                        return;
                }

                if (_renderPolygons)
                {
                    float polyOffset = 0.0f;
                    //polyOffset -= p.DrawPriority;
                    //polyOffset += maxDrawPriority;
                    if (_renderWireframe)
                        polyOffset += 1.0f;
                    if (polyOffset != 0)
                    {
                        GL.Enable(EnableCap.PolygonOffsetFill);
                        GL.PolygonOffset(1.0f, polyOffset);
                    }
                    else
                        GL.Disable(EnableCap.PolygonOffsetFill);
                    GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
                    p.Render(ctx, false, mainWindow);
                }
                if (_renderWireframe)
                {
                    GL.Disable(EnableCap.PolygonOffsetFill);
                    GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
                    GL.LineWidth(0.5f);
                    p.Render(ctx, true, mainWindow);
                }
            }
        }
        private static unsafe void WritePrimitive(MDL0ObjectNode poly, NewPrimitive prim, XmlWriter writer)
        {
            PrimitiveManager manager = poly._manager;
            int count;
            int elements = 0, stride = 0;
            int set;
            bool first;
            uint[] pDataArr = prim._indices;
            uint pData = 0;
            ushort* pVert = (ushort*)poly._manager._indices.Address;

            switch (prim._type)
            {
                case BeginMode.Triangles:
                    writer.WriteStartElement("triangles");
                    stride = 3;
                    break;

                case BeginMode.Lines:
                    writer.WriteStartElement("lines");
                    stride = 2;
                    break;

                case BeginMode.Points:
                    writer.WriteStartElement("points");
                    stride = 1;
                    break;
            }
            count = prim._elementCount / stride;

            if (poly.UsableMaterialNode != null)
                writer.WriteAttributeString("material", poly.UsableMaterialNode.Name);

            writer.WriteAttributeString("count", count.ToString());

            List<int> elementType = new List<int>();
            for (int i = 0; i < 12; i++)
            {
                if (manager._faceData[i] == null)
                    continue;

                writer.WriteStartElement("input");

                switch (i)
                {
                    case 0:
                        writer.WriteAttributeString("semantic", "VERTEX");
                        writer.WriteAttributeString("source", "#" + poly._name + "_Vertices");
                        break;

                    case 1:
                        writer.WriteAttributeString("semantic", "NORMAL");
                        writer.WriteAttributeString("source", "#" + poly._name + "_Normals");
                        break;

                    case 2:
                    case 3:
                        set = i - 2;
                        writer.WriteAttributeString("semantic", "COLOR");
                        writer.WriteAttributeString("source", "#" + poly._name + "_Colors" + set.ToString());
                        writer.WriteAttributeString("set", set.ToString());
                        break;

                    default:
                        set = i - 4;
                        writer.WriteAttributeString("semantic", "TEXCOORD");
                        writer.WriteAttributeString("source", "#" + poly._name + "_UVs" + set.ToString());
                        writer.WriteAttributeString("set", set.ToString());
                        break;
                }

                writer.WriteAttributeString("offset", elements.ToString());
                writer.WriteEndElement(); //input

                elements++;
                elementType.Add(i);
            }

            writer.WriteStartElement("p");
            first = true;
            for (int i = 0; i < count; i++)
            {
                for (int x = 0; x < stride; x++)
                {
                    int index = (int)pDataArr[pData++];
                    for (int y = 0; y < elements; y++)
                    {
                        if (first)
                            first = false;
                        else
                            writer.WriteString(" ");

                        if (elementType[y] < 4)
                            if (elementType[y] < 2)
                                if (elementType[y] == 0)
                                    writer.WriteString(pVert[index].ToString(CultureInfo.InvariantCulture.NumberFormat));
                                else
                                    writer.WriteString(_normRemap[index].ToString(CultureInfo.InvariantCulture.NumberFormat));
                            else
                                writer.WriteString(_colorRemap[elementType[y] - 2][index].ToString(CultureInfo.InvariantCulture.NumberFormat));
                        else
                            writer.WriteString(_uvRemap[elementType[y] - 4][index].ToString(CultureInfo.InvariantCulture.NumberFormat));
                    }
                }
            }
            writer.WriteEndElement(); //p
            writer.WriteEndElement(); //primitive
        }
Example #6
0
        private void SelectVerts(MDL0ObjectNode o)
        {
            foreach (Vertex3 v in o._manager._vertices)
            {
                //Project each vertex into screen coordinates.
                //Then check to see if the 2D coordinates lie within the selection box.
                //In Soviet Russia, vertices come to YOUUUUU

                Vector3 vec3 = v.WeightedPosition;
                Vector2 vec2 = (Vector2)modelPanel.Project(vec3);
                Point start = modelPanel._selStart, end = modelPanel._selEnd;
                Vector2 min = new Vector2(Math.Min(start.X, end.X), Math.Min(start.Y, end.Y));
                Vector2 max = new Vector2(Math.Max(start.X, end.X), Math.Max(start.Y, end.Y));
                if ((vec2 <= max) && (vec2 >= min))
                    if (Alt)
                    {
                        v._selected = false;
                        if (_selectedVertices.Contains(v))
                            _selectedVertices.Remove(v);
                        v._highlightColor = Color.Transparent;
                    }
                    else if (!v._selected)
                    {
                        v._selected = true;

                        if (!Ctrl || !_selectedVertices.Contains(v))
                            _selectedVertices.Add(v);
                        v._highlightColor = Color.Orange;
                    }
            }
        }
Example #7
0
        public string GeneratePixelShaderCode(MDL0ObjectNode Object, PSGRENDER_MODE PSGRenderMode, TKContext ctx)
        {
            tempShader = "";

            int numStages = ShaderNode.Children.Count;
            int numTexgen = Children.Count;

            w("//Pixel Shader for TEV stages\n");
            w("//{0} TEV stages, {1} texgens, {2} IND stages\n", numStages, numTexgen, IndirectShaderStages);

            int nIndirectStagesUsed = 0;

            if (IndirectShaderStages > 0)
            {
                for (int i = 0; i < numStages; ++i)
                {
                    TEVStage stage = ShaderNode.Children[i] as TEVStage;
                    if (stage.IndirectActive && stage.bt < IndirectShaderStages)
                    {
                        nIndirectStagesUsed |= 1 << stage.bt;
                    }
                }
            }

            DepthTextureEnable = (/*bpmem.ztex2.op != ZTEXTURE_DISABLE && */ !ZCompareLoc && EnableDepthTest && EnableDepthUpdate) /* || g_ActiveConfig.bEnablePerPixelDepth*/;

            //A few required defines and ones that will make our lives a lot easier
            if (ctx.bSupportsGLSLBinding || ctx.bSupportsGLSLUBO)
            {
                w("#version 330 compatibility\n");
                if (ctx.bSupportsGLSLBinding)
                {
                    w("#extension GL_ARB_shading_language_420pack : enable\n");
                }
                //if (ctx.bSupportsGLSLUBO)
                //    w("#extension GL_ARB_uniform_buffer_object : enable\n");
            }
            else
            {
                w("#version 120\n");
            }

            if (ctx.bSupportsGLSLATTRBind)
            {
                w("#extension GL_ARB_explicit_attrib_location : enable\n");
            }

            w("#define saturate(x) clamp(x, 0.0f, 1.0f)\n");
            w("#define lerp(x, y, z) mix(x, y, z)\n");

            w("float fmod(float x, float y)\n");
            w("{\n");
            w("float z = fract(abs(x / y)) * abs(y);\n");
            w("return (x < 0) ? -z : z;\n");
            w("}\n");

            for (uint i = 0; i < 8; i++)
            {
                w("{0}uniform sampler2D samp{1};\n", WriteBinding(i, ctx), i);
            }

            w("\n");

            w("uniform vec4 " + I_COLORS + "[4];\n");
            w("uniform vec4 " + I_KCOLORS + "[4];\n");
            w("uniform vec4 " + I_ALPHA + ";\n");
            w("uniform vec4 " + I_TEXDIMS + "[8];\n");
            w("uniform vec4 " + I_ZBIAS + "[2];\n");
            w("uniform vec4 " + I_INDTEXSCALE + "[2];\n");
            w("uniform vec4 " + I_INDTEXMTX + "[6];\n");
            w("uniform vec4 " + I_FOG + "[3];\n");

            // Compiler will optimize these out by itself.
            w("uniform vec4 " + I_PLIGHTS + "[40];\n");
            w("uniform vec4 " + I_PMATERIALS + "[4];\n");

            w("vec4 ocol0;\n");

            if (DepthTextureEnable)
            {
                w("float depth;\n");
            }

            w("vec4 rawpos = gl_FragCoord;\n");

            w("vec4 colors_0 = gl_Color;\n");
            w("vec4 colors_1 = gl_SecondaryColor;\n");

            if (numTexgen < 7)
            {
                for (int i = 0; i < numTexgen; i++)
                {
                    w("vec3 uv{0} = gl_TexCoord[{0}].xyz;\n", i);
                }
                w("vec4 clipPos = gl_TexCoord[{0}];\n", numTexgen);
                w("vec4 Normal = gl_TexCoord[{0}];\n", numTexgen + 1);
            }
            else
            {
                for (int i = 0; i < 8; ++i)
                {
                    w("vec4 uv{0} = gl_TexCoord[{0}];\n", i);
                }
            }

            w("void main()\n{\n");

            AlphaPretest Pretest = PretestAlpha();

            //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_ALPHA_PASS && !DepthTextureEnable && Pretest >= 0)
            //{
            //    if (Pretest == AlphaPretest.AlwaysFail)
            //    {
            //        w("ocol0 = vec4(0);\n");
            //        w("discard;\n");

            //        if(PSGRenderMode != PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND)
            //            w("gl_FragColor = ocol0;\n");

            //        w("return;\n");
            //    }
            //    else
            //        w("ocol0 = " + I_ALPHA + ".aaaa;\n");

            //    w("}\n");

            //    return tempShader;
            //}

            w("vec4 c0 = " + I_COLORS + "[1], c1 = " + I_COLORS + "[2], c2 = " + I_COLORS + "[3], prev = vec4(0.0f, 0.0f, 0.0f, 0.0f), textemp = vec4(0.0f, 0.0f, 0.0f, 0.0f), rastemp = vec4(0.0f, 0.0f, 0.0f, 0.0f), konsttemp = vec4(0.0f, 0.0f, 0.0f, 0.0f);\n");
            w("vec3 comp16 = vec3(1.0f, 255.0f, 0.0f), comp24 = vec3(1.0f, 255.0f, 255.0f*255.0f);\n");
            w("vec4 alphabump = vec4(0.0f,0.0f,0.0f,0.0f);\n");
            w("vec3 tevcoord = vec3(0.0f, 0.0f, 0.0f);\n");
            w("vec2 wrappedcoord=vec2(0.0f,0.0f), tempcoord=vec2(0.0f,0.0f);\n");
            w("vec4 cc0 = vec4(0.0f,0.0f,0.0f,0.0f), cc1 = vec4(0.0f,0.0f,0.0f,0.0f);\n");
            w("vec4 cc2 = vec4(0.0f,0.0f,0.0f,0.0f), cprev = vec4(0.0f,0.0f,0.0f,0.0f);\n");
            w("vec4 crastemp=vec4(0.0f,0.0f,0.0f,0.0f), ckonsttemp = vec4(0.0f,0.0f,0.0f,0.0f);\n\n");

            if (Children.Count < 7)
            {
                w("vec3 _norm0 = normalize(Normal.xyz);\n\n");
                w("vec3 pos = vec3(clipPos.x,clipPos.y,Normal.w);\n");
            }
            else
            {
                w("vec3 _norm0 = normalize(vec3(uv4.w,uv5.w,uv6.w));\n\n");
                w("vec3 pos = vec3(uv0.w,uv1.w,uv7.w);\n");
            }

            w("vec4 mat, lacc;\nvec3 ldir, h;\nfloat dist, dist2, attn;\n");

            Object.tabs = tabs;
            tempShader += Object.GenerateLightingShader(I_PMATERIALS, I_PLIGHTS, "colors_", "colors_");

            //if (numTexgen < 7)
            //    w("clipPos = vec4(rawpos.x, rawpos.y, clipPos.z, clipPos.w);\n");
            //else
            //    w("vec4 clipPos = vec4(rawpos.x, rawpos.y, uv2.w, uv3.w);\n");

            // HACK to handle cases where the tex gen is not enabled
            if (numTexgen == 0)
            {
                w("vec3 uv0 = vec3(0.0f, 0.0f, 0.0f);\n");
            }
            else
            {
                for (int i = 0; i < numTexgen; ++i)
                {
                    // optional perspective divides
                    if (((MDL0MaterialRefNode)Children[i]).Projection == TexProjection.STQ)
                    {
                        w("if (uv{0}.z != 0.0f)\n", i);
                        w("    uv{0}.xy = uv{0}.xy / uv{0}.z;\n", i);
                    }

                    //w("uv{0}.xy = uv{0}.xy * "+I_TEXDIMS+"[{0}].zw;\n", i);
                }
            }

            for (int i = 0; i < IndirectShaderStages; i++)
            {
                if ((nIndirectStagesUsed & (1 << i)) != 0)
                {
                    uint texcoord = (ShaderNode._swapBlock._Value16.Value >> ((i + 1) * 3) & 7);

                    if (texcoord < numTexgen)
                    {
                        w("tempcoord = uv{0}.xy * " + I_INDTEXSCALE + "[{1}].{2};\n", texcoord, i / 2, (i & 1) != 0 ? "zw" : "xy");
                    }
                    else
                    {
                        w("tempcoord = vec2(0.0f, 0.0f);\n");
                    }

                    SampleTexture(String.Format("vec3 indtex{0}", i), "tempcoord", "abg", (ShaderNode._swapBlock._Value16.Value >> (i * 3) & 7));
                }
            }

            foreach (TEVStage stage in ShaderNode.Children)
            {
                if (stage.Index < ActiveShaderStages)
                {
                    w(stage.Write(this, Object));
                }
                else
                {
                    break;
                }
            }

            if (numStages > 0)
            {
                w("prev.rgb = {0};\n", tevCOutputTable[(int)((TEVStage)ShaderNode.Children[numStages - 1]).ColorRegister]);
                w("prev.a = {0};\n", tevAOutputTable[(int)((TEVStage)ShaderNode.Children[numStages - 1]).AlphaRegister]);
            }

            // emulation of unsigned 8 overflow when casting
            //w("prev = fract(4.0f + prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");

            if (Pretest == AlphaPretest.AlwaysFail)
            {
                w("ocol0 = vec4(0.0f);\n");

                //if (DepthTextureEnable)
                //    w("depth = 1.0f;\n");

                //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND)
                //    w("ocol1 = vec4(0.0f);\n");
                //else
                w("gl_FragColor = ocol0;\n");

                if (DepthTextureEnable)
                {
                    w("gl_FragDepth = depth;\n");
                }

                w("discard;\n");

                w("return;\n");
            }
            else
            {
                if (Pretest != AlphaPretest.AlwaysPass)
                {
                    WriteAlphaTest(PSGRenderMode);
                }

                //if (_fog != null && (_fog.Type != 0) || DepthTextureEnable)
                //{
                //    // the screen space depth value = far z + (clip z / clip w) * z range
                //    w("float zCoord = " + I_ZBIAS + "[1].x + (clipPos.z / clipPos.w) * " + I_ZBIAS + "[1].y;\n");
                //}

                //if (DepthTextureEnable)
                //{
                //    // use the texture input of the last texture stage (textemp), hopefully this has been read and is in correct format...
                //    if (/*bpmem.ztex2.op != ZTEXTURE_DISABLE && */!ZCompLoc && EnableDepthTest && EnableDepthUpdate)
                //    {
                //        //if (bpmem.ztex2.op == ZTEXTURE_ADD)
                //        //    Write("zCoord = dot("+I_ZBIAS+"[0].xyzw, textemp.xyzw) + "+I_ZBIAS+"[1].w + zCoord;\n");
                //        //else
                //            w("zCoord = dot(" + I_ZBIAS + "[0].xyzw, textemp.xyzw) + " + I_ZBIAS + "[1].w;\n");

                //        // scale to make result from frac correct
                //        w("zCoord = zCoord * (16777215.0f/16777216.0f);\n");
                //        w("zCoord = fract(zCoord);\n");
                //        w("zCoord = zCoord * (16777216.0f/16777215.0f);\n");
                //    }
                //    w("depth = zCoord;\n");
                //}

                //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_ALPHA_PASS)
                //    w("ocol0 = vec4(prev.rgb, " + I_ALPHA + ".a);\n");
                //else
                {
                    WriteFog();
                    w("ocol0 = prev;\n");
                }

                //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND)
                //{
                //    w("ocol1 = ocol0;\n");
                //    w("ocol0.a = " + I_ALPHA + ".a;\n");
                //}

                //if (DepthTextureEnable)
                //    w("gl_FragDepth = depth;\n");
                //if (PSGRenderMode != PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND)
                w("gl_FragColor = ocol0;\n");
            }
            w("}\n");

            return(tempShader);
        }
        private void ImportObject(MDL0ObjectNode node)
        {
            MDL0ObjectNode newNode = node.SoftCopy();
            if (node._vertexNode != null)
            {
                _internalModel.VertexGroup.AddChild(node._vertexNode);
                (newNode._vertexNode = (MDL0VertexNode)_internalModel.VertexGroup.Children[_internalModel._vertList.Count - 1])._objects.Add(newNode);
            }
            if (node.NormalNode != null)
            {
                _internalModel.NormalGroup.AddChild(node._normalNode);
                (newNode._normalNode = (MDL0NormalNode)_internalModel.NormalGroup.Children[_internalModel._normList.Count - 1])._objects.Add(newNode);
            }
            for (int i = 0; i < 8; i++)
                if (node._uvSet[i] != null)
                {
                    _internalModel.UVGroup.AddChild(node._uvSet[i]);
                    newNode._uvSet[i] = (MDL0UVNode)_internalModel.UVGroup.Children[_internalModel._uvList.Count - 1];
                    newNode._uvSet[i].Name = "#" + (_internalModel._uvList.Count - 1);
                    newNode._uvSet[i]._objects.Add(newNode);
                }

            for (int i = 0; i < 2; i++)
                if (node._colorSet[i] != null)
                {
                    _internalModel.ColorGroup.AddChild(node._colorSet[i]);
                    (newNode._colorSet[i] = (MDL0ColorNode)_internalModel.ColorGroup.Children[_internalModel._colorList.Count - 1])._objects.Add(newNode);
                }

            if (node.OpaMaterialNode != null)
            {
                _internalModel._matGroup.AddChild(node.OpaMaterialNode);
                newNode.OpaMaterialNode = (MDL0MaterialNode)_internalModel.MaterialGroup.Children[_internalModel._matList.Count - 1];

                _internalModel._shadGroup.AddChild(node.OpaMaterialNode._shader);
                newNode.OpaMaterialNode.ShaderNode = (MDL0ShaderNode)_internalModel.ShaderGroup.Children[_internalModel._shadList.Count - 1];

                foreach (MDL0MaterialRefNode r in newNode.OpaMaterialNode.Children)
                {
                    if (r._texture != null)
                        (r._texture = _internalModel.FindOrCreateTexture(r.TextureNode.Name))._references.Add(r);

                    if (r._palette != null)
                        (r._palette = _internalModel.FindOrCreatePalette(r.PaletteNode.Name))._references.Add(r);
                }
            }
            if (node.XluMaterialNode != null)
            {
                _internalModel._matGroup.AddChild(node.XluMaterialNode);
                newNode.XluMaterialNode = (MDL0MaterialNode)_internalModel.MaterialGroup.Children[_internalModel._matList.Count - 1];

                _internalModel._shadGroup.AddChild(node.XluMaterialNode._shader);
                newNode.XluMaterialNode.ShaderNode = (MDL0ShaderNode)_internalModel.ShaderGroup.Children[_internalModel._shadList.Count - 1];

                foreach (MDL0MaterialRefNode r in newNode.XluMaterialNode.Children)
                {
                    if (r._texture != null)
                        (r._texture = _internalModel.FindOrCreateTexture(r.TextureNode.Name))._references.Add(r);

                    if (r._palette != null)
                        (r._palette = _internalModel.FindOrCreatePalette(r.PaletteNode.Name))._references.Add(r);
                }
            }

            newNode._manager = node._manager;

            if (newNode.Weighted)
            {
                foreach (Vertex3 vert in newNode._manager._vertices)
                    if (vert._matrixNode != null)
                    {
                        //To do:
                        //Get difference between new and old influence matrices
                        //and add it to the weighted position
                        //to fit the mesh to the new bones if it doesn't already.

                        //Matrix m = vert.MatrixNode.Matrix;
                        //Matrix invm = vert.MatrixNode.InverseMatrix;
                        if (vert._matrixNode is Influence)
                        {
                            for (int i = 0; i < vert.MatrixNode.Weights.Count; i++)
                            {
                                MDL0BoneNode b = vert.MatrixNode.Weights[i].Bone;
                                if (b != null)
                                    vert.MatrixNode.Weights[i].Bone = _internalModel._boneGroup.FindChildByType(b.Name, true, ResourceType.MDL0Bone) as MDL0BoneNode;
                            }

                            vert.MatrixNode = _internalModel._influences.FindOrCreate((Influence)vert._matrixNode, true);
                        }
                        else
                            vert.MatrixNode = _internalModel.BoneGroup.FindChildByType(((MDL0BoneNode)vert.MatrixNode).Name, true, ResourceType.MDL0Bone) as IMatrixNode;

                        //Matrix m2 = vert.MatrixNode.Matrix * invm;
                        //vert.WeightedPosition = vert.WeightedPosition * m2;
                    }

                //foreach (Vertex3 vert in newNode._manager._vertices)
                //    vert.Unweight();
            }
            else if (newNode._matrixNode != null)
            {
                if (newNode._matrixNode is Influence)
                {
                    for (int i = 0; i < newNode.MatrixNode.Weights.Count; i++)
                        newNode.MatrixNode.Weights[i].Bone = _internalModel._boneGroup.FindChildByType(newNode.MatrixNode.Weights[i].Bone.Name, true, ResourceType.MDL0Bone) as MDL0BoneNode;

                    newNode.MatrixNode = _internalModel._influences.FindOrCreate((Influence)newNode._matrixNode, true);
                }
                else
                    newNode.MatrixNode = _internalModel.BoneGroup.FindChildByType(((MDL0BoneNode)newNode.MatrixNode).Name, true, ResourceType.MDL0Bone) as IMatrixNode;
            }

            newNode.RecalcIndices();
            newNode._bone = (MDL0BoneNode)_internalModel.BoneGroup.Children[0];
            newNode.Name = "polygon" + (_internalModel._objList.Count);
            newNode._rebuild = true;
            newNode.SignalPropertyChange();
            _internalModel._objGroup.AddChild(newNode);
        }
        public VertexAttributeFormat[] SetFormatList(MDL0ObjectNode polygon, ModelLinker linker)
        {
            List<VertexAttributeFormat> list = new List<VertexAttributeFormat>();
            VertexCodec vert = null;
            ColorCodec col = null;

            for (int i = 0; i < 12; i++)
            {
                if (polygon._manager._faceData[i] != null)
                    switch (i)
                    {
                        case 0: //Positions
                            if (linker._vertices != null && linker._vertices.Count != 0 && polygon._elementIndices[0] != -1)
                                if ((vert = linker._vertices[polygon._elementIndices[0]]) != null)
                                    list.Add(new VertexAttributeFormat(
                                        GXAttribute.Position,
                                        (GXCompType)vert._type,
                                        (GXCompCnt)(vert._hasZ ? 1 : 0),
                                        (byte)vert._scale));
                            break;
                        case 1: //Normals
                            vert = null;
                            if (linker._normals != null && linker._normals.Count != 0 && polygon._elementIndices[1] != -1)
                                if ((vert = linker._normals[polygon._elementIndices[1]]) != null)
                                    list.Add(new VertexAttributeFormat(
                                        GXAttribute.Normal,
                                        (GXCompType)vert._type,
                                        GXCompCnt.NrmXYZ,
                                        (byte)vert._scale));
                            break;
                        case 2: //Color 1
                        case 3: //Color 2
                            col = null;
                            if (linker._colors != null && linker._colors.Count != 0 && polygon._elementIndices[i] != -1 && (col = linker._colors[polygon._elementIndices[i]]) != null)
                                list.Add(new VertexAttributeFormat(
                                    (GXAttribute)((int)GXAttribute.Color0 + (i - 2)),
                                    (GXCompType)col._outType,
                                    (GXCompCnt)(col._hasAlpha ? 1 : 0),
                                    0));
                            break;
                        case 4: //Tex 1
                        case 5: //Tex 2
                        case 6: //Tex 3
                        case 7: //Tex 4
                        case 8: //Tex 5
                        case 9: //Tex 6
                        case 10: //Tex 7
                        case 11: //Tex 8
                            vert = null;
                            if (linker._uvs != null && linker._uvs.Count != 0 && polygon._elementIndices[i] != -1)
                                if ((vert = linker._uvs[polygon._elementIndices[i]]) != null)
                                    list.Add(new VertexAttributeFormat(
                                        (GXAttribute)((int)GXAttribute.Tex0 + (i - 4)),
                                        (GXCompType)vert._type,
                                        GXCompCnt.TexST,
                                        (byte)vert._scale));
                            break;
                    }
            }
            return list.ToArray();
        }
        internal void WritePrimitives(MDL0ObjectNode poly, MDL0Object* header)
        {
            _polygon = poly;

            VoidPtr start = header->PrimitiveData;
            VoidPtr address = header->PrimitiveData;
            FacepointAttribute[] desc = poly._descList;
            IMatrixNode[] cache = poly.Model._linker.NodeCache;

            foreach (PrimitiveGroup g in poly._primGroups)
            {
                if (!poly.Model._isImport && !poly._reOptimized)
                    g.RegroupNodes();

                g._nodes.Sort();
                g._offset = (uint)address - (uint)start;
                g._nodeOffsets.Clear();

                //Write matrix headers for linking weighted influences to points
                if (poly.Weighted)
                {
                    int index = 0;

                    //Texture Matrices
                    if (poly.HasTexMtx)
                        for (int i = 0; i < g._nodes.Count; i++)
                        {
                            *(byte*)address++ = 0x30;

                            g._nodeOffsets.Add(new NodeOffset((uint)(address - start) - g._offset, cache[g._nodes[i]]));

                            *(bushort*)address = g._nodes[i]; address += 2;
                            *(byte*)address++ = 0xB0;
                            *(byte*)address++ = (byte)(0x78 + (12 * index++));
                        }

                    index = 0;

                    //Position Matrices
                    for (int i = 0; i < g._nodes.Count; i++)
                    {
                        *(byte*)address++ = 0x20;

                        g._nodeOffsets.Add(new NodeOffset((uint)(address - start) - g._offset, cache[g._nodes[i]]));

                        *(bushort*)address = g._nodes[i]; address += 2;
                        *(byte*)address++ = 0xB0;
                        *(byte*)address++ = (byte)(12 * index++);
                    }

                    index = 0;

                    //Normal Matrices
                    for (int i = 0; i < g._nodes.Count; i++)
                    {
                        *(byte*)address++ = 0x28;

                        g._nodeOffsets.Add(new NodeOffset((uint)(address - start) - g._offset, cache[g._nodes[i]]));

                        *(bushort*)address = g._nodes[i]; address += 2;
                        *(byte*)address++ = 0x84;
                        *(byte*)address++ = (byte)(9 * index++);
                    }
                }

                if (poly.Model._isImport || poly._reOptimized)
                {
                    //Write strips first
                    if (g._tristrips.Count != 0)
                        foreach (PointTriangleStrip strip in g._tristrips)
                        {
                            *(PrimitiveHeader*)address = strip.Header; address += 3;
                            foreach (Facepoint f in strip._points)
                                WriteFacepoint(f, g, desc, ref address, poly);
                        }

                    //Write remaining triangles under a single list header
                    if (g._triangles.Count != 0)
                    {
                        *(PrimitiveHeader*)address = g.TriangleHeader; address += 3;
                        foreach (PointTriangle tri in g._triangles)
                        {
                            WriteFacepoint(tri._x, g, desc, ref address, poly);
                            WriteFacepoint(tri._y, g, desc, ref address, poly);
                            WriteFacepoint(tri._z, g, desc, ref address, poly);
                        }
                    }
                }
                else //Write the original primitives read from the model
                    for (int i = 0; i < g._headers.Count; i++)
                    {
                        *(PrimitiveHeader*)address = g._headers[i];
                        address += 3;
                        foreach (Facepoint point in g._points[i])
                            WriteFacepoint(point, g, desc, ref address, poly);
                    }
            }
        }
 internal void WriteFacepoint(Facepoint f, PrimitiveGroup g, FacepointAttribute[] desc, ref VoidPtr address, MDL0ObjectNode node)
 {
     foreach (FacepointAttribute d in desc)
         switch (d._attr)
         {
             case GXAttribute.PosNrmMtxId:
                 if (d._type == XFDataFormat.Direct)
                     *(byte*)address++ = (byte)(3 * g._nodes.IndexOf(f.NodeID));
                 break;
             case GXAttribute.Tex0MtxId:
             case GXAttribute.Tex1MtxId:
             case GXAttribute.Tex2MtxId:
             case GXAttribute.Tex3MtxId:
             case GXAttribute.Tex4MtxId:
             case GXAttribute.Tex5MtxId:
             case GXAttribute.Tex6MtxId:
             case GXAttribute.Tex7MtxId:
                 if (d._type == XFDataFormat.Direct)
                     *(byte*)address++ = (byte)(30 + (3 * g._nodes.IndexOf(f.NodeID)));
                 break;
             case GXAttribute.Position:
                 switch (d._type)
                 {
                     case XFDataFormat.Direct:
                         byte* addr = (byte*)address;
                         node.Model._linker._vertices[node._elementIndices[0]].Write(ref addr, f._vertexIndex);
                         address = addr;
                         break;
                     case XFDataFormat.Index8:
                         *(byte*)address++ = (byte)f._vertexIndex;
                         break;
                     case XFDataFormat.Index16:
                         *(bushort*)address = (ushort)f._vertexIndex;
                         address += 2;
                         break;
                 }
                 break;
             case GXAttribute.Normal:
                 switch (d._type)
                 {
                     case XFDataFormat.Direct:
                         byte* addr = (byte*)address;
                         node.Model._linker._normals[node._elementIndices[1]].Write(ref addr, f._normalIndex);
                         address = addr;
                         break;
                     case XFDataFormat.Index8:
                         *(byte*)address++ = (byte)f._normalIndex;
                         break;
                     case XFDataFormat.Index16:
                         *(bushort*)address = (ushort)f._normalIndex;
                         address += 2;
                         break;
                 }
                 break;
             case GXAttribute.Color0:
             case GXAttribute.Color1:
                 switch (d._type)
                 {
                     case XFDataFormat.Direct:
                         int index = (int)d._attr - 11;
                         byte* addr = (byte*)address;
                         node.Model._linker._colors[node._elementIndices[index + 2]].Write(ref addr, f._colorIndices[index]);
                         address = addr;
                         break;
                     case XFDataFormat.Index8:
                         if (_polygon._colorChanged[(int)d._attr - (int)GXAttribute.Color0] && _polygon._colorSet[(int)d._attr - (int)GXAttribute.Color0] != null)
                             *(byte*)address++ = 0;
                         else
                             *(byte*)address++ = (byte)f._colorIndices[(int)d._attr - 11];
                         break;
                     case XFDataFormat.Index16:
                         if (_polygon._colorChanged[(int)d._attr - (int)GXAttribute.Color0] && _polygon._colorSet[(int)d._attr - (int)GXAttribute.Color0] != null)
                             *(bushort*)address = 0;
                         else
                             *(bushort*)address = (ushort)f._colorIndices[(int)d._attr - 11];
                         address += 2;
                         break;
                 }
                 break;
             case GXAttribute.Tex0:
             case GXAttribute.Tex1:
             case GXAttribute.Tex2:
             case GXAttribute.Tex3:
             case GXAttribute.Tex4:
             case GXAttribute.Tex5:
             case GXAttribute.Tex6:
             case GXAttribute.Tex7:
                 switch (d._type)
                 {
                     case XFDataFormat.Direct:
                         int index = (int)d._attr - 13;
                         byte* addr = (byte*)address;
                         node.Model._linker._uvs[node._elementIndices[index + 4]].Write(ref addr, f._UVIndices[index]);
                         address = addr;
                         break;
                     case XFDataFormat.Index8:
                         *(byte*)address++ = (byte)f._UVIndices[(int)d._attr - 13];
                         break;
                     case XFDataFormat.Index16:
                         *(bushort*)address = (ushort)f._UVIndices[(int)d._attr - 13];
                         address += 2;
                         break;
                 }
                 break;
         }
 }
        public PrimitiveManager(MDL0Object* polygon, AssetStorage assets, IMatrixNode[] nodes, MDL0ObjectNode p)
        {
            _polygon = p;

            byte*[] pAssetList = new byte*[12];
            byte*[] pOutList = new byte*[12];
            int id;

            //This relies on the header being accurate!
            _indices = new UnsafeBuffer(2 * (_pointCount = polygon->_numVertices));
            _faceCount = polygon->_numFaces;

            //Compile decode script by reading the polygon def list
            //This sets how to read the facepoints
            ElementDescriptor desc = new ElementDescriptor(polygon);

            //Grab asset lists in sequential order.
            if ((id = polygon->_vertexId) >= 0 && desc.HasData[0] && assets.Assets[0] != null)
            {
                pOutList[0] = (byte*)(_faceData[0] = new UnsafeBuffer(12 * _pointCount)).Address;
                pAssetList[0] = (byte*)assets.Assets[0][id].Address;
            }
            if ((id = polygon->_normalId) >= 0 && desc.HasData[1] && assets.Assets[1] != null)
            {
                pOutList[1] = (byte*)(_faceData[1] = new UnsafeBuffer(12 * _pointCount)).Address;
                pAssetList[1] = (byte*)assets.Assets[1][id].Address;
            }
            for (int i = 0, x = 2; i < 2; i++, x++)
                if ((id = ((bshort*)polygon->_colorIds)[i]) >= 0 && desc.HasData[x] && assets.Assets[2] != null)
                {
                    pOutList[x] = (byte*)(_faceData[x] = new UnsafeBuffer(4 * _pointCount)).Address;
                    pAssetList[x] = (byte*)assets.Assets[2][id].Address;
                }
            for (int i = 0, x = 4; i < 8; i++, x++)
                if ((id = ((bshort*)polygon->_uids)[i]) >= 0 && desc.HasData[x] && assets.Assets[3] != null)
                {
                    pOutList[x] = (byte*)(_faceData[x] = new UnsafeBuffer(8 * _pointCount)).Address;
                    pAssetList[x] = (byte*)assets.Assets[3][id].Address;
                }

            //Extract primitives, using our descriptor and asset lists
            fixed (byte** pOut = pOutList)
            fixed (byte** pAssets = pAssetList)
                ExtractPrimitives(polygon, ref desc, pOut, pAssets);

            //Compile merged vertex list
            _vertices = desc.Finish((Vector3*)pAssetList[0], nodes);

            ushort* pIndex = (ushort*)_indices.Address;
            for (int x = 0; x < _pointCount; x++)
                if (pIndex[x] >= 0 && pIndex[x] < _vertices.Count)
                    _vertices[pIndex[x]]._faceDataIndices.Add(x);
        }
        internal Facepoint[] MergeInternalFaceData(MDL0ObjectNode poly)
        {
            Facepoint[] _facepoints = new Facepoint[_pointCount];

            ushort* pIndex = (ushort*)_indices.Address;
            for (int x = 0; x < 12; x++)
            {
                if (_faceData[x] == null && x != 0)
                    continue;

                switch (x)
                {
                    case 0:
                        for (int i = 0; i < _pointCount; i++)
                            if (_vertices.Count != 0)
                            {
                                Facepoint f = _facepoints[i] = new Facepoint() { _index = i };
                                f._vertexIndex = *pIndex++;
                                if (f._vertexIndex < _vertices.Count && f._vertexIndex >= 0)
                                    f._vertex = _vertices[f._vertexIndex];
                            }
                        break;
                    case 1:
                        Vector3* pIn1 = (Vector3*)_faceData[x].Address;
                        for (int i = 0; i < _pointCount; i++)
                            _facepoints[i]._normalIndex = Array.IndexOf(GetNormals(false), *pIn1++);
                        break;
                    case 2:
                    case 3:
                        RGBAPixel* pIn2 = (RGBAPixel*)_faceData[x].Address;
                        if (Collada._importOptions._useOneNode)
                            for (int i = 0; i < _pointCount; i++)
                                _facepoints[i]._colorIndices[x - 2] = Array.IndexOf(Collada._importOptions._singleColorNodeEntries, *pIn2++);
                        else
                            for (int i = 0; i < _pointCount; i++)
                                _facepoints[i]._colorIndices[x - 2] = Array.IndexOf(((MDL0ObjectNode)_polygon.Model._objList[_newClrObj[x - 2]])._manager.GetColors(x - 2, false), *pIn2++);
                        break;
                    default:
                        Vector2* pIn3 = (Vector2*)_faceData[x].Address;
                        for (int i = 0; i < _pointCount; i++)
                            _facepoints[i]._UVIndices[x - 4] = Array.IndexOf(GetUVs(x - 4, false), *pIn3++);
                        break;
                }
            }
            return _facepoints;
        }
        internal Facepoint[] MergeExternalFaceData(MDL0ObjectNode poly)
        {
            Facepoint[] _facepoints = new Facepoint[_pointCount];

            ushort* pIndex = (ushort*)_indices.Address;
            for (int x = 0; x < 12; x++)
            {
                if (poly._elementIndices[x] < 0 && x != 0)
                    continue;

                switch (x)
                {
                    case 0:
                        Vector3* pIn0 = (Vector3*)_faceData[x].Address;
                        for (int i = 0; i < _pointCount; i++)
                        {
                            Facepoint f = _facepoints[i] = new Facepoint() { _index = i };
                            if (_vertices.Count != 0)
                            {
                                ushort id = *pIndex++;
                                if (id < _vertices.Count && id >= 0)
                                    f._vertex = _vertices[id];
                                f._vertexIndex = f._vertex._facepoints[0]._vertexIndex;
                            }
                        }
                        break;
                    case 1:
                        Vector3* pIn1 = (Vector3*)_faceData[x].Address;
                        for (int i = 0; i < _pointCount; i++)
                            _facepoints[i]._normalIndex = Array.IndexOf(poly._normalNode.Normals, *pIn1++);
                        break;
                    case 2:
                    case 3:
                        RGBAPixel* pIn2 = (RGBAPixel*)_faceData[x].Address;
                        for (int i = 0; i < _pointCount; i++)
                            _facepoints[i]._colorIndices[x - 2] = Array.IndexOf(poly._colorSet[x - 2].Colors, *pIn2++);
                        break;
                    default:
                        Vector2* pIn3 = (Vector2*)_faceData[x].Address;
                        for (int i = 0; i < _pointCount; i++)
                            _facepoints[i]._UVIndices[x - 4] = Array.IndexOf(poly._uvSet[x - 4].Points, *pIn3++);
                        break;
                }
            }
            return _facepoints;
        }
        public void Reset()
        {
            lstObjects.BeginUpdate();
            lstObjects.Items.Clear();
            lstTextures.BeginUpdate();
            lstTextures.Items.Clear();

            _selectedPolygon = null;
            _targetObject = null;

            chkAllObj.CheckState = CheckState.Checked;
            chkAllTextures.CheckState = CheckState.Checked;

            if (TargetModel != null)
            {
                ResourceNode n;

                UpdateAnimations(TargetAnimType);

                if ((n = TargetModel.FindChild("Objects", false)) != null)
                    foreach (MDL0ObjectNode poly in n.Children)
                        lstObjects.Items.Add(poly, poly._render);

                if ((n = TargetModel.FindChild("Textures", false)) != null)
                    foreach (MDL0TextureNode tref in n.Children)
                        lstTextures.Items.Add(tref, tref.Enabled);
            }

            lstTextures.EndUpdate();
            lstObjects.EndUpdate();

            //VIS0Indices.Clear(); int i = 0;
            //foreach (MDL0PolygonNode p in lstObjects.Items)
            //{
            //    if (p._bone != null && p._bone.BoneIndex != 0)
            //        if (VIS0Indices.ContainsKey(p._bone.Name))
            //            if (!VIS0Indices[p._bone.Name].Contains(i))
            //                VIS0Indices[p._bone.Name].Add(i); else { }
            //        else VIS0Indices.Add(p._bone.Name, new List<int> { i });
            //    i++;
            //}
        }
Example #16
0
        internal string Write(MDL0MaterialNode mat, MDL0ObjectNode obj)
        {
            MDL0ShaderNode shader = ((MDL0ShaderNode)Parent);

            string stage = "";

            //Get the texture coordinate to use
            int texcoord = (int)TextureCoord;

            //Do we need to use the coordinates?
            bool bHasTexCoord = texcoord < mat.Children.Count;

            //Is there an indirect stage? (CMD is not 0)
            //Is active ==
            //FB true
            //LB false
            //TW max
            //SW max
            //M max
            //0001 0111 1111 1110 0000 0000 = 0x17FE00
            bool bHasIndStage = IndirectActive && bt < mat.IndirectShaderStages;

            // HACK to handle cases where the tex gen is not enabled
            if (!bHasTexCoord)
            {
                texcoord = 0;
            }

            stage += String.Format("//TEV stage {0}\n\n", Index);

            //Add indirect support later

            if (bHasIndStage)
            {
                stage += String.Format("// indirect op\n");

                //Perform the indirect op on the incoming regular coordinates using indtex as the offset coords
                if (Alpha != IndTexAlphaSel.Off)
                {
                    stage += String.Format("alphabump = indtex{0}.{1} {2};\n",
                                           (int)TexStage,
                                           (int)Alpha,
                                           (int)TexFormat);
                }

                //Format
                stage += String.Format("vec3 indtevcrd{0} = indtex{1} * {2};\n", Index, (int)TexStage, (int)TexFormat);

                //Bias
                if (Bias != IndTexBiasSel.None)
                {
                    stage += String.Format("indtevcrd{0}.{1} += {2};\n", Index, MDL0MaterialNode.tevIndBiasField[(int)Bias], MDL0MaterialNode.tevIndBiasAdd[(int)TexFormat]);
                }

                //Multiply by offset matrix and scale
                if (Matrix != 0)
                {
                    if ((int)Matrix <= 3)
                    {
                        int mtxidx = 2 * ((int)Matrix - 1);
                        stage += String.Format("vec2 indtevtrans{0} = vec2(dot(" + MDL0MaterialNode.I_INDTEXMTX + "[{1}].xyz, indtevcrd{2}), dot(" + MDL0MaterialNode.I_INDTEXMTX + "[{3}].xyz, indtevcrd{4}));\n",
                                               Index, mtxidx, Index, mtxidx + 1, Index);
                    }
                    else if ((int)Matrix < 5 && (int)Matrix <= 7 && bHasTexCoord)
                    {
                        //S
                        int mtxidx = 2 * ((int)Matrix - 5);
                        stage += String.Format("vec2 indtevtrans{0} = " + MDL0MaterialNode.I_INDTEXMTX + "[{1}].ww * uv{2}.xy * indtevcrd{3}.xx;\n", Index, mtxidx, texcoord, Index);
                    }
                    else if ((int)Matrix < 9 && (int)Matrix <= 11 && bHasTexCoord)
                    {
                        //T
                        int mtxidx = 2 * ((int)Matrix - 9);
                        stage += String.Format("vec2 indtevtrans{0} = " + MDL0MaterialNode.I_INDTEXMTX + "[{1}].ww * uv{2}.xy * indtevcrd{3}.yy;\n", Index, mtxidx, texcoord, Index);
                    }
                    else
                    {
                        stage += String.Format("vec2 indtevtrans{0} = 0;\n", Index);
                    }
                }
                else
                {
                    stage += String.Format("vec2 indtevtrans{0} = 0;\n", Index);
                }

                #region Wrapping

                // wrap S
                if (S_Wrap == IndTexWrap.NoWrap)
                {
                    stage += String.Format("wrappedcoord.x = uv{0}.x;\n", texcoord);
                }
                else if (S_Wrap == IndTexWrap.Wrap0)
                {
                    stage += String.Format("wrappedcoord.x = 0.0f;\n");
                }
                else
                {
                    stage += String.Format("wrappedcoord.x = fmod( uv{0}.x, {1} );\n", texcoord, MDL0MaterialNode.tevIndWrapStart[(int)S_Wrap]);
                }

                // wrap T
                if (T_Wrap == IndTexWrap.NoWrap)
                {
                    stage += String.Format("wrappedcoord.y = uv{0}.y;\n", texcoord);
                }
                else if (T_Wrap == IndTexWrap.Wrap0)
                {
                    stage += String.Format("wrappedcoord.y = 0.0f;\n");
                }
                else
                {
                    stage += String.Format("wrappedcoord.y = fmod( uv{0}.y, {1} );\n", texcoord, MDL0MaterialNode.tevIndWrapStart[(int)T_Wrap]);
                }

                stage += String.Format("tevcoord.xy {0}= wrappedcoord + indtevtrans{1};\n", UsePrevStage ? "+" : "", Index);

                #endregion
            }

            //Check if we need to use Alpha
            if (ColorSelectionA == ColorArg.RasterAlpha || ColorSelectionA == ColorArg.RasterColor ||
                ColorSelectionB == ColorArg.RasterAlpha || ColorSelectionB == ColorArg.RasterColor ||
                ColorSelectionC == ColorArg.RasterAlpha || ColorSelectionC == ColorArg.RasterColor ||
                ColorSelectionD == ColorArg.RasterAlpha || ColorSelectionD == ColorArg.RasterColor ||
                AlphaSelectionA == AlphaArg.RasterAlpha || AlphaSelectionB == AlphaArg.RasterAlpha ||
                AlphaSelectionC == AlphaArg.RasterAlpha || AlphaSelectionD == AlphaArg.RasterAlpha)
            {
                string rasswap = shader.swapModeTable[rswap];
                stage += String.Format("rastemp = {0}.{1};\n", MDL0MaterialNode.tevRasTable[(int)ColorChannel], rasswap);
                stage += String.Format("crastemp = fract(rastemp * (255.0f/256.0f)) * (256.0f/255.0f);\n");
            }

            if (TextureEnabled)
            {
                if (!bHasIndStage)        //Calculate tevcoord
                {
                    if (bHasTexCoord)
                    {
                        stage += String.Format("tevcoord.xy = uv{0}.xy;\n", texcoord);
                    }
                    else
                    {
                        stage += String.Format("tevcoord.xy = vec2(0.0f, 0.0f);\n");
                    }
                }

                string texswap = shader.swapModeTable[tswap];
                int    texmap  = (int)TextureMapID;

                stage += String.Format("{0} = texture2D(samp{1}, {2}.xy" /* + " * " + MDL0MaterialNode.I_TEXDIMS + "[{3}].xy" */ + ").{4};\n", "textemp", texmap, "tevcoord", texmap, texswap);
            }
            else
            {
                stage += String.Format("textemp = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n");
            }

            //Check if we need to use Konstant Colors
            if (ColorSelectionA == ColorArg.KonstantColorSelection ||
                ColorSelectionB == ColorArg.KonstantColorSelection ||
                ColorSelectionC == ColorArg.KonstantColorSelection ||
                ColorSelectionD == ColorArg.KonstantColorSelection ||
                AlphaSelectionA == AlphaArg.KonstantAlphaSelection ||
                AlphaSelectionB == AlphaArg.KonstantAlphaSelection ||
                AlphaSelectionC == AlphaArg.KonstantAlphaSelection ||
                AlphaSelectionD == AlphaArg.KonstantAlphaSelection)
            {
                int kc = (int)KonstantColorSelection;
                int ka = (int)KonstantAlphaSelection;

                stage += String.Format("konsttemp = vec4({0}, {1});\n", MDL0MaterialNode.tevKSelTableC[kc], MDL0MaterialNode.tevKSelTableA[ka]);

                if (kc > 7 || ka > 7)
                {
                    stage += String.Format("ckonsttemp = fract(konsttemp * (255.0f/256.0f)) * (256.0f/255.0f);\n");
                }
                else
                {
                    stage += String.Format("ckonsttemp = konsttemp;\n");
                }
            }

            if (ColorSelectionA == ColorArg.PreviousColor || ColorSelectionA == ColorArg.PreviousAlpha ||
                ColorSelectionB == ColorArg.PreviousColor || ColorSelectionB == ColorArg.PreviousAlpha ||
                ColorSelectionC == ColorArg.PreviousColor || ColorSelectionC == ColorArg.PreviousAlpha ||
                AlphaSelectionA == AlphaArg.PreviousAlpha || AlphaSelectionB == AlphaArg.PreviousAlpha || AlphaSelectionC == AlphaArg.PreviousAlpha)
            {
                stage += String.Format("cprev = fract(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");
            }

            if (ColorSelectionA == ColorArg.Color0 || ColorSelectionA == ColorArg.Alpha0 ||
                ColorSelectionB == ColorArg.Color0 || ColorSelectionB == ColorArg.Alpha0 ||
                ColorSelectionC == ColorArg.Color0 || ColorSelectionC == ColorArg.Alpha0 ||
                AlphaSelectionA == AlphaArg.Alpha0 || AlphaSelectionB == AlphaArg.Alpha0 || AlphaSelectionC == AlphaArg.Alpha0)
            {
                stage += String.Format("cc0 = fract(c0 * (255.0f/256.0f)) * (256.0f/255.0f);\n");
            }

            if (ColorSelectionA == ColorArg.Color1 || ColorSelectionA == ColorArg.Alpha1 ||
                ColorSelectionB == ColorArg.Color1 || ColorSelectionB == ColorArg.Alpha1 ||
                ColorSelectionC == ColorArg.Color1 || ColorSelectionC == ColorArg.Alpha1 ||
                AlphaSelectionA == AlphaArg.Alpha1 || AlphaSelectionB == AlphaArg.Alpha1 || AlphaSelectionC == AlphaArg.Alpha1)
            {
                stage += String.Format("cc1 = fract(c1 * (255.0f/256.0f)) * (256.0f/255.0f);\n");
            }

            if (ColorSelectionA == ColorArg.Color2 || ColorSelectionA == ColorArg.Alpha2 ||
                ColorSelectionB == ColorArg.Color2 || ColorSelectionB == ColorArg.Alpha2 ||
                ColorSelectionC == ColorArg.Color2 || ColorSelectionC == ColorArg.Alpha2 ||
                AlphaSelectionA == AlphaArg.Alpha2 || AlphaSelectionB == AlphaArg.Alpha2 || AlphaSelectionC == AlphaArg.Alpha2)
            {
                stage += String.Format("cc2 = fract(c2 * (255.0f/256.0f)) * (256.0f/255.0f);\n");
            }

            #region Color Channel

            stage += String.Format("// color combine\n{0} = ", MDL0MaterialNode.tevCOutputTable[(int)ColorRegister]);

            if (ColorClamp)
            {
                stage += "saturate(";
            }

            if (ColorScale > TevScale.MultiplyBy1)
            {
                stage += String.Format("{0} * (", MDL0MaterialNode.tevScaleTable[(int)ColorScale]);
            }

            if (!(ColorSelectionD == ColorArg.Zero && ColorSubtract == false))
            {
                stage += String.Format("{0} {1} ", MDL0MaterialNode.tevCInputTable[(int)ColorSelectionD], MDL0MaterialNode.tevOpTable[ColorSubtract ? 1 : 0]);
            }

            if (ColorSelectionA == ColorSelectionB)
            {
                stage += String.Format("{0}",
                                       MDL0MaterialNode.tevCInputTable[(int)ColorSelectionA + 16]);
            }
            else if (ColorSelectionC == ColorArg.Zero)
            {
                stage += String.Format("{0}",
                                       MDL0MaterialNode.tevCInputTable[(int)ColorSelectionA + 16]);
            }
            else if (ColorSelectionC == ColorArg.One)
            {
                stage += String.Format("{0}",
                                       MDL0MaterialNode.tevCInputTable[(int)ColorSelectionB + 16]);
            }
            else if (ColorSelectionA == ColorArg.Zero)
            {
                stage += String.Format("{0} * {1}",
                                       MDL0MaterialNode.tevCInputTable[(int)ColorSelectionB + 16],
                                       MDL0MaterialNode.tevCInputTable[(int)ColorSelectionC + 16]);
            }
            else if (ColorSelectionB == ColorArg.Zero)
            {
                stage += String.Format("{0} * (vec3(1.0f, 1.0f, 1.0f) - {1})",
                                       MDL0MaterialNode.tevCInputTable[(int)ColorSelectionA + 16],
                                       MDL0MaterialNode.tevCInputTable[(int)ColorSelectionC + 16]);
            }
            else
            {
                stage += String.Format("lerp({0}, {1}, {2})",
                                       MDL0MaterialNode.tevCInputTable[(int)ColorSelectionA + 16],
                                       MDL0MaterialNode.tevCInputTable[(int)ColorSelectionB + 16],
                                       MDL0MaterialNode.tevCInputTable[(int)ColorSelectionC + 16]);
            }

            stage += MDL0MaterialNode.tevBiasTable[(int)ColorBias];

            if (ColorClamp)
            {
                stage += ")";
            }
            if (ColorScale > TevScale.MultiplyBy1)
            {
                stage += ")";
            }

            #endregion

            stage += ";\n";

            #region Alpha Channel

            stage += String.Format("// alpha combine\n{0} = ", MDL0MaterialNode.tevAOutputTable[(int)AlphaRegister]);

            if (AlphaClamp)
            {
                stage += "saturate(";
            }

            if (AlphaScale > TevScale.MultiplyBy1)
            {
                stage += String.Format("{0} * (", MDL0MaterialNode.tevScaleTable[(int)AlphaScale]);
            }

            if (!(AlphaSelectionD == AlphaArg.Zero && AlphaSubtract == false))
            {
                stage += String.Format("{0}.a {1} ", MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionD], MDL0MaterialNode.tevOpTable[AlphaSubtract ? 1 : 0]);
            }

            if (AlphaSelectionA == AlphaSelectionB)
            {
                stage += String.Format("{0}.a",
                                       MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionA + 8]);
            }
            else if (AlphaSelectionC == AlphaArg.Zero)
            {
                stage += String.Format("{0}.a",
                                       MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionA + 8]);
            }
            else if (AlphaSelectionA == AlphaArg.Zero)
            {
                stage += String.Format("{0}.a * {1}.a",
                                       MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionB + 8],
                                       MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionC + 8]);
            }
            else if (AlphaSelectionB == AlphaArg.Zero)
            {
                stage += String.Format("{0}.a * (1.0f - {1}.a)",
                                       MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionA + 8],
                                       MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionC + 8]);
            }
            else
            {
                stage += String.Format("lerp({0}.a, {1}.a, {2}.a)",
                                       MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionA + 8],
                                       MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionB + 8],
                                       MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionC + 8]);
            }

            stage += MDL0MaterialNode.tevBiasTable[(int)AlphaBias];

            if (AlphaClamp)
            {
                stage += ")";
            }
            if (AlphaScale > TevScale.MultiplyBy1)
            {
                stage += ")";
            }

            #endregion

            stage += ";\n\n//TEV stage " + Index + " done\n\n";

            return(stage);
        }
        private void GetBaseInfluence()
        {
            ResourceNode[] boneCache = _externalModel._linker.BoneCache;
            if ((_node = (MDL0ObjectNode)comboBox1.SelectedItem).Weighted)
            {
                int least = int.MaxValue;
                foreach (IMatrixNode inf in _node.Influences)
                    if (inf is MDL0BoneNode && ((MDL0BoneNode)inf).BoneIndex < least)
                        least = ((MDL0BoneNode)inf).BoneIndex;

                if (least != int.MaxValue)
                {
                    MDL0BoneNode temp = (MDL0BoneNode)boneCache[least];
                    _baseInf = (IMatrixNode)temp.Parent;
                }
            }
            else _baseInf = _node.MatrixNode;

            if (_baseInf is Influence)
            {
                label2.Hide();
                comboBox2.Hide();
            }
            else if (_baseInf is MDL0BoneNode)
            {
                label2.Show();
                comboBox2.Show();
            }

            baseBone.Text = _baseInf.ToString();

            if (comboBox3.SelectedIndex == 0 && _baseInf is MDL0BoneNode)
            {
                int i = 0;
                foreach (MDL0BoneNode s in comboBox2.Items)
                {
                    if (s.Name == baseBone.Text)
                    {
                        comboBox2.SelectedIndex = i;
                        break;
                    }
                    i++;
                }
            }

            modelPanel1.AddTarget(_node);
            Vector3 min, max;
            _node.GetBox(out min, out max);
            modelPanel1.SetCamWithBox(min, max);
        }
        public FacepointAttribute[] SetVertexDescList(MDL0ObjectNode obj, params bool[] forceDirect)
        {
            //Everything is set in the order the facepoint is written!

            ModelLinker linker = obj.Model._linker;
            short[] indices = obj._elementIndices;
            XFDataFormat fmt;

            //Create new command list
            List<FacepointAttribute> list = new List<FacepointAttribute>();

            obj._arrayFlags._data = 0;

            if (obj.Weighted)
            {
                list.Add(new FacepointAttribute(GXAttribute.PosNrmMtxId, XFDataFormat.Direct));
                obj._fpStride++;
                obj._arrayFlags.HasPosMatrix = true;

                //There are no texture matrices without a position/normal matrix also
                for (int i = 0; i < 8; i++)
                    if (obj.HasTextureMatrix[i])
                    {
                        list.Add(new FacepointAttribute((GXAttribute)(i + 1), XFDataFormat.Direct));
                        obj._fpStride++;
                        obj._arrayFlags.SetHasTexMatrix(i, true);
                    }
            }
            if (indices[0] > -1 && _faceData[0] != null) //Positions
            {
                obj._arrayFlags.HasPositions = true;
                fmt = (forceDirect != null && forceDirect.Length > 0 && forceDirect[0] == true) ? XFDataFormat.Direct : (XFDataFormat)(GetVertices(false).Length > byte.MaxValue ? 3 : 2);

                list.Add(new FacepointAttribute(GXAttribute.Position, fmt));
                obj._fpStride += fmt == XFDataFormat.Direct ? linker._vertices[obj._elementIndices[0]]._dstStride : (int)fmt - 1;
            }
            if (indices[1] > -1 && _faceData[1] != null) //Normals
            {
                obj._arrayFlags.HasNormals = true;

                fmt = (forceDirect != null && forceDirect.Length > 1 && forceDirect[1] == true) ? XFDataFormat.Direct : (XFDataFormat)(GetNormals(false).Length > byte.MaxValue ? 3 : 2);

                list.Add(new FacepointAttribute(GXAttribute.Normal, fmt));
                obj._fpStride += fmt == XFDataFormat.Direct ? linker._normals[obj._elementIndices[1]]._dstStride : (int)fmt - 1;
            }
            for (int i = 2; i < 4; i++)
                if (indices[i] > -1 && (_faceData[i] != null || obj._colorChanged[i - 2])) //Colors
                {
                    obj._arrayFlags.SetHasColor(i - 2, true);

                    if (obj._colorChanged[i - 2])
                        fmt = XFDataFormat.Index8;
                    else
                        fmt = (forceDirect != null && forceDirect.Length > i && forceDirect[i] == true) ? XFDataFormat.Direct : (XFDataFormat)(GetColors(i - 2, false).Length > byte.MaxValue ? 3 : 2);

                    list.Add(new FacepointAttribute((GXAttribute)(i + 9), fmt));
                    obj._fpStride += fmt == XFDataFormat.Direct ? linker._colors[obj._elementIndices[i]]._dstStride : (int)fmt - 1;
                }
            for (int i = 4; i < 12; i++)
                if (indices[i] > -1 && _faceData[i] != null) //UVs
                {
                    obj._arrayFlags.SetHasUVs(i - 4, true);

                    fmt = (forceDirect != null && forceDirect.Length > i && forceDirect[i] == true) ? XFDataFormat.Direct : (XFDataFormat)(GetUVs(i - 4, false).Length > byte.MaxValue ? 3 : 2);

                    list.Add(new FacepointAttribute((GXAttribute)(i + 9), fmt));
                    obj._fpStride += fmt == XFDataFormat.Direct ? linker._uvs[obj._elementIndices[i]]._dstStride : (int)fmt - 1;
                }

            return list.ToArray();
        }
 public ObjectOptimization(MDL0ObjectNode o)
 {
     _object = o;
     _facepoints = _object._manager.MergeExternalFaceData(_object);
     _pointCount = _object._numFacepoints;
     _faceCount = _object._numFaces;
 }
        //This sets up how to read the facepoints that are going to be written.
        public void WriteVertexDescriptor(FacepointAttribute[] attributes, MDL0ObjectNode obj)
        {
            XFNormalFormat nrmFmt = XFNormalFormat.None;
            int numColors = 0;
            int numUVs = 0;

            uint posNrmMtxId = 0;
            uint texMtxIdMask = 0;
            uint pos = 0;
            uint nrm = 0;
            uint col0 = 0;
            uint col1 = 0;
            uint tex0 = 0;
            uint tex1 = 0;
            uint tex2 = 0;
            uint tex3 = 0;
            uint tex4 = 0;
            uint tex5 = 0;
            uint tex6 = 0;
            uint tex7 = 0;

            foreach (FacepointAttribute attrPtr in attributes)
                switch (attrPtr._attr)
                {
                    case GXAttribute.PosNrmMtxId:
                        posNrmMtxId = (uint)attrPtr._type;
                        break;

                    case GXAttribute.Tex0MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~1) | ((uint)attrPtr._type << 0);
                        break;
                    case GXAttribute.Tex1MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~2) | ((uint)attrPtr._type << 1);
                        break;
                    case GXAttribute.Tex2MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~4) | ((uint)attrPtr._type << 2);
                        break;
                    case GXAttribute.Tex3MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~8) | ((uint)attrPtr._type << 3);
                        break;
                    case GXAttribute.Tex4MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~16) | ((uint)attrPtr._type << 4);
                        break;
                    case GXAttribute.Tex5MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~32) | ((uint)attrPtr._type << 5);
                        break;
                    case GXAttribute.Tex6MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~64) | ((uint)attrPtr._type << 6);
                        break;
                    case GXAttribute.Tex7MtxId:
                        texMtxIdMask = (uint)(texMtxIdMask & ~128) | ((uint)attrPtr._type << 7);
                        break;

                    case GXAttribute.Position:
                        pos = (uint)attrPtr._type;
                        break;

                    case GXAttribute.Normal:
                        if (attrPtr._type != XFDataFormat.None)
                        {
                            nrm = (uint)attrPtr._type;
                            nrmFmt = XFNormalFormat.XYZ;
                        }
                        break;

                    case GXAttribute.NBT:
                        if (attrPtr._type != XFDataFormat.None)
                        {
                            nrm = (uint)attrPtr._type;
                            nrmFmt = XFNormalFormat.NBT;
                        }
                        break;

                    case GXAttribute.Color0: col0 = (uint)attrPtr._type; numColors += (col0 != 0 ? 1 : 0); break;
                    case GXAttribute.Color1: col1 = (uint)attrPtr._type; numColors += (col1 != 0 ? 1 : 0); break;

                    case GXAttribute.Tex0: tex0 = (uint)attrPtr._type; numUVs += (tex0 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex1: tex1 = (uint)attrPtr._type; numUVs += (tex1 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex2: tex2 = (uint)attrPtr._type; numUVs += (tex2 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex3: tex3 = (uint)attrPtr._type; numUVs += (tex3 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex4: tex4 = (uint)attrPtr._type; numUVs += (tex4 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex5: tex5 = (uint)attrPtr._type; numUVs += (tex5 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex6: tex6 = (uint)attrPtr._type; numUVs += (tex6 != 0 ? 1 : 0); break;
                    case GXAttribute.Tex7: tex7 = (uint)attrPtr._type; numUVs += (tex7 != 0 ? 1 : 0); break;
                }

            obj._vertexFormat._lo = ShiftVtxLo(posNrmMtxId, texMtxIdMask, pos, nrm, col0, col1);
            obj._vertexFormat._hi = ShiftVtxHi(tex0, tex1, tex2, tex3, tex4, tex5, tex6, tex7);
            obj._vertexSpecs = new XFVertexSpecs(numColors, numUVs, nrmFmt);
        }
Example #21
0
        internal string Write(MDL0MaterialNode mat, MDL0ObjectNode obj)
        {
            MDL0ShaderNode shader = ((MDL0ShaderNode)Parent);

            string stage = "";

            //Get the texture coordinate to use
            int texcoord = (int)TextureCoord;

            //Do we need to use the coordinates?
            bool bHasTexCoord = texcoord < mat.Children.Count;

            //Is there an indirect stage? (CMD is not 0)
            //Is active ==
            //FB true
            //LB false
            //TW max
            //SW max
            //M max
            //0001 0111 1111 1110 0000 0000 = 0x17FE00
            bool bHasIndStage = IndirectActive && bt < mat.IndirectShaderStages;

            // HACK to handle cases where the tex gen is not enabled
            if (!bHasTexCoord)
                texcoord = 0;

            stage += String.Format("//TEV stage {0}\n\n", Index);

            //Add indirect support later

            if (bHasIndStage)
            {
                stage += String.Format("// indirect op\n");

                //Perform the indirect op on the incoming regular coordinates using indtex as the offset coords
                if (Alpha != IndTexAlphaSel.Off)
                    stage += String.Format("alphabump = indtex{0}.{1} {2};\n",
                            (int)TexStage,
                            (int)Alpha,
                            (int)TexFormat);

                //Format
                stage += String.Format("vec3 indtevcrd{0} = indtex{1} * {2};\n", Index, (int)TexStage, (int)TexFormat);

                //Bias
                if (Bias != IndTexBiasSel.None)
                    stage += String.Format("indtevcrd{0}.{1} += {2};\n", Index, MDL0MaterialNode.tevIndBiasField[(int)Bias], MDL0MaterialNode.tevIndBiasAdd[(int)TexFormat]);

                //Multiply by offset matrix and scale
                if (Matrix != 0)
                {
                    if ((int)Matrix <= 3)
                    {
                        int mtxidx = 2 * ((int)Matrix - 1);
                        stage += String.Format("vec2 indtevtrans{0} = vec2(dot(" + MDL0MaterialNode.I_INDTEXMTX + "[{1}].xyz, indtevcrd{2}), dot(" + MDL0MaterialNode.I_INDTEXMTX + "[{3}].xyz, indtevcrd{4}));\n",
                            Index, mtxidx, Index, mtxidx + 1, Index);
                    }
                    else if ((int)Matrix < 5 && (int)Matrix <= 7 && bHasTexCoord)
                    {
                        //S
                        int mtxidx = 2 * ((int)Matrix - 5);
                        stage += String.Format("vec2 indtevtrans{0} = " + MDL0MaterialNode.I_INDTEXMTX + "[{1}].ww * uv{2}.xy * indtevcrd{3}.xx;\n", Index, mtxidx, texcoord, Index);
                    }
                    else if ((int)Matrix < 9 && (int)Matrix <= 11 && bHasTexCoord)
                    {
                        //T
                        int mtxidx = 2 * ((int)Matrix - 9);
                        stage += String.Format("vec2 indtevtrans{0} = " + MDL0MaterialNode.I_INDTEXMTX + "[{1}].ww * uv{2}.xy * indtevcrd{3}.yy;\n", Index, mtxidx, texcoord, Index);
                    }
                    else
                        stage += String.Format("vec2 indtevtrans{0} = 0;\n", Index);
                }
                else
                    stage += String.Format("vec2 indtevtrans{0} = 0;\n", Index);

                #region Wrapping

                // wrap S
                if (S_Wrap == IndTexWrap.NoWrap)
                    stage += String.Format("wrappedcoord.x = uv{0}.x;\n", texcoord);
                else if (S_Wrap == IndTexWrap.Wrap0)
                    stage += String.Format("wrappedcoord.x = 0.0f;\n");
                else
                    stage += String.Format("wrappedcoord.x = fmod( uv{0}.x, {1} );\n", texcoord, MDL0MaterialNode.tevIndWrapStart[(int)S_Wrap]);

                // wrap T
                if (T_Wrap == IndTexWrap.NoWrap)
                    stage += String.Format("wrappedcoord.y = uv{0}.y;\n", texcoord);
                else if (T_Wrap == IndTexWrap.Wrap0)
                    stage += String.Format("wrappedcoord.y = 0.0f;\n");
                else
                    stage += String.Format("wrappedcoord.y = fmod( uv{0}.y, {1} );\n", texcoord, MDL0MaterialNode.tevIndWrapStart[(int)T_Wrap]);

                stage += String.Format("tevcoord.xy {0}= wrappedcoord + indtevtrans{1};\n", UsePrevStage ? "+" : "", Index);

                #endregion
            }

            //Check if we need to use Alpha
            if (ColorSelectionA == ColorArg.RasterAlpha || ColorSelectionA == ColorArg.RasterColor
             || ColorSelectionB == ColorArg.RasterAlpha || ColorSelectionB == ColorArg.RasterColor
             || ColorSelectionC == ColorArg.RasterAlpha || ColorSelectionC == ColorArg.RasterColor
             || ColorSelectionD == ColorArg.RasterAlpha || ColorSelectionD == ColorArg.RasterColor
             || AlphaSelectionA == AlphaArg.RasterAlpha || AlphaSelectionB == AlphaArg.RasterAlpha
             || AlphaSelectionC == AlphaArg.RasterAlpha || AlphaSelectionD == AlphaArg.RasterAlpha)
            {
                string rasswap = shader.swapModeTable[rswap];
                stage += String.Format("rastemp = {0}.{1};\n", MDL0MaterialNode.tevRasTable[(int)ColorChannel], rasswap);
                stage += String.Format("crastemp = fract(rastemp * (255.0f/256.0f)) * (256.0f/255.0f);\n");
            }

            if (TextureEnabled)
            {
                if(!bHasIndStage) //Calculate tevcoord
                    if(bHasTexCoord)
                        stage += String.Format("tevcoord.xy = uv{0}.xy;\n", texcoord);
                    else
                        stage += String.Format("tevcoord.xy = vec2(0.0f, 0.0f);\n");

                string texswap = shader.swapModeTable[tswap];
                int texmap = (int)TextureMapID;

                stage += String.Format("{0} = texture2D(samp{1}, {2}.xy"/* + " * " + MDL0MaterialNode.I_TEXDIMS + "[{3}].xy" */+ ").{4};\n", "textemp", texmap, "tevcoord", texmap, texswap);
            }
            else
                stage += String.Format("textemp = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n");

            //Check if we need to use Konstant Colors
            if (ColorSelectionA == ColorArg.KonstantColorSelection ||
                ColorSelectionB == ColorArg.KonstantColorSelection ||
                ColorSelectionC == ColorArg.KonstantColorSelection ||
                ColorSelectionD == ColorArg.KonstantColorSelection ||
                AlphaSelectionA == AlphaArg.KonstantAlphaSelection ||
                AlphaSelectionB == AlphaArg.KonstantAlphaSelection ||
                AlphaSelectionC == AlphaArg.KonstantAlphaSelection ||
                AlphaSelectionD == AlphaArg.KonstantAlphaSelection)
            {
                int kc = (int)KonstantColorSelection;
                int ka = (int)KonstantAlphaSelection;

                stage += String.Format("konsttemp = vec4({0}, {1});\n", MDL0MaterialNode.tevKSelTableC[kc], MDL0MaterialNode.tevKSelTableA[ka]);

                if(kc > 7 || ka > 7)
                    stage += String.Format("ckonsttemp = fract(konsttemp * (255.0f/256.0f)) * (256.0f/255.0f);\n");
                else
                    stage += String.Format("ckonsttemp = konsttemp;\n");
            }

            if (ColorSelectionA == ColorArg.PreviousColor || ColorSelectionA == ColorArg.PreviousAlpha
             || ColorSelectionB == ColorArg.PreviousColor || ColorSelectionB == ColorArg.PreviousAlpha
             || ColorSelectionC == ColorArg.PreviousColor || ColorSelectionC == ColorArg.PreviousAlpha
             || AlphaSelectionA == AlphaArg.PreviousAlpha || AlphaSelectionB == AlphaArg.PreviousAlpha || AlphaSelectionC == AlphaArg.PreviousAlpha)
                stage += String.Format("cprev = fract(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");

            if (ColorSelectionA == ColorArg.Color0 || ColorSelectionA == ColorArg.Alpha0
             || ColorSelectionB == ColorArg.Color0 || ColorSelectionB == ColorArg.Alpha0
             || ColorSelectionC == ColorArg.Color0 || ColorSelectionC == ColorArg.Alpha0
             || AlphaSelectionA == AlphaArg.Alpha0 || AlphaSelectionB == AlphaArg.Alpha0 || AlphaSelectionC == AlphaArg.Alpha0)
                stage += String.Format("cc0 = fract(c0 * (255.0f/256.0f)) * (256.0f/255.0f);\n");

            if (ColorSelectionA == ColorArg.Color1 || ColorSelectionA == ColorArg.Alpha1
             || ColorSelectionB == ColorArg.Color1 || ColorSelectionB == ColorArg.Alpha1
             || ColorSelectionC == ColorArg.Color1 || ColorSelectionC == ColorArg.Alpha1
             || AlphaSelectionA == AlphaArg.Alpha1 || AlphaSelectionB == AlphaArg.Alpha1 || AlphaSelectionC == AlphaArg.Alpha1)
                stage += String.Format("cc1 = fract(c1 * (255.0f/256.0f)) * (256.0f/255.0f);\n");

            if (ColorSelectionA == ColorArg.Color2 || ColorSelectionA == ColorArg.Alpha2
             || ColorSelectionB == ColorArg.Color2 || ColorSelectionB == ColorArg.Alpha2
             || ColorSelectionC == ColorArg.Color2 || ColorSelectionC == ColorArg.Alpha2
             || AlphaSelectionA == AlphaArg.Alpha2 || AlphaSelectionB == AlphaArg.Alpha2 || AlphaSelectionC == AlphaArg.Alpha2)
                stage += String.Format("cc2 = fract(c2 * (255.0f/256.0f)) * (256.0f/255.0f);\n");

            #region Color Channel

            stage += String.Format("// color combine\n{0} = ", MDL0MaterialNode.tevCOutputTable[(int)ColorRegister]);

            if (ColorClamp)
                stage += "saturate(";

            if (ColorScale > TevScale.MultiplyBy1)
                stage += String.Format("{0} * (", MDL0MaterialNode.tevScaleTable[(int)ColorScale]);

            if (!(ColorSelectionD == ColorArg.Zero && ColorSubtract == false))
                stage += String.Format("{0} {1} ", MDL0MaterialNode.tevCInputTable[(int)ColorSelectionD], MDL0MaterialNode.tevOpTable[ColorSubtract ? 1 : 0]);

            if (ColorSelectionA == ColorSelectionB)
                stage += String.Format("{0}",
                    MDL0MaterialNode.tevCInputTable[(int)ColorSelectionA + 16]);
            else if (ColorSelectionC == ColorArg.Zero)
                stage += String.Format("{0}",
                    MDL0MaterialNode.tevCInputTable[(int)ColorSelectionA + 16]);
            else if (ColorSelectionC == ColorArg.One)
                stage += String.Format("{0}",
                    MDL0MaterialNode.tevCInputTable[(int)ColorSelectionB + 16]);
            else if (ColorSelectionA == ColorArg.Zero)
                stage += String.Format("{0} * {1}",
                    MDL0MaterialNode.tevCInputTable[(int)ColorSelectionB + 16],
                    MDL0MaterialNode.tevCInputTable[(int)ColorSelectionC + 16]);
            else if (ColorSelectionB == ColorArg.Zero)
                stage += String.Format("{0} * (vec3(1.0f, 1.0f, 1.0f) - {1})",
                    MDL0MaterialNode.tevCInputTable[(int)ColorSelectionA + 16],
                    MDL0MaterialNode.tevCInputTable[(int)ColorSelectionC + 16]);
            else
                stage += String.Format("lerp({0}, {1}, {2})",
                    MDL0MaterialNode.tevCInputTable[(int)ColorSelectionA + 16],
                    MDL0MaterialNode.tevCInputTable[(int)ColorSelectionB + 16],
                    MDL0MaterialNode.tevCInputTable[(int)ColorSelectionC + 16]);

            stage += MDL0MaterialNode.tevBiasTable[(int)ColorBias];

            if (ColorClamp) stage += ")";
            if (ColorScale > TevScale.MultiplyBy1) stage += ")";

            #endregion

            stage += ";\n";

            #region Alpha Channel

            stage += String.Format("// alpha combine\n{0} = ", MDL0MaterialNode.tevAOutputTable[(int)AlphaRegister]);

            if (AlphaClamp)
                stage += "saturate(";

            if (AlphaScale > TevScale.MultiplyBy1)
                stage += String.Format("{0} * (", MDL0MaterialNode.tevScaleTable[(int)AlphaScale]);

            if(!(AlphaSelectionD == AlphaArg.Zero && AlphaSubtract == false))
                stage += String.Format("{0}.a {1} ", MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionD], MDL0MaterialNode.tevOpTable[AlphaSubtract ? 1 : 0]);

            if (AlphaSelectionA == AlphaSelectionB)
                stage += String.Format("{0}.a",
                    MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionA + 8]);
            else if (AlphaSelectionC == AlphaArg.Zero)
                stage += String.Format("{0}.a",
                    MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionA + 8]);
            else if (AlphaSelectionA == AlphaArg.Zero)
                stage += String.Format("{0}.a * {1}.a",
                    MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionB + 8],
                    MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionC + 8]);
            else if (AlphaSelectionB == AlphaArg.Zero)
                stage += String.Format("{0}.a * (1.0f - {1}.a)",
                    MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionA + 8],
                    MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionC + 8]);
            else
                stage += String.Format("lerp({0}.a, {1}.a, {2}.a)",
                    MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionA + 8],
                    MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionB + 8],
                    MDL0MaterialNode.tevAInputTable[(int)AlphaSelectionC + 8]);

            stage += MDL0MaterialNode.tevBiasTable[(int)AlphaBias];

            if (AlphaClamp) stage += ")";
            if (AlphaScale > TevScale.MultiplyBy1) stage += ")";

            #endregion

            stage += ";\n\n//TEV stage " + Index + " done\n\n";

            return stage;
        }
        private static void WritePolygon(StreamWriter writer, MDL0ObjectNode poly)
        {
            if (poly._manager._vertices != null)
            {
                int count = poly._manager._vertices.Count;
                Vector3[] Vertices = new Vector3[count];
                DialogResult result = MessageBox.Show("Do you want to export the weighted positions of the vertices?", "", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
                if (result == DialogResult.Yes)
                {
                    //Weight vertices
                    foreach (Influence inf in (poly.Model)._influences._influences)
                        inf.CalcMatrix();
                    poly._manager.Weight();

                    //Set weighted positions
                    for (int i = 0; i < count; i++)
                        if (poly._manager._vertices[i].WeightedPosition.ToString() != "(0,0,0)")
                            Vertices[i] = poly._manager._vertices[i].WeightedPosition;
                        else
                            Vertices[i] = poly._manager._vertices[i].Position;
                }
                else if (result == DialogResult.No)
                {
                    //Set raw positions
                    for (int i = 0; i < count; i++)
                        Vertices[i] = poly._manager._vertices[i].Position;
                }
                if (result != DialogResult.Cancel) //Export
                    WriteVertexGroup(writer, Vertices);
            }
            if (poly._manager._faceData[1] != null)
                WriteNormalGroup(writer, poly._manager, true);

            for (int i = 0; i < 1; i++) //Obj only supports 1 uv coord set...
                if (poly._manager._faceData[i + 4] != null)
                    WriteUVGroup(writer, poly._manager._faceData[i + 4]);

            writer.WriteLine();
            writer.WriteLine(String.Format("g {0}", poly.Name));
            //if (poly._material != null)
            //    WriteMaterial(writer, poly._material);
            //if (poly.Primitives != null)
            //    foreach (Primitive p in poly.Primitives)
            //    {
            //        switch (p._type)
            //        {
            //            case GLPrimitiveType.TriangleFan:
            //                WriteTriFan(writer, p);
            //                break;
            //            case GLPrimitiveType.TriangleStrip:
            //                WriteTriStrip(writer, p);
            //                break;
            //            case GLPrimitiveType.Triangles:
            //                WriteTriList(writer, p);
            //                break;
            //            case GLPrimitiveType.Quads:
            //                WriteQuadList(writer, p);
            //                break;
            //        }
            //    }
            if (poly._manager != null)
            {
                if (poly._manager._triangles != null)
                    WriteTriList(writer, poly._manager);
                //if (poly._manager._lines != null)
                //{

                //}
                //if (poly._manager._points != null)
                //{

                //}
            }
        }
        private static void WritePolyInstance(MDL0ObjectNode poly, XmlWriter writer)
        {
            writer.WriteStartElement("node");
            writer.WriteAttributeString("id", poly.Name);
            writer.WriteAttributeString("name", poly.Name);
            writer.WriteAttributeString("type", "NODE");

            writer.WriteStartElement("instance_controller");
            writer.WriteAttributeString("url", String.Format("#{0}_Controller", poly.Name));

            writer.WriteStartElement("skeleton");
            writer.WriteString("#" + poly.Model._linker.BoneCache[0].Name);
            writer.WriteEndElement();

            if (poly.UsableMaterialNode != null)
            {
                writer.WriteStartElement("bind_material");
                writer.WriteStartElement("technique_common");
                writer.WriteStartElement("instance_material");
                writer.WriteAttributeString("symbol", poly.UsableMaterialNode.Name);
                writer.WriteAttributeString("target", "#" + poly.UsableMaterialNode.Name);

                foreach (MDL0MaterialRefNode mr in poly.UsableMaterialNode.Children)
                {
                    writer.WriteStartElement("bind_vertex_input");
                    writer.WriteAttributeString("semantic", "TEXCOORD" + (mr.TextureCoordId < 0 ? 0 : mr.TextureCoordId)); //Replace with true set id
                    writer.WriteAttributeString("input_semantic", "TEXCOORD");
                    writer.WriteAttributeString("input_set", (mr.TextureCoordId < 0 ? 0 : mr.TextureCoordId).ToString()); //Replace with true set id
                    writer.WriteEndElement(); //bind_vertex_input
                }

                writer.WriteEndElement(); //instance_material
                writer.WriteEndElement(); //technique_common
                writer.WriteEndElement(); //bind_material
            }

            writer.WriteEndElement(); //instance_geometry
            writer.WriteEndElement(); //node
        }
        public static string GenerateVertexShader(MDL0ObjectNode obj)
        {
            Reset();

            MDL0MaterialNode mat = obj.UsableMaterialNode;
            MDL0ShaderNode shader = mat.ShaderNode;

            //w("#version 330\n");

            bool[] data = new bool[12];
            for (int i = 0; i < 12; i++)
                data[i] = obj._manager._faceData[i] != null;

            if (data[0])
                w("in vec3 Position;");
            if (data[1])
                w("in vec3 Normal;");
            for (int i = 0; i < 2; i++)
                if (data[i + 2])
                    w("in vec4 Color{0};", i);
            for (int i = 0; i < 8; i++)
                if (data[i + 4])
                    w("in vec2 UV{0};", i);

            w("uniform mat4 projection_matrix;");
            w("uniform mat4 modelview_matrix;");

            for (int i = 0; i < obj._uvSet.Length; i++)
                if (obj._uvSet[i] != null)
                    w("out vec2 UVSet{0};", i);
            for (int i = 0; i < obj._colorSet.Length; i++)
                if (obj._colorSet[i] != null)
                    w("out vec4 ColorSet{0};", i);

            Start();

            w("gl_Position = projection_matrix * modelview_matrix * vec4(Position, 1.0);");
            //w("gl_Normal = vec4(Normal, 1.0);\n");
            for (int i = 0; i < obj._uvSet.Length; i++)
                if (obj._uvSet[i] != null)
                    w("UVSet{0} = UV{0};", i);
            for (int i = 0; i < obj._colorSet.Length; i++)
                if (obj._colorSet[i] != null)
                    w("ColorSet{0} = Color{0};", i);

            Finish();

            return tempShader;
        }
        public string GeneratePixelShaderCode(MDL0ObjectNode Object, PSGRENDER_MODE PSGRenderMode, TKContext ctx)
        {
            tempShader = "";

            int numStages = ShaderNode.Children.Count;
            int numTexgen = Children.Count;

            w("//Pixel Shader for TEV stages\n");
            w("//{0} TEV stages, {1} texgens, {2} IND stages\n", numStages, numTexgen, IndirectShaderStages);

            int nIndirectStagesUsed = 0;
            if (IndirectShaderStages > 0)
                for (int i = 0; i < numStages; ++i)
                {
                    TEVStage stage = ShaderNode.Children[i] as TEVStage;
                    if (stage.IndirectActive && stage.bt < IndirectShaderStages)
                        nIndirectStagesUsed |= 1 << stage.bt;
                }

            DepthTextureEnable = (/*bpmem.ztex2.op != ZTEXTURE_DISABLE && */!ZCompareLoc && EnableDepthTest && EnableDepthUpdate)/* || g_ActiveConfig.bEnablePerPixelDepth*/;

            //A few required defines and ones that will make our lives a lot easier
            if (ctx.bSupportsGLSLBinding || ctx.bSupportsGLSLUBO)
            {
                w("#version 330 compatibility\n");
                if (ctx.bSupportsGLSLBinding)
                    w("#extension GL_ARB_shading_language_420pack : enable\n");
                //if (ctx.bSupportsGLSLUBO)
                //    w("#extension GL_ARB_uniform_buffer_object : enable\n");
            }
            else
                w("#version 120\n");

            if (ctx.bSupportsGLSLATTRBind)
                w("#extension GL_ARB_explicit_attrib_location : enable\n");

            w("#define saturate(x) clamp(x, 0.0f, 1.0f)\n");
            w("#define lerp(x, y, z) mix(x, y, z)\n");

            w("float fmod(float x, float y)\n");
            w("{\n");
            w("float z = fract(abs(x / y)) * abs(y);\n");
            w("return (x < 0) ? -z : z;\n");
            w("}\n");

            for (uint i = 0; i < 8; i++)
                w("{0}uniform sampler2D samp{1};\n", WriteBinding(i, ctx), i);

            w("\n");

            w("uniform vec4 " + I_COLORS + "[4];\n");
            w("uniform vec4 " + I_KCOLORS + "[4];\n");
            w("uniform vec4 " + I_ALPHA + ";\n");
            w("uniform vec4 " + I_TEXDIMS + "[8];\n");
            w("uniform vec4 " + I_ZBIAS + "[2];\n");
            w("uniform vec4 " + I_INDTEXSCALE + "[2];\n");
            w("uniform vec4 " + I_INDTEXMTX + "[6];\n");
            w("uniform vec4 " + I_FOG + "[3];\n");

            // Compiler will optimize these out by itself.
            w("uniform vec4 " + I_PLIGHTS + "[40];\n");
            w("uniform vec4 " + I_PMATERIALS + "[4];\n");

            w("vec4 ocol0;\n");

            if (DepthTextureEnable)
                w("float depth;\n");

            w("vec4 rawpos = gl_FragCoord;\n");

            w("vec4 colors_0 = gl_Color;\n");
            w("vec4 colors_1 = gl_SecondaryColor;\n");

            if (numTexgen < 7)
            {
                for (int i = 0; i < numTexgen; i++)
                    w("vec3 uv{0} = gl_TexCoord[{0}].xyz;\n", i);
                w("vec4 clipPos = gl_TexCoord[{0}];\n", numTexgen);
                w("vec4 Normal = gl_TexCoord[{0}];\n", numTexgen + 1);
            }
            else
                for (int i = 0; i < 8; ++i)
                    w("vec4 uv{0} = gl_TexCoord[{0}];\n", i);

            w("void main()\n{\n");

            AlphaPretest Pretest = PretestAlpha();
            //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_ALPHA_PASS && !DepthTextureEnable && Pretest >= 0)
            //{
            //    if (Pretest == AlphaPretest.AlwaysFail)
            //    {
            //        w("ocol0 = vec4(0);\n");
            //        w("discard;\n");

            //        if(PSGRenderMode != PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND)
            //            w("gl_FragColor = ocol0;\n");

            //        w("return;\n");
            //    }
            //    else
            //        w("ocol0 = " + I_ALPHA + ".aaaa;\n");

            //    w("}\n");

            //    return tempShader;
            //}

            w("vec4 c0 = " + I_COLORS + "[1], c1 = " + I_COLORS + "[2], c2 = " + I_COLORS + "[3], prev = vec4(0.0f, 0.0f, 0.0f, 0.0f), textemp = vec4(0.0f, 0.0f, 0.0f, 0.0f), rastemp = vec4(0.0f, 0.0f, 0.0f, 0.0f), konsttemp = vec4(0.0f, 0.0f, 0.0f, 0.0f);\n");
            w("vec3 comp16 = vec3(1.0f, 255.0f, 0.0f), comp24 = vec3(1.0f, 255.0f, 255.0f*255.0f);\n");
            w("vec4 alphabump = vec4(0.0f,0.0f,0.0f,0.0f);\n");
            w("vec3 tevcoord = vec3(0.0f, 0.0f, 0.0f);\n");
            w("vec2 wrappedcoord=vec2(0.0f,0.0f), tempcoord=vec2(0.0f,0.0f);\n");
            w("vec4 cc0 = vec4(0.0f,0.0f,0.0f,0.0f), cc1 = vec4(0.0f,0.0f,0.0f,0.0f);\n");
            w("vec4 cc2 = vec4(0.0f,0.0f,0.0f,0.0f), cprev = vec4(0.0f,0.0f,0.0f,0.0f);\n");
            w("vec4 crastemp=vec4(0.0f,0.0f,0.0f,0.0f), ckonsttemp = vec4(0.0f,0.0f,0.0f,0.0f);\n\n");

            if (Children.Count < 7)
            {
                w("vec3 _norm0 = normalize(Normal.xyz);\n\n");
                w("vec3 pos = vec3(clipPos.x,clipPos.y,Normal.w);\n");
            }
            else
            {
                w("vec3 _norm0 = normalize(vec3(uv4.w,uv5.w,uv6.w));\n\n");
                w("vec3 pos = vec3(uv0.w,uv1.w,uv7.w);\n");
            }

            w("vec4 mat, lacc;\nvec3 ldir, h;\nfloat dist, dist2, attn;\n");

            Object.tabs = tabs;
            tempShader += Object.GenerateLightingShader(I_PMATERIALS, I_PLIGHTS, "colors_", "colors_");

            //if (numTexgen < 7)
            //    w("clipPos = vec4(rawpos.x, rawpos.y, clipPos.z, clipPos.w);\n");
            //else
            //    w("vec4 clipPos = vec4(rawpos.x, rawpos.y, uv2.w, uv3.w);\n");

            // HACK to handle cases where the tex gen is not enabled
            if (numTexgen == 0)
                w("vec3 uv0 = vec3(0.0f, 0.0f, 0.0f);\n");
            else
            {
                for (int i = 0; i < numTexgen; ++i)
                {
                    // optional perspective divides
                    if (((MDL0MaterialRefNode)Children[i]).Projection == TexProjection.STQ)
                    {
                        w("if (uv{0}.z != 0.0f)\n", i);
                        w("    uv{0}.xy = uv{0}.xy / uv{0}.z;\n", i);
                    }

                    //w("uv{0}.xy = uv{0}.xy * "+I_TEXDIMS+"[{0}].zw;\n", i);
                }
            }

            for (int i = 0; i < IndirectShaderStages; i++)
            {
                if ((nIndirectStagesUsed & (1 << i)) != 0)
                {
                    uint texcoord = (ShaderNode._swapBlock._Value16.Value >> ((i + 1) * 3) & 7);

                    if (texcoord < numTexgen)
                        w("tempcoord = uv{0}.xy * " + I_INDTEXSCALE + "[{1}].{2};\n", texcoord, i / 2, (i & 1) != 0 ? "zw" : "xy");
                    else
                        w("tempcoord = vec2(0.0f, 0.0f);\n");

                    SampleTexture(String.Format("vec3 indtex{0}", i), "tempcoord", "abg", (ShaderNode._swapBlock._Value16.Value >> (i * 3) & 7));
                }
            }

            foreach (TEVStage stage in ShaderNode.Children)
                if (stage.Index < ActiveShaderStages)
                    w(stage.Write(this, Object));
                else break;

            if (numStages > 0)
            {
                w("prev.rgb = {0};\n", tevCOutputTable[(int)((TEVStage)ShaderNode.Children[numStages - 1]).ColorRegister]);
                w("prev.a = {0};\n", tevAOutputTable[(int)((TEVStage)ShaderNode.Children[numStages - 1]).AlphaRegister]);
            }

            // emulation of unsigned 8 overflow when casting
            //w("prev = fract(4.0f + prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");

            if (Pretest == AlphaPretest.AlwaysFail)
            {
                w("ocol0 = vec4(0.0f);\n");

                //if (DepthTextureEnable)
                //    w("depth = 1.0f;\n");

                //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND)
                //    w("ocol1 = vec4(0.0f);\n");
                //else
                w("gl_FragColor = ocol0;\n");

                if (DepthTextureEnable)
                    w("gl_FragDepth = depth;\n");

                w("discard;\n");

                w("return;\n");
            }
            else
            {
                if (Pretest != AlphaPretest.AlwaysPass)
                    WriteAlphaTest(PSGRenderMode);

                //if (_fog != null && (_fog.Type != 0) || DepthTextureEnable)
                //{
                //    // the screen space depth value = far z + (clip z / clip w) * z range
                //    w("float zCoord = " + I_ZBIAS + "[1].x + (clipPos.z / clipPos.w) * " + I_ZBIAS + "[1].y;\n");
                //}

                //if (DepthTextureEnable)
                //{
                //    // use the texture input of the last texture stage (textemp), hopefully this has been read and is in correct format...
                //    if (/*bpmem.ztex2.op != ZTEXTURE_DISABLE && */!ZCompLoc && EnableDepthTest && EnableDepthUpdate)
                //    {
                //        //if (bpmem.ztex2.op == ZTEXTURE_ADD)
                //        //    Write("zCoord = dot("+I_ZBIAS+"[0].xyzw, textemp.xyzw) + "+I_ZBIAS+"[1].w + zCoord;\n");
                //        //else
                //            w("zCoord = dot(" + I_ZBIAS + "[0].xyzw, textemp.xyzw) + " + I_ZBIAS + "[1].w;\n");

                //        // scale to make result from frac correct
                //        w("zCoord = zCoord * (16777215.0f/16777216.0f);\n");
                //        w("zCoord = fract(zCoord);\n");
                //        w("zCoord = zCoord * (16777216.0f/16777215.0f);\n");
                //    }
                //    w("depth = zCoord;\n");
                //}

                //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_ALPHA_PASS)
                //    w("ocol0 = vec4(prev.rgb, " + I_ALPHA + ".a);\n");
                //else
                {
                    WriteFog();
                    w("ocol0 = prev;\n");
                }

                //if (PSGRenderMode == PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND)
                //{
                //    w("ocol1 = ocol0;\n");
                //    w("ocol0.a = " + I_ALPHA + ".a;\n");
                //}

                //if (DepthTextureEnable)
                //    w("gl_FragDepth = depth;\n");
                //if (PSGRenderMode != PSGRENDER_MODE.PSGRENDER_DSTALPHA_DUAL_SOURCE_BLEND)
                w("gl_FragColor = ocol0;\n");

            }
            w("}\n");

            return tempShader;
        }
        public static void SetUniforms(MDL0ObjectNode obj)
        {
            //MDL0MaterialNode mat = obj.UsableMaterialNode;

            //int pHandle = obj._programHandle;
            //int u = -1;

            //u = GL.GetUniformLocation(pHandle, "C1Amb");
            //if (u > -1)
            //    GL.Uniform4(u,
            //    mat.C1AmbientColor.R * RGBAPixel.ColorFactor,
            //    mat.C1AmbientColor.G * RGBAPixel.ColorFactor,
            //    mat.C1AmbientColor.B * RGBAPixel.ColorFactor,
            //    mat.C1AmbientColor.A * RGBAPixel.ColorFactor);

            //u = GL.GetUniformLocation(pHandle, "C2Amb");
            //if (u > -1)
            //    GL.Uniform4(u,
            //    mat.C2AmbientColor.R * RGBAPixel.ColorFactor,
            //    mat.C2AmbientColor.G * RGBAPixel.ColorFactor,
            //    mat.C2AmbientColor.B * RGBAPixel.ColorFactor,
            //    mat.C2AmbientColor.A * RGBAPixel.ColorFactor);

            //u = GL.GetUniformLocation(pHandle, "C1Mat");
            //if (u > -1)
            //    GL.Uniform4(u,
            //    mat.C1MaterialColor.R * RGBAPixel.ColorFactor,
            //    mat.C1MaterialColor.G * RGBAPixel.ColorFactor,
            //    mat.C1MaterialColor.B * RGBAPixel.ColorFactor,
            //    mat.C1MaterialColor.A * RGBAPixel.ColorFactor);

            //u = GL.GetUniformLocation(pHandle, "C2Mat");
            //if (u > -1)
            //    GL.Uniform4(u,
            //    mat.C2MaterialColor.R * RGBAPixel.ColorFactor,
            //    mat.C2MaterialColor.G * RGBAPixel.ColorFactor,
            //    mat.C2MaterialColor.B * RGBAPixel.ColorFactor,
            //    mat.C2MaterialColor.A * RGBAPixel.ColorFactor);
        }
Example #27
0
        //Only updates single-bind vertices and objects!
        //Influences using this bone must be handled separately
        private void InfluenceAssets(bool influence)
        {
            Matrix m = influence ? InverseBindMatrix : BindMatrix;

            Matrix rm = m.GetRotationMatrix();

            foreach (IMatrixNodeUser user in Users)
            {
                if (user is MDL0ObjectNode)
                {
                    Vector3 *      pData = null;
                    MDL0ObjectNode o     = user as MDL0ObjectNode;

                    if (o._manager._faceData[1] != null)
                    {
                        pData = (Vector3 *)o._manager._faceData[1].Address;
                    }

                    foreach (Vertex3 v in o._manager._vertices)
                    {
                        v.Position *= m;

                        if (pData != null)
                        {
                            foreach (int i in v._faceDataIndices)
                            {
                                pData[i] *= rm;
                            }
                        }
                    }
                }
                else if (user is Vertex3)
                {
                    Vertex3        v = user as Vertex3;
                    MDL0ObjectNode o = v.Parent as MDL0ObjectNode;

                    v.Position *= m;

                    if (o._manager._faceData[1] != null)
                    {
                        Vector3 *pData = (Vector3 *)o._manager._faceData[1].Address;
                        foreach (int i in v._faceDataIndices)
                        {
                            pData[i] *= rm;
                        }
                    }
                }
            }
            foreach (MDL0ObjectNode o in _singleBindObjects)
            {
                Vector3 *pData = null;
                if (o._manager._faceData[1] != null)
                {
                    pData = (Vector3 *)o._manager._faceData[1].Address;
                }

                foreach (Vertex3 v in o._manager._vertices)
                {
                    v.Position *= m;

                    if (pData != null)
                    {
                        foreach (int i in v._faceDataIndices)
                        {
                            pData[i] *= rm;
                        }
                    }
                }
            }
        }
        private void CreateObject(InstanceEntry inst, NodeEntry node, ResourceNode parent, PrimitiveManager manager, MDL0Node model, DecoderShell shell)
        {
            if (manager != null)
            {
                Error = "There was a problem creating a new object for " + (node._name != null ? node._name : node._id);
                int i = 0;
                foreach (Vertex3 v in manager._vertices)
                    v._index = i++;

                MDL0ObjectNode poly = new MDL0ObjectNode() { _manager = manager };
                poly._manager._polygon = poly;
                poly._name = node._name != null ? node._name : node._id;

                //Attach single-bind
                if (parent != null && parent is MDL0BoneNode)
                    poly.MatrixNode = (MDL0BoneNode)parent;

                //Attach material
                if (inst._material != null)
                    foreach (MaterialEntry mat in shell._materials)
                        if (mat._id == inst._material._target)
                        {
                            (poly._opaMaterial = (mat._node as MDL0MaterialNode))._objects.Add(poly);
                            break;
                        }

                model._numFaces += poly._numFaces = manager._faceCount = manager._pointCount / 3;
                model._numFacepoints += poly._numFacepoints = manager._pointCount;

                poly._parent = model._objGroup;
                model._objList.Add(poly);
            }
        }
        public static unsafe void PMD2MDL0(MDL0Node model)
        {
            model._version = 9;
            model._isImport = true;
            Collada._importOptions = BrawlLib.Properties.Settings.Default.ColladaImportOptions;
            Collada._importOptions._forceCCW = true;
            Collada._importOptions._fltVerts = true;
            Collada._importOptions._fltNrms = true;
            Collada._importOptions._fltUVs = true;

            model.InitGroups();

            List<MDL0BoneNode> BoneCache = new List<MDL0BoneNode>();

            int index = 0;
            if (!String.IsNullOrWhiteSpace(_header._modelNameEnglish))
                model.Name = _header._modelNameEnglish;
            else
                model.Name = _header._modelName;

            if (!String.IsNullOrWhiteSpace(_header._commentEnglish))
                MessageBox.Show(_header._commentEnglish);
            else
                MessageBox.Show(_header._comment);

            ModelBone parent = null;
            foreach (ModelBone b in _bones)
            {
                MDL0BoneNode bone = new MDL0BoneNode();

                if (!String.IsNullOrWhiteSpace(b._boneNameEnglish))
                    bone._name = b._boneNameEnglish;
                else
                    bone._name = b._boneName;

                bone._entryIndex = index++;

                if (b._parentBoneIndex != ushort.MaxValue)
                {
                    parent = _bones[b._parentBoneIndex];
                    foreach (MDL0BoneNode v in model._boneGroup._children)
                        AssignParent(v, b, bone, parent);
                }
                else
                {
                    bone.Parent = model._boneGroup;
                    bone._bindState._scale = new Vector3(1.0f);
                    bone._bindState._translate = new Vector3(b._wPos[0], b._wPos[1], b._wPos[2]);
                    bone._bindState.CalcTransforms();
                    bone.RecalcBindState();
                }

                BoneCache.Add(bone);
            }

            MDL0ShaderNode texSpa = null, tex = null, colorSpa = null, color = null;

            index = 0;
            foreach (ModelMaterial m in _materials)
            {
                MDL0MaterialNode mn = new MDL0MaterialNode();
                mn.Name = "Material" + index++;

                MDL0MaterialRefNode texRef = null;
                MDL0MaterialRefNode spaRef = null;

                if (!String.IsNullOrEmpty(m._textureFileName))
                    if (m._textureFileName.Contains('*'))
                    {
                        string[] names = m._textureFileName.Split('*');
                        if (!String.IsNullOrEmpty(names[0]))
                        {
                            texRef = new MDL0MaterialRefNode();
                            texRef.Name = names[0].Substring(0, names[0].IndexOf('.'));
                        }
                        if (!String.IsNullOrEmpty(names[1]))
                        {
                            spaRef = new MDL0MaterialRefNode();
                            spaRef.Name = names[1].Substring(0, names[1].IndexOf('.'));
                            spaRef.MapMode = MDL0MaterialRefNode.MappingMethod.EnvCamera;
                            spaRef.UWrapMode = MDL0MaterialRefNode.WrapMode.Clamp;
                            spaRef.VWrapMode = MDL0MaterialRefNode.WrapMode.Clamp;
                            spaRef.Projection = Wii.Graphics.TexProjection.STQ;
                            spaRef.InputForm = Wii.Graphics.TexInputForm.ABC1;
                            spaRef.Coordinates = Wii.Graphics.TexSourceRow.Normals;
                            spaRef.Normalize = true;
                        }
                    }
                    else
                    {
                        texRef = new MDL0MaterialRefNode();
                        texRef.Name = m._textureFileName.Substring(0, m._textureFileName.IndexOf('.'));
                        texRef.Coordinates = Wii.Graphics.TexSourceRow.TexCoord0;
                    }

                if (texRef != null)
                {
                    (texRef._texture = model.FindOrCreateTexture(texRef.Name))._references.Add(texRef);
                    texRef._parent = mn;
                    mn._children.Add(texRef);
                }
                if (spaRef != null)
                {
                    (spaRef._texture = model.FindOrCreateTexture(spaRef.Name))._references.Add(spaRef);
                    spaRef._parent = mn;
                    mn._children.Add(spaRef);
                }

                mn._chan1._matColor = new RGBAPixel((byte)(m._diffuseColor[0] * 255), (byte)(m._diffuseColor[1] * 255), (byte)(m._diffuseColor[2] * 255), 255);
                mn._chan1.ColorMaterialSource = GXColorSrc.Register;

                if (texRef != null && spaRef != null)
                {
                    if (texSpa == null)
                    {
                        MDL0ShaderNode n = TexSpaShader;
                        n._parent = model._shadGroup;
                        model._shadList.Add(n);
                        texSpa = n;
                    }
                    mn.ShaderNode = texSpa;
                }
                else if (texRef != null)
                {
                    if (tex == null)
                    {
                        MDL0ShaderNode n = TexShader;
                        n._parent = model._shadGroup;
                        model._shadList.Add(n);
                        tex = n;
                    }
                    mn.ShaderNode = tex;
                }
                else if (spaRef != null)
                {
                    if (colorSpa == null)
                    {
                        MDL0ShaderNode n = ColorSpaShader;
                        n._parent = model._shadGroup;
                        model._shadList.Add(n);
                        colorSpa = n;
                    }
                    mn.ShaderNode = colorSpa;
                }
                else
                {
                    if (color == null)
                    {
                        MDL0ShaderNode n = ColorShader;
                        n._parent = model._shadGroup;
                        model._shadList.Add(n);
                        color = n;
                    }
                    mn.ShaderNode = color;
                }

                mn._parent = model._matGroup;
                model._matList.Add(mn);
            }

            model._numFaces = 0;
            model._numFacepoints = 0;

            int x = 0;
            int offset = 0;
            foreach (ModelMaterial m in _materials)
            {
                PrimitiveManager manager = new PrimitiveManager() { _pointCount = (int)m._faceVertCount };
                MDL0ObjectNode p = new MDL0ObjectNode() { _manager = manager, _opaMaterial = (MDL0MaterialNode)model._matList[x] };
                p._opaMaterial._objects.Add(p);
                p._manager._vertices = new List<Vertex3>();
                p.Name = "polygon" + x++;
                p._parent = model._objGroup;

                model._numFaces += p._numFaces = manager._faceCount = manager._pointCount / 3;
                model._numFacepoints += p._numFacepoints = manager._pointCount;

                p._manager._indices = new UnsafeBuffer((int)m._faceVertCount * 2);
                p._manager._faceData[0] = new UnsafeBuffer((int)m._faceVertCount * 12);
                p._manager._faceData[1] = new UnsafeBuffer((int)m._faceVertCount * 12);
                p._manager._faceData[4] = new UnsafeBuffer((int)m._faceVertCount * 8);

                p._manager._dirty[0] = true;
                p._manager._dirty[1] = true;
                p._manager._dirty[4] = true;

                ushort* Indices = (ushort*)p._manager._indices.Address;
                Vector3* Vertices = (Vector3*)p._manager._faceData[0].Address;
                Vector3* Normals = (Vector3*)p._manager._faceData[1].Address;
                Vector2* UVs = (Vector2*)p._manager._faceData[4].Address;

                manager._triangles = new NewPrimitive((int)m._faceVertCount, BeginMode.Triangles);
                uint[] pTriarr = manager._triangles._indices;
                uint pTri = 0;

                index = 0;
                List<int> usedVertices = new List<int>();
                List<int> vertexIndices = new List<int>();
                for (int s = offset, l = 0; l < (int)m._faceVertCount; l++, s++)
                {
                    ushort i = _faceIndices[s];
                    ModelVertex mv = _vertices[i];
                    ushort j = 0;
                    if (!usedVertices.Contains(i))
                    {
                        Influence inf;
                        BoneWeight weight1 = null, weight2 = null;

                        float weight = ((float)mv._boneWeight / 100.0f).Clamp(0.0f, 1.0f);

                        if (weight > 0.0f && weight < 1.0f)
                        {
                            weight1 = new BoneWeight(BoneCache[mv._boneIndex[0]], weight);
                            weight2 = new BoneWeight(BoneCache[mv._boneIndex[1]], 1.0f - weight);
                        }
                        else if (weight == 0.0f)
                            weight1 = new BoneWeight(BoneCache[mv._boneIndex[1]]);
                        else
                            weight1 = new BoneWeight(BoneCache[mv._boneIndex[0]]);

                        if (weight2 != null)
                            inf = new Influence(new List<BoneWeight> { weight1, weight2 });
                        else
                            inf = new Influence(new List<BoneWeight> { weight1 });

                        Vector3 t = new Vector3();
                        Vertex3 v;
                        t._x = mv._position[0];
                        t._y = mv._position[1];
                        t._z = mv._position[2];
                        if (inf._weights.Count > 1)
                        {
                            inf = model._influences.FindOrCreate(inf, true);
                            inf.CalcMatrix();
                            v = new Vertex3(t, inf);
                        }
                        else
                        {
                            MDL0BoneNode bone = inf._weights[0].Bone;
                            v = new Vertex3(t * bone._inverseBindMatrix, bone);
                        }

                        p._manager._vertices.Add(v);
                        vertexIndices.Add(usedVertices.Count);
                        usedVertices.Add(i);
                        j = (ushort)(usedVertices.Count - 1);
                    }
                    else
                        j = (ushort)vertexIndices[usedVertices.IndexOf(i)];

                    *Indices++ = j;
                    pTriarr[pTri++] = (uint)l;
                    *Vertices++ = p._manager._vertices[j]._position;
                    *Normals++ = mv._normal;
                    *UVs++ = mv._texCoord;
                }
                model._objList.Add(p);
                offset += (int)m._faceVertCount;
            }

            //Check each polygon to see if it can be rigged to a single influence
            if (model._objList != null && model._objList.Count != 0)
                foreach (MDL0ObjectNode p in model._objList)
                {
                    IMatrixNode node = null;
                    bool singlebind = true;

                    foreach (Vertex3 v in p._manager._vertices)
                        if (v._matrixNode != null)
                        {
                            if (node == null)
                                node = v._matrixNode;

                            if (v._matrixNode != node)
                            {
                                singlebind = false;
                                break;
                            }
                        }

                    if (singlebind && p._matrixNode == null)
                    {
                        //Increase reference count ahead of time for rebuild
                        if (p._manager._vertices[0]._matrixNode != null)
                            p._manager._vertices[0]._matrixNode.ReferenceCount++;

                        foreach (Vertex3 v in p._manager._vertices)
                            if (v._matrixNode != null)
                                v._matrixNode.ReferenceCount--;

                        p._nodeId = -2; //Continued on polygon rebuild
                    }
                }

            //foreach (MDL0ObjectNode p in model._objList)
            //    foreach (MDL0MaterialNode m in model._matList)
            //    {
            //        MDL0MaterialNode m2 = p.OpaMaterialNode;

            //        if (m2 == null || m2.ShaderNode != m.ShaderNode || m2.Children.Count != m.Children.Count)
            //            continue;

            //        for (int i = 0; i < m.Children.Count; i++)
            //            if (m2.Children[i].Name != m.Children[i].Name)
            //                continue;

            //        p.OpaMaterialNode = m;
            //        break;
            //    }
            //for (int i = 0; i < model._matList.Count; i++)
            //    if (((MDL0MaterialNode)model._matList[i])._objects.Count == 0)
            //        model._matList.RemoveAt(i--);

            model.CleanGroups();
            model.BuildFromScratch(null);
        }
 public MDL0ObjectNode HardCopy()
 {
     MDL0ObjectNode o = new MDL0ObjectNode() { _manager = _manager, Name = Name };
     o._vertexNode = _vertexNode;
     o._normalNode = _normalNode;
     for (int i = 0; i < 2; i++)
         o._colorSet[i] = _colorSet[i];
     for (int i = 0; i < 8; i++)
         o._uvSet[i] = _uvSet[i];
     //o.Nodes = Nodes;
     o._opaMaterial = _opaMaterial;
     o._xluMaterial = _xluMaterial;
     o._furVecNode = _furVecNode;
     o._furPosNode = _furPosNode;
     o._bone = _bone;
     o._primGroups = _primGroups;
     o._matrixNode = _matrixNode;
     o._elementIndices = _elementIndices;
     o._uncompSource = o._origSource = new DataSource(WorkingUncompressed.Address, WorkingUncompressed.Length, Wii.Compression.CompressionType.None);
     return o;
 }