//------------------2'nd vertex--------------------- tmp = reader.ReadLine(); tmp = tmp.Replace('.', ','); //read first vertex triData = tmp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); parentBone = Convert.ToInt32(triData[0]); v2 = new CustomVertex.Skinned(); v2.Position = new Vector3( Convert.ToSingle(triData[1]), Convert.ToSingle(triData[3]), Convert.ToSingle(triData[2])); v2.Normal = new Vector3( Convert.ToSingle(triData[4]), Convert.ToSingle(triData[6]), Convert.ToSingle(triData[5])); v2.Texture = new Vector2( Convert.ToSingle(triData[7]), Convert.ToSingle(triData[8])); //reading bones count, which affecting on current vertex if (triData.Length > 9) numBones = Convert.ToInt32(triData[9]); if (numBones > 4) Debug.Fail("Bones limit overflow!", "Maximum allowed count of bones per vertex: 4\nbut current bones count per vertex is: " + numBones.ToString()); v2.Bones = new Vector4(0, 0, 0, 0); v2.Weights = new Vector4(0, 0, 0, 0); totalWeight = 0; offset = 9; for (int i = 0; i < numBones; i++) { if (i == 0) { v2.Bones.X = (float)Convert.ToInt32(triData[++offset]); v2.Weights.X = Convert.ToSingle(triData[++offset]); totalWeight += v2.Weights.X; } else if (i == 1) { v2.Bones.Y = (float)Convert.ToInt32(triData[++offset]); v2.Weights.Y = Convert.ToSingle(triData[++offset]); totalWeight += v2.Weights.Y; } else if (i == 2) { v2.Bones.Z = (float)Convert.ToInt32(triData[++offset]); v2.Weights.Z = Convert.ToSingle(triData[++offset]); totalWeight += v2.Weights.Z; } else if (i == 3) { v2.Bones.W = (float)Convert.ToInt32(triData[++offset]); v2.Weights.W = Convert.ToSingle(triData[++offset]); totalWeight += v2.Weights.W; } } addWeight = 1.0f - totalWeight; if (addWeight > 0) if ((int)v2.Bones.X == parentBone) v2.Weights.X += addWeight; else if ((int)v2.Bones.Y == parentBone) v2.Weights.Y += addWeight; else if ((int)v2.Bones.Z == parentBone) v2.Weights.Z += addWeight; else if ((int)v2.Bones.W == parentBone) v2.Weights.W += addWeight; //------------------3'rd vertex--------------------- tmp = reader.ReadLine(); tmp = tmp.Replace('.', ','); //read first vertex triData = tmp.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); parentBone = Convert.ToInt32(triData[0]); v3 = new CustomVertex.Skinned(); v3.Position = new Vector3( Convert.ToSingle(triData[1]), Convert.ToSingle(triData[3]), Convert.ToSingle(triData[2])); v3.Normal = new Vector3( Convert.ToSingle(triData[4]), Convert.ToSingle(triData[6]), Convert.ToSingle(triData[5])); v3.Texture = new Vector2( Convert.ToSingle(triData[7]), Convert.ToSingle(triData[8])); //reading bones count, which affecting on current vertex] if (triData.Length > 9) numBones = Convert.ToInt32(triData[9]); if (numBones > 4) Debug.Fail("Bones limit overflow!", "Maximum allowed count of bones per vertex: 4\nbut current bones count per vertex is: " + numBones.ToString()); v3.Bones = new Vector4(0, 0, 0, 0); v3.Weights = new Vector4(0, 0, 0, 0); totalWeight = 0; offset = 9; for (int i = 0; i < numBones; i++) { if (i == 0) { v3.Bones.X = (float)Convert.ToInt32(triData[++offset]); v3.Weights.X = Convert.ToSingle(triData[++offset]); totalWeight += v3.Weights.X; } else if (i == 1) { v3.Bones.Y = (float)Convert.ToInt32(triData[++offset]); v3.Weights.Y = Convert.ToSingle(triData[++offset]); totalWeight += v3.Weights.Y; } else if (i == 2) { v3.Bones.Z = (float)Convert.ToInt32(triData[++offset]); v3.Weights.Z = Convert.ToSingle(triData[++offset]); totalWeight += v3.Weights.Z; } else if (i == 3) { v3.Bones.W = (float)Convert.ToInt32(triData[++offset]); v3.Weights.W = Convert.ToSingle(triData[++offset]); totalWeight += v3.Weights.W; } } addWeight = 1.0f - totalWeight; if (addWeight > 0) if ((int)v3.Bones.X == parentBone) v3.Weights.X += addWeight; else if ((int)v3.Bones.Y == parentBone) v3.Weights.Y += addWeight; else if ((int)v3.Bones.Z == parentBone) v3.Weights.Z += addWeight; else if ((int)v3.Bones.W == parentBone) v3.Weights.W += addWeight; //now we have all data, so we'll sore it in the our vertex model tri.v1 = v1; tri.v2 = v2; tri.v3 = v3; triCache.Add(tri); tmp = reader.ReadLine(); } while (tmp != "end"); //compute susbsets count List<string> subsetNames = new List<string>(); for (int i = 0; i < triCache.Count; i++) { if (!subsetNames.Contains(triCache[i].TextureName)) subsetNames.Add(triCache[i].TextureName); } int SubsetsCount = subsetNames.Count; List<TRIANGLE>[] subsets = new List<TRIANGLE>[SubsetsCount]; for (int i = 0; i < SubsetsCount; i++) subsets[i] = new List<TRIANGLE>(); for (int i = 0; i < triCache.Count; i++) for (int j = 0; j < subsetNames.Count; j++) if (triCache[i].TextureName == subsetNames[j]) subsets[j].Add(triCache[i]); //now we have all data, so, store it in the buffer stream.Close(); reader.Dispose(); stream.Dispose();
//++++++++++++++++++++++++END LOAD SMD+++++++++++++++++++++++++++++ VertexBuffer vb = new VertexBuffer(CG.GraphicsDevice, triCache.Count * 3 * CustomVertex.Skinned.Size, Usage.WriteOnly, CustomVertex.Skinned.Format, Pool.Default); GeometrySubset[] sub = new GeometrySubset[subsets.Length]; int prev = 0; CustomVertex.Skinned[] vertices; CustomVertex.Skinned[] vertexFull = new CustomVertex.Skinned[triCache.Count * 3]; int off = 0; for (int i = 0; i < sub.Length; i++) { sub[i].FaceCount = subsets[i].Count; sub[i].Length = (uint)sub[i].FaceCount * 3; sub[i].Offset = prev * 3; sub[i].SubsetMaterial = LifeDataManager.LoadMaterial(); sub[i].SubsetMaterial.AmbientColor = new Color4(0x000000); sub[i].SubsetMaterial.DiffuseColor = new Color4(0xffffff); sub[i].SubsetMaterial.SpecularColor = new Color4(0xffffff); sub[i].SubsetMaterial.EmissiveColor = new Color4(0x000000); sub[i].SubsetMaterial.TextureStages[0].LayerTexture = LoadTexture(LifeFileSystem.TexturesPath + subsetNames[i]); prev += subsets[i].Count; vertices = new CustomVertex.Skinned[subsets[i].Count * 3]; int counter = 0; for (int j = 0; j < subsets[i].Count; j++) { vertices[counter] = subsets[i][j].v1; counter++; vertices[counter] = subsets[i][j].v2; counter++; vertices[counter] = subsets[i][j].v3; counter++; } vertices.CopyTo(vertexFull, off); off += vertices.Length; } vb.Lock(0, 0, 0).WriteRange<CustomVertex.Skinned>(vertexFull); vb.Unlock(); VertexElement[] elements = new VertexElement[] { new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0), new VertexElement(0, 12, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Normal,0), new VertexElement(0, 24, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate,0), new VertexElement(0, 32, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.BlendIndices,0), new VertexElement(0, 48, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.BlendWeight,0), VertexElement.VertexDeclarationEnd }; VertexDeclaration decl = new VertexDeclaration(CG.GraphicsDevice, elements); Geometric g = new Geometric(vb, null, sub, triCache.Count, triCache.Count * 3, CustomVertex.Skinned.Size, decl); g.ID = ++g_lastGeometryID; g.SkinInfo = skinInfo; g.ResourceDataName = fileName; g_geometryCache.Add(g.ID, g); return g; }
--КЛАСС КОСТИ
public class BONE { public int ID = -1; public BONE Parent = null; public BONE[] Childs = null; public string BoneName; public Matrix AbsoluteMatrix = Matrix.Identity; public Matrix LocalMatrix = Matrix.Identity; public Vector3 zPos, zRot, lPos, lRot; private Matrix g_baseMat = Matrix.Identity; public Matrix BaseMatrix { get { return g_baseMat; } set { g_baseMat = value; g_baseMat = Matrix.Invert(g_baseMat); } } public Matrix WorldMatrix = Matrix.Identity; public void UpdateMatrices() { if (Parent != null) WorldMatrix = Parent.WorldMatrix * (LocalMatrix * g_baseMat); else WorldMatrix = (g_baseMat * LocalMatrix); if (Childs != null && Childs.Length > 0) for (int i = 0; i < Childs.Length; i++) Childs[i].UpdateMatrices(); } public void AddChild(BONE child) { if (Childs == null) Childs = new BONE[] { child }; else { BONE[] tmp = new BONE[Childs.Length + 1]; Childs.CopyTo(tmp, 0); tmp[Childs.Length] = child; Childs = tmp; } } public BONE(int id, string name, BONE parent) { BoneName = name; ID = id; Parent = parent; } }
--КЛАСС СКЕЛЕТА
public class Skeleton { public int maxBoneID = 0; public BONE[] Bones = null; public Skeleton() { Bones = new BONE[] { new BONE(-1, "Root bone", null) }; } public BONE AddBone(BONE bone) { if (Bones == null) Bones = new BONE[] { bone }; else { BONE[] tmp = new BONE[Bones.Length + 1]; Bones.CopyTo(tmp, 0); tmp[Bones.Length] = bone; Bones = tmp; } return bone; } public Matrix[] GetMatrices() { Matrix[] mat = new Matrix[maxBoneID + 1]; // GetBone(4).LocalMatrix *= Matrix.RotationZ((float)Math.Sin(Environment.TickCount / 1000f)/4f); GetBone(-1).UpdateMatrices(); Vector3 pos, scale; Quaternion rot; GetBone(4).WorldMatrix.Decompose(out scale, out rot, out pos); for (int i = 0; i < maxBoneID + 1; i++) { mat[i] = GetBone(i).WorldMatrix; } return mat; } public BONE GetBone(int boneID) { for (int i = 0; i < Bones.Length; i++) if (Bones[i].ID == boneID) return Bones[i]; return null; } }
--СТРУКТУРА ВЕРШИНЫ
[StructLayout(LayoutKind.Sequential)] public struct Skinned { public Vector3 Position; public Vector3 Normal; public Vector2 Texture; public Vector4 Bones; public Vector4 Weights; public static int Size { get { return sizeof(float) * 16; } } public const VertexFormat Format = VertexFormat.None; }
Да ты здесь целый движок выложил :-)
Теперь класс Renderer, менеджер объектов и текстур.
не : ) это кусок из движка : Р
гдето 0.06% от движка
Facepalm
> Теперь класс Renderer, менеджер объектов и текстур.
давно есть ; )
ну так что? ктонить посмотрит? подскажет?
а то уже напрягает то, что движок стоит на месте.. я без анимации дальше не пойду (пока не сделаю)
уфф.. какие ещё форматы нормальны в освоении (просты) с скелеткой и НОРМАЛЬНЫМ ЭКСПОРТОМ?- в LH сразу и без шаманств с бубном? (нет, Х ф топку)
heihachi
По коду не подскажу - не знаю.
Но тебе надо отдохнуть денек другой, попить пивка, а потом с новыми силами исправить это глюк за пару минут и постучать по лбу, - какой же я дуб был :-)
а потом заводить движок...
heihachi
> Но тебе надо отдохнуть денек другой, попить пивка
отдыхал, пил, непомогло.. сволочь : ( а казался самым простым форматом что я видел а тут такие фишки.
А нафига вообще менять местами Y и Z - может дело в етом?
Или попробуй без шейдеров...
JR-44
> А нафига вообще менять местами Y и Z - может дело в етом?
т.к. ф этом формате принята другая система координат - Z вверх, Y вдаль
JR-44
> Или попробуй без шейдеров...
лень и незачем, шейдер работает и он правильный
Тема в архиве.