private void _LoadBone(BlendTypeRepository repository, BlendValueCapsule bone, int parentBoneIndex, ref List <DrawSystem.BoneData> outList) { if (bone != null) { // make bone data var name = bone.GetMember("name").GetAllValueAsString(); float length = bone.GetMember("length").GetRawValue <float>(); var offset = new Vector3() { X = bone.GetMember("head").GetAt(0).GetRawValue <float>(), Y = bone.GetMember("head").GetAt(1).GetRawValue <float>(), Z = bone.GetMember("head").GetAt(2).GetRawValue <float>(), }; offset = BlenderUtil.ChangeCoordsSystem(offset); var elements = new float[16]; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { elements[i * 4 + j] = bone.GetMember("arm_mat").GetAt(i, j).GetRawValue <float>(); } } var modelTrans = new Matrix(elements); modelTrans = BlenderUtil.ChangeCoordsSystem(modelTrans); var result = new DrawSystem.BoneData() { Name = name, Parent = parentBoneIndex, BoneTransform = modelTrans, // convert local bone transformation after BoneOffset = Matrix.Invert(modelTrans), Length = length, }; outList.Add(result); parentBoneIndex = outList.Count() - 1; //Console.WriteLine(" found bone : " + name); // call for children var childBone = bone.GetMember("childbase").GetMember("first").GetRawValue <BlendAddress>().DereferenceOne(); while (childBone != null) { _LoadBone(repository, childBone, parentBoneIndex, ref outList); childBone = childBone.GetMember("next").GetRawValue <BlendAddress>().DereferenceOne(); } } }
private bool _LoadScene(BlendTypeRepository repository, List <BlockHeaderEntity> entityList) { // find root BlendValueCapsule root = entityList.Where(e => e.Name == "GLOB").Select(e => e.Children[0].Value).First(); if (root == null) { return(false); } var scene = root.GetMember("curscene").GetRawValue <BlendAddress>().DereferenceOne(); var listBase = scene.GetMember("base"); var nextBase = listBase.GetMember("first").GetRawValue <BlendAddress>().DereferenceOne(); // load mesh while (nextBase != null) { var obj = nextBase.GetMember("object").GetRawValue <BlendAddress>().DereferenceOne(); if (obj != null) { string name = obj.GetMember("id").GetMember("name").GetAllValueAsString(); int restrictFlag = obj.GetMember("restrictflag").GetRawValue <char>(); if ((restrictFlag & 1) != 0) { // invisible object } var data = obj.GetMember("data").GetRawValue <BlendAddress>().DereferenceOne(); if (data != null && data.Type.Name == "Mesh") { // mesh object Console.WriteLine("found mesh : " + name); if (!_LoadMesh(repository, obj)) { return(false); } } var groupId = obj.GetMember("dup_group").GetRawValue <BlendAddress>().DereferenceOne(); if (groupId != null) { // link object Console.WriteLine("found link obj: " + name); var lib = groupId.GetMember("lib").GetRawValue <BlendAddress>().DereferenceOne(); var path = lib.GetMember("filepath").GetAllValueAsString(); // make layout matrix var elements = new float[16]; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { elements[i * 4 + j] = obj.GetMember("obmat").GetAt(i, j).GetRawValue <float>(); } } var layoutTrans = new Matrix(elements); layoutTrans = BlenderUtil.ChangeCoordsSystem(layoutTrans); var node = new LinkNode() { Name = name, Layout = layoutTrans, TargetFileName = Path.GetFileName(path), }; m_linkList.Add(node); } } nextBase = nextBase.GetMember("next").GetRawValue <BlendAddress>().DereferenceOne(); } return(true); }
private void _LoadAction(BlendTypeRepository repository, BlendValueCapsule bAnimAction, ref List <AnimType.ActionData> animActionList) { var groupList = new List <AnimType.ActionGroupData>(); var bGroup = bAnimAction.GetMember("groups").GetMember("first").GetRawValue <BlendAddress>().DereferenceOne(); while (bGroup != null) { var groupData = new AnimType.ActionGroupData(); groupData.BoneName = bGroup.GetMember("name").GetAllValueAsString(); groupData.Location = AnimType.ChannelData <Vector3> .Empty(); groupData.Rotation = AnimType.ChannelData <Quaternion> .Empty(); groupData.Scale = AnimType.ChannelData <Vector3> .Empty(); //Console.WriteLine(" found anim action group : " + groupData.BoneName); var channelList = new List <AnimType.ChannelData <float> >(); var bChannel = bGroup.GetMember("channels").GetMember("first").GetRawValue <BlendAddress>().DereferenceOne(); while (bChannel != null) { string boneName = ""; string propertyName = ""; var bRnaPath = bChannel.GetMember("rna_path").GetRawValue <BlendAddress>().DereferenceAll(Blender.BlendPrimitiveType.Char()); string rnaPath = Blender.ConvertUtil.CharArray2String(bRnaPath.Select(c => (object)c.GetRawValue <char>())); if (!BlenderUtil.ParseRnaPath(rnaPath, ref boneName, ref propertyName)) { Debug.Fail("Failed to parse rna path(" + rnaPath + ")"); return; } int arrayIndex = bChannel.GetMember("array_index").GetRawValue <int>(); if (boneName == groupData.BoneName) { //Console.WriteLine(String.Format(" {0}.{1}[{2}]", boneName, propertyName, arrayIndex)); var bBeztList = bChannel.GetMember("bezt").GetRawValue <BlendAddress>().DereferenceAll(); var channel = new AnimType.ChannelData <float>(); channel.KeyFrames = new AnimType.KeyData <float> [bBeztList.Count()]; foreach (var bBezt in bBeztList.Select((value, index) => new { value, index })) { float frame = bBezt.value.GetMember("vec").GetAt(1, 0).GetRawValue <float>(); float value = bBezt.value.GetMember("vec").GetAt(1, 1).GetRawValue <float>(); channel.KeyFrames[bBezt.index] = new AnimType.KeyData <float>((int)frame, value); } channelList.Add(channel); } bChannel = bChannel.GetMember("next").GetRawValue <BlendAddress>().DereferenceOne(); } // while if (channelList.Count() == 10) { // channel type convertion // location : floatx3 to Vector3 // rotation : floatx4 to Quatanion // scale : floatx3 to Vector3 groupData.Location.KeyFrames = channelList[0].KeyFrames .Select((key, index) => new AnimType.KeyData <Vector3>(key.Frame, new Vector3(key.Value, channelList[1].KeyFrames[index].Value, channelList[2].KeyFrames[index].Value))) .Select(key => { key.Value = BlenderUtil.ChangeCoordsSystem(key.Value); return(key); }) //.Select(key => { key.Frame--; return key; }) // blender frame index starts from 1 .ToArray(); groupData.Rotation.KeyFrames = channelList[3].KeyFrames .Select((key, index) => new AnimType.KeyData <Quaternion>(key.Frame, new Quaternion(channelList[4].KeyFrames[index].Value, channelList[5].KeyFrames[index].Value, channelList[6].KeyFrames[index].Value, key.Value))) .Select(key => { key.Value = BlenderUtil.ChangeCoordsSystem(key.Value); return(key); }) //.Select(key => { key.Frame--; return key; }) // blender frame index starts from 1 .ToArray(); groupData.Scale.KeyFrames = channelList[7].KeyFrames .Select((key, index) => new AnimType.KeyData <Vector3>(key.Frame, new Vector3(key.Value, channelList[8].KeyFrames[index].Value, channelList[9].KeyFrames[index].Value))) .Select(key => { key.Value = BlenderUtil.ChangeCoordsSystem(key.Value); return(key); }) //.Select(key => { key.Frame--; return key; }) // blender frame index starts from 1 .ToArray(); groupList.Add(groupData); bGroup = bGroup.GetMember("next").GetRawValue <BlendAddress>().DereferenceOne(); } else { Debug.Fail("unexpected the number of channels."); return; } } if (groupList.Count != 0) { var actionData = new AnimType.ActionData(); var actionName = bAnimAction.GetMember("id").GetMember("name").GetAllValueAsString(); actionName = actionName.Substring(2, actionName.Length - 2); // ACArmatureAction => ArmatureAction actionData.Name = actionName; actionData.Groups = groupList.ToArray(); animActionList.Add(actionData); } }
private VertexOriginal[] _CreateOriginalVertices(BlendTypeRepository repository, BlendValueCapsule mesh, int[] deformGroupIndex2BoneIndex) { var mpolyList = mesh.GetMember("mpoly").GetRawValue <BlendAddress>().DereferenceAll(); var mloopList = mesh.GetMember("mloop").GetRawValue <BlendAddress>().DereferenceAll(); var mloopuvList = mesh.GetMember("mloopuv").GetRawValue <BlendAddress>().DereferenceAll(); var mvertList = mesh.GetMember("mvert").GetRawValue <BlendAddress>().DereferenceAll(); var dvertList = mesh.GetMember("dvert").GetRawValue <BlendAddress>().DereferenceAll(); int capacity = mpolyList.Count() * 6; // assume that all polygons is square. var vertices = new List <VertexOriginal>(capacity); foreach (var mpoly in mpolyList) { int offset = mpoly.GetMember("loopstart").GetRawValue <int>(); int count = mpoly.GetMember("totloop").GetRawValue <int>(); short materialIndex = mpoly.GetMember("mat_nr").GetRawValue <short>(); Debug.Assert(count >= 0, "negative totloop is here!"); // todo: ref previous loop int[] plan = null; switch (count) { case 3: plan = new int[] { offset + 2, offset + 1, offset + 0 }; break; case 4: // triangulation plan = new int[] { offset + 2, offset + 1, offset, offset + 3, offset + 2, offset }; break; default: Debug.Fail("tutloop must be 3 or 4"); // todo: ref previous loop break; } if (plan == null) { continue; } foreach (int i in plan) { int vIndex = mloopList[i].GetMember("v").GetRawValue <int>(); var position = mvertList[vIndex].GetMember("co"); var normal = mvertList[vIndex].GetMember("no"); VertexOriginal vertex; vertex.Position.X = position.GetAt(0).GetRawValue <float>(); vertex.Position.Y = position.GetAt(1).GetRawValue <float>(); vertex.Position.Z = position.GetAt(2).GetRawValue <float>(); vertex.Position.W = 1; vertex.Position = BlenderUtil.ChangeCoordsSystem(vertex.Position); vertex.Normal.X = normal.GetAt(0).GetRawValue <short>(); vertex.Normal.Y = normal.GetAt(1).GetRawValue <short>(); vertex.Normal.Z = normal.GetAt(2).GetRawValue <short>(); vertex.Normal = BlenderUtil.ChangeCoordsSystem(vertex.Normal); vertex.Normal.Normalize(); var uv = mloopuvList[i].GetMember("uv"); vertex.Texcoord.X = uv.GetAt(0).GetRawValue <float>(); vertex.Texcoord.Y = 1 - uv.GetAt(1).GetRawValue <float>(); vertex.Tangent = Vector3.Zero; vertex.Binormal = Vector3.Zero; vertex.MaterialIndex = materialIndex; var weights = dvertList == null ? null : dvertList[vIndex].GetMember("dw").GetRawValue <BlendAddress>().DereferenceAll(); if (weights == null || deformGroupIndex2BoneIndex == null) { vertex.BoneWeights = null; vertex.BoneIndices = null; } else { // load bone weights // bone weight can be stored 0, so we ignore this case. //int maxWeightCount = dvertList[vIndex].GetMember("totweight").GetRawValue<int>(); var noneZeroWeightList = weights.Select(w => new Tuple <float, int>(w.GetMember("weight").GetRawValue <float>(), w.GetMember("def_nr").GetRawValue <int>())) .OrderByDescending(tuple => tuple.Item1) // sort by descending .Where(tuple => tuple.Item1 > 0.0f); // ignore zero value too int weightCount = noneZeroWeightList.Count(); vertex.BoneWeights = new float[weightCount]; vertex.BoneIndices = new uint[weightCount]; int wIndex = 0; foreach (var tuple in noneZeroWeightList) { float weight = tuple.Item1; int deformGroupIndex = tuple.Item2; vertex.BoneWeights[wIndex] = weight; // def_nr is NOT index of bones, but index of deform group // we must replace to index of bones using bone-deform mapping. vertex.BoneIndices[wIndex] = (uint)deformGroupIndex2BoneIndex[deformGroupIndex]; wIndex++; } } vertices.Add(vertex); } } // compute tangent and binormal int polyCount = vertices.Count / 3; for (int polyIndex = 0; polyIndex < polyCount; ++polyIndex) { var posArray = new Vector4[] { vertices[polyIndex * 3].Position, vertices[polyIndex * 3 + 1].Position, vertices[polyIndex * 3 + 2].Position, }; var normalArray = new Vector3[] { vertices[polyIndex * 3].Normal, vertices[polyIndex * 3 + 1].Normal, vertices[polyIndex * 3 + 2].Normal, }; var uvArray = new Vector2[] { vertices[polyIndex * 3].Texcoord, vertices[polyIndex * 3 + 1].Texcoord, vertices[polyIndex * 3 + 2].Texcoord, }; var faceTangent = MathUtil.ComputeFaceTangent(posArray[0], posArray[1], posArray[2], uvArray[0], uvArray[1], uvArray[2]); for (int vIndex = 0; vIndex < 3; ++vIndex) { // calc tangent var normal = normalArray[vIndex]; var tangent = faceTangent; MathUtil.Orthonormalize(ref normal, ref tangent); // calc binormal var binormal = Vector3.Cross(normalArray[vIndex], tangent); //binormal.Normalize(); var oldVertex = vertices[polyIndex * 3 + vIndex]; oldVertex.Tangent = tangent; oldVertex.Binormal = binormal; vertices[polyIndex * 3 + vIndex] = oldVertex; } } return(vertices.ToArray()); }