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; }
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 }
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; } } }
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++; //} }
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); }
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); }
//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; }