public static void SetBoundingBox(xxFrame frame) { if (frame.Mesh == null) { frame.Bounds = new BoundingBox(); } else { xxMesh meshList = frame.Mesh; Vector3 min = new Vector3(Single.MaxValue, Single.MaxValue, Single.MaxValue); Vector3 max = new Vector3(Single.MinValue, Single.MinValue, Single.MinValue); for (int i = 0; i < meshList.SubmeshList.Count; i++) { List <xxVertex> vertList = meshList.SubmeshList[i].VertexList; for (int j = 0; j < vertList.Count; j++) { xxVertex vert = vertList[j]; Vector3 pos = vert.Position; min = Vector3.Minimize(min, pos); max = Vector3.Maximize(max, pos); } } frame.Bounds = new BoundingBox(min, max); } }
public static List <xxVertex> CreateVertexListDup(List <xxSubmesh> submeshList) { List <xxVertex> vertListDup = new List <xxVertex>(UInt16.MaxValue); List <VertexCompare> vertCompareList = new List <VertexCompare>(UInt16.MaxValue); for (int i = 0; i < submeshList.Count; i++) { xxSubmesh meshObj = submeshList[i]; List <xxVertex> vertList = meshObj.VertexList; for (int j = 0; j < vertList.Count; j++) { xxVertex vert = vertList[j]; VertexCompare vertCompare = new VertexCompare(vertCompareList.Count, vert.Position, vert.Normal, vert.BoneIndices, vert.Weights3); int idx = vertCompareList.BinarySearch(vertCompare); if (idx < 0) { vertCompareList.Insert(~idx, vertCompare); vert.Index = vertCompareList.Count; vertListDup.Add(vert.Clone()); } else { vert.Index = vertCompareList[idx].index; } } } vertListDup.TrimExcess(); return(vertListDup); }
public xxVertex Clone() { xxVertex vertex = InitClone(); vertex.Index = Index; vertex.Position = Position; vertex.Weights3 = (float[])Weights3.Clone(); vertex.BoneIndices = (byte[])BoneIndices.Clone(); vertex.Normal = Normal; vertex.UV = (float[])UV.Clone(); vertex.Unknown1 = Unknown1.CloneIfNotNull(); return(vertex); }
private static void UpdateBoneIndices(List <xxVertex> vertList, byte[] boneMap) { for (int i = 0; i < vertList.Count; i++) { xxVertex vert = vertList[i]; byte[] boneIndices = (byte[])vert.BoneIndices.Clone(); for (int j = 0; j < boneIndices.Length; j++) { if (boneIndices[j] != 0xFF) { boneIndices[j] = boneMap[boneIndices[j]]; } } vert.BoneIndices = boneIndices; } }
public static void CopyNormalsNear(List <xxVertex> src, List <xxVertex> dest) { for (int i = 0; i < dest.Count; i++) { var destVert = dest[i]; var destPos = destVert.Position; float minDistSq = Single.MaxValue; xxVertex nearestVert = null; foreach (xxVertex srcVert in src) { var srcPos = srcVert.Position; float[] diff = new float[] { destPos[0] - srcPos[0], destPos[1] - srcPos[1], destPos[2] - srcPos[2] }; float distSq = (diff[0] * diff[0]) + (diff[1] * diff[1]) + (diff[2] * diff[2]); if (distSq < minDistSq) { minDistSq = distSq; nearestVert = srcVert; } } destVert.Normal = nearestVert.Normal; } }
public static void CopyBonesNear(List <xxVertex> src, List <xxVertex> dest) { for (int i = 0; i < dest.Count; i++) { var destVert = dest[i]; var destPos = destVert.Position; float minDistSq = Single.MaxValue; xxVertex nearestVert = null; foreach (xxVertex srcVert in src) { var srcPos = srcVert.Position; float[] diff = new float[] { destPos[0] - srcPos[0], destPos[1] - srcPos[1], destPos[2] - srcPos[2] }; float distSq = (diff[0] * diff[0]) + (diff[1] * diff[1]) + (diff[2] * diff[2]); if (distSq < minDistSq) { minDistSq = distSq; nearestVert = srcVert; } } destVert.BoneIndices = (byte[])nearestVert.BoneIndices.Clone(); destVert.Weights3 = (float[])nearestVert.Weights3.Clone(); } }
public float SetMorphKeyframe(xxFrame meshFrame, xaMorphIndexSet idxSet, xaMorphKeyframe keyframe, bool asStart) { foreach (AnimationFrame frame in meshFrames) { if (frame.Name == meshFrame.Name) { xxMesh xxMesh = meshFrame.Mesh; int meshObjIdx = xa.MorphMeshObjIdx(idxSet.MeshIndices, xxMesh); if (meshObjIdx < 0) { Report.ReportLog("no valid mesh object was found for the morph"); return(-1f); } MorphMeshContainer morphMesh = null; AnimationMeshContainer animMesh = frame.MeshContainer as AnimationMeshContainer; if (animMesh != null) { for (int i = 1; i < meshObjIdx; i++) { animMesh = (AnimationMeshContainer)animMesh.NextMeshContainer; if (animMesh == null) { break; } } if (animMesh == null) { Report.ReportLog("Bad submesh specified."); return(-1f); } morphMesh = new MorphMeshContainer(); morphMesh.FaceCount = xxMesh.SubmeshList[meshObjIdx].FaceList.Count; morphMesh.IndexBuffer = animMesh.MeshData.Mesh.IndexBuffer; morphMesh.VertexCount = xxMesh.SubmeshList[meshObjIdx].VertexList.Count; List <xxVertex> vertexList = xxMesh.SubmeshList[meshObjIdx].VertexList; VertexBuffer vertBuffer = CreateMorphVertexBuffer(idxSet, keyframe, vertexList); morphMesh.StartBuffer = morphMesh.EndBuffer = vertBuffer; int vertBufferSize = morphMesh.VertexCount * Marshal.SizeOf(typeof(TweeningMeshesVertexBufferFormat.Stream2)); vertBuffer = new VertexBuffer(device, vertBufferSize, Usage.WriteOnly, VertexFormat.Texture1, Pool.Managed); using (DataStream vertexStream = vertBuffer.Lock(0, vertBufferSize, LockFlags.None)) { for (int i = 0; i < vertexList.Count; i++) { xxVertex vertex = vertexList[i]; vertexStream.Write(vertex.UV[0]); vertexStream.Write(vertex.UV[1]); } vertBuffer.Unlock(); } morphMesh.CommonBuffer = vertBuffer; morphMesh.MaterialIndex = animMesh.MaterialIndex; morphMesh.TextureIndex = animMesh.TextureIndex; morphMesh.NextMeshContainer = animMesh; frame.MeshContainer = morphMesh; morphMesh.TweenFactor = 0.0f; } else { morphMesh = frame.MeshContainer as MorphMeshContainer; List <xxVertex> vertexList = xxMesh.SubmeshList[meshObjIdx].VertexList; VertexBuffer vertBuffer = CreateMorphVertexBuffer(idxSet, keyframe, vertexList); if (asStart) { if (morphMesh.StartBuffer != morphMesh.EndBuffer) { morphMesh.StartBuffer.Dispose(); } morphMesh.StartBuffer = vertBuffer; morphMesh.TweenFactor = 0.0f; } else { if (morphMesh.StartBuffer != morphMesh.EndBuffer) { morphMesh.EndBuffer.Dispose(); } morphMesh.EndBuffer = vertBuffer; morphMesh.TweenFactor = 1.0f; } } return(morphMesh.TweenFactor); } } Report.ReportLog("Mesh frame " + meshFrame + " not displayed."); return(-1f); }
private void FillVertexBuffer(Mesh animationMesh, List <xxVertex> vertexList, int selectedBoneIdx) { using (DataStream vertexStream = animationMesh.LockVertexBuffer(LockFlags.None)) { Color4 col = new Color4(1f, 1f, 1f); for (int i = 0; i < vertexList.Count; i++) { xxVertex vertex = vertexList[i]; vertexStream.Write(vertex.Position.X); vertexStream.Write(vertex.Position.Y); vertexStream.Write(vertex.Position.Z); vertexStream.Write(vertex.Weights3[0]); vertexStream.Write(vertex.Weights3[1]); vertexStream.Write(vertex.Weights3[2]); vertexStream.Write(vertex.BoneIndices[0]); vertexStream.Write(vertex.BoneIndices[1]); vertexStream.Write(vertex.BoneIndices[2]); vertexStream.Write(vertex.BoneIndices[3]); vertexStream.Write(vertex.Normal.X); vertexStream.Write(vertex.Normal.Y); vertexStream.Write(vertex.Normal.Z); if (selectedBoneIdx >= 0) { col.Red = 0f; col.Green = 0f; col.Blue = 0f; byte[] boneIndices = vertex.BoneIndices; float[] boneWeights = vertex.Weights4(true); for (int j = 0; j < boneIndices.Length; j++) { if (boneIndices[j] == 0xFF) { continue; } byte boneIdx = boneIndices[j]; if (boneIdx == selectedBoneIdx) { /* switch (cols) * { * case WeightsColourPreset.Greyscale: * col.r = col.g = col.b = boneWeights[j]; * break; * case WeightsColourPreset.Metal: * col.r = boneWeights[j] > 0.666f ? 1f : boneWeights[j] * 1.5f; * col.g = boneWeights[j] * boneWeights[j] * boneWeights[j]; * break; * WeightsColourPreset.Rainbow:*/ if (boneWeights[j] > 0.75f) { col.Red = 1f; col.Green = (1f - boneWeights[j]) * 2f; col.Blue = 0f; } else if (boneWeights[j] > 0.5f) { col.Red = 1f; col.Green = (1f - boneWeights[j]) * 2f; col.Blue = 0f; } else if (boneWeights[j] > 0.25f) { col.Red = (boneWeights[j] - 0.25f) * 4f; col.Green = 1f; col.Blue = 0f; } else { col.Green = boneWeights[j] * 4f; col.Blue = 1f - boneWeights[j] * 4f; } /* break; * }*/ break; } } } vertexStream.Write(col.ToArgb()); vertexStream.Write(vertex.UV[0]); vertexStream.Write(vertex.UV[1]); } animationMesh.UnlockVertexBuffer(); } }
private AnimationFrame CreateFrame(xxFrame frame, xxParser parser, HashSet <string> extractFrames, HashSet <string> meshNames, Device device, Matrix combinedParent, List <AnimationFrame> meshFrames) { AnimationFrame animationFrame = new AnimationFrame(); animationFrame.Name = frame.Name; animationFrame.TransformationMatrix = frame.Matrix; animationFrame.OriginalTransform = animationFrame.TransformationMatrix; animationFrame.CombinedTransform = combinedParent * animationFrame.TransformationMatrix; xxMesh mesh = frame.Mesh; if (meshNames.Contains(frame.Name) && (mesh != null)) { List <xxBone> boneList = mesh.BoneList; string[] boneNames = new string[boneList.Count]; Matrix[] boneOffsets = new Matrix[boneList.Count]; for (int i = 0; i < boneList.Count; i++) { xxBone bone = boneList[i]; boneNames[i] = bone.Name; boneOffsets[i] = bone.Matrix; } AnimationMeshContainer[] meshContainers = new AnimationMeshContainer[mesh.SubmeshList.Count]; Vector3 min = new Vector3(Single.MaxValue); Vector3 max = new Vector3(Single.MinValue); for (int i = 0; i < mesh.SubmeshList.Count; i++) { xxSubmesh submesh = mesh.SubmeshList[i]; List <xxFace> faceList = submesh.FaceList; List <xxVertex> vertexList = submesh.VertexList; Mesh animationMesh = new Mesh(device, faceList.Count, vertexList.Count, MeshFlags.Managed, PositionBlendWeightsIndexedNormalTexturedColoured.Format); using (DataStream indexStream = animationMesh.LockIndexBuffer(LockFlags.None)) { for (int j = 0; j < faceList.Count; j++) { ushort[] indices = faceList[j].VertexIndices; indexStream.Write(indices[0]); indexStream.Write(indices[2]); indexStream.Write(indices[1]); } animationMesh.UnlockIndexBuffer(); } FillVertexBuffer(animationMesh, vertexList, -1); var normalLines = new PositionBlendWeightsIndexedColored[vertexList.Count * 2]; for (int j = 0; j < vertexList.Count; j++) { xxVertex vertex = vertexList[j]; normalLines[j * 2] = new PositionBlendWeightsIndexedColored(vertex.Position, vertex.Weights3, vertex.BoneIndices, Color.Yellow.ToArgb()); normalLines[(j * 2) + 1] = new PositionBlendWeightsIndexedColored(vertex.Position + (vertex.Normal / 16), vertex.Weights3, vertex.BoneIndices, Color.Yellow.ToArgb()); min = Vector3.Minimize(min, vertex.Position); max = Vector3.Maximize(max, vertex.Position); } AnimationMeshContainer meshContainer = new AnimationMeshContainer(); meshContainer.Name = animationFrame.Name; meshContainer.MeshData = new MeshData(animationMesh); meshContainer.NormalLines = normalLines; meshContainers[i] = meshContainer; int matIdx = submesh.MaterialIndex; if ((matIdx >= 0) && (matIdx < parser.MaterialList.Count)) { int texIdx; if (!MatTexIndices.TryGetValue(matIdx, out texIdx)) { texIdx = -1; xxMaterial mat = parser.MaterialList[matIdx]; Material materialD3D = new Material(); materialD3D.Ambient = mat.Ambient; materialD3D.Diffuse = mat.Diffuse; materialD3D.Emissive = mat.Emissive; materialD3D.Specular = mat.Specular; materialD3D.Power = mat.Power; Materials[matIdx] = materialD3D; xxMaterialTexture matTex = mat.Textures[0]; string matTexName = matTex.Name; if (matTexName != String.Empty) { for (int j = 0; j < parser.TextureList.Count; j++) { xxTexture tex = parser.TextureList[j]; if (tex.Name == matTexName) { texIdx = j; if (Textures[j] == null) { ImportedTexture importedTex = xx.ImportedTexture(tex); Textures[j] = Texture.FromMemory(device, importedTex.Data); } break; } } } MatTexIndices.Add(matIdx, texIdx); } meshContainer.MaterialIndex = matIdx; meshContainer.TextureIndex = texIdx; } } for (int i = 0; i < (meshContainers.Length - 1); i++) { meshContainers[i].NextMeshContainer = meshContainers[i + 1]; } for (int i = 0; i < meshContainers.Length; i++) { meshContainers[i].BoneNames = boneNames; meshContainers[i].BoneOffsets = boneOffsets; } min = Vector3.TransformCoordinate(min, animationFrame.CombinedTransform); max = Vector3.TransformCoordinate(max, animationFrame.CombinedTransform); animationFrame.Bounds = new BoundingBox(min, max); animationFrame.MeshContainer = meshContainers[0]; meshFrames.Add(animationFrame); } for (int i = 0; i < frame.Count; i++) { xxFrame child = frame[i]; if (extractFrames.Contains(child.Name)) { AnimationFrame childAnimationFrame = CreateFrame(child, parser, extractFrames, meshNames, device, animationFrame.CombinedTransform, meshFrames); childAnimationFrame.Parent = animationFrame; animationFrame.AppendChild(childAnimationFrame); } } numFrames++; return(animationFrame); }
public static void CreateUnknown(xxVertex vertex) { vertex.Unknown1 = new byte[20]; }
public static void CalculateNormals(List <Tuple <List <xxFace>, List <xxVertex> > > pairList, float threshold) { if (threshold < 0) { VertexRef[][] vertRefArray = new VertexRef[pairList.Count][]; for (int i = 0; i < pairList.Count; i++) { List <xxVertex> vertList = pairList[i].Item2; vertRefArray[i] = new VertexRef[vertList.Count]; for (int j = 0; j < vertList.Count; j++) { xxVertex vert = vertList[j]; VertexRef vertRef = new VertexRef(); vertRef.vert = vert; vertRef.norm = new Vector3(); vertRefArray[i][j] = vertRef; } } for (int i = 0; i < pairList.Count; i++) { List <xxFace> faceList = pairList[i].Item1; for (int j = 0; j < faceList.Count; j++) { xxFace face = faceList[j]; Vector3 v1 = vertRefArray[i][face.VertexIndices[1]].vert.Position - vertRefArray[i][face.VertexIndices[2]].vert.Position; Vector3 v2 = vertRefArray[i][face.VertexIndices[0]].vert.Position - vertRefArray[i][face.VertexIndices[2]].vert.Position; Vector3 norm = Vector3.Cross(v2, v1); norm.Normalize(); for (int k = 0; k < face.VertexIndices.Length; k++) { vertRefArray[i][face.VertexIndices[k]].norm += norm; } } } for (int i = 0; i < vertRefArray.Length; i++) { for (int j = 0; j < vertRefArray[i].Length; j++) { Vector3 norm = vertRefArray[i][j].norm; norm.Normalize(); vertRefArray[i][j].vert.Normal = norm; } } } else { int vertCount = 0; for (int i = 0; i < pairList.Count; i++) { vertCount += pairList[i].Item2.Count; } VertexRefComparerX vertRefComparerX = new VertexRefComparerX(); List <VertexRef> vertRefListX = new List <VertexRef>(vertCount); VertexRef[][] vertRefArray = new VertexRef[pairList.Count][]; for (int i = 0; i < pairList.Count; i++) { var vertList = pairList[i].Item2; vertRefArray[i] = new VertexRef[vertList.Count]; for (int j = 0; j < vertList.Count; j++) { xxVertex vert = vertList[j]; VertexRef vertRef = new VertexRef(); vertRef.vert = vert; vertRef.norm = new Vector3(); vertRefArray[i][j] = vertRef; vertRefListX.Add(vertRef); } } vertRefListX.Sort(vertRefComparerX); for (int i = 0; i < pairList.Count; i++) { var faceList = pairList[i].Item1; for (int j = 0; j < faceList.Count; j++) { xxFace face = faceList[j]; Vector3 v1 = vertRefArray[i][face.VertexIndices[1]].vert.Position - vertRefArray[i][face.VertexIndices[2]].vert.Position; Vector3 v2 = vertRefArray[i][face.VertexIndices[0]].vert.Position - vertRefArray[i][face.VertexIndices[2]].vert.Position; Vector3 norm = Vector3.Cross(v2, v1); norm.Normalize(); for (int k = 0; k < face.VertexIndices.Length; k++) { vertRefArray[i][face.VertexIndices[k]].norm += norm; } } } float squaredThreshold = threshold * threshold; while (vertRefListX.Count > 0) { VertexRef vertRef = vertRefListX[vertRefListX.Count - 1]; List <VertexRef> dupList = new List <VertexRef>(); List <VertexRef> dupListX = GetAxisDups(vertRef, vertRefListX, 0, threshold, null); foreach (VertexRef dupRef in dupListX) { if (((vertRef.vert.Position.Y - dupRef.vert.Position.Y) <= threshold) && ((vertRef.vert.Position.Z - dupRef.vert.Position.Z) <= threshold) && ((vertRef.vert.Position - dupRef.vert.Position).LengthSquared() <= squaredThreshold)) { dupList.Add(dupRef); } } vertRefListX.RemoveAt(vertRefListX.Count - 1); Vector3 norm = vertRef.norm; foreach (VertexRef dupRef in dupList) { norm += dupRef.norm; vertRefListX.Remove(dupRef); } norm.Normalize(); vertRef.vert.Normal = norm; foreach (VertexRef dupRef in dupList) { dupRef.vert.Normal = norm; vertRefListX.Remove(dupRef); } } } }