public void Export(string filePath) { PalletProperties palletProperties = _palletSolution.Analysis.PalletProperties; COLLADA model = new COLLADA(); // asset model.asset = new asset() { created = DateTime.Now, modified = DateTime.Now }; model.asset.keywords = "StackBuilder Pallet Case"; model.asset.title = _palletSolution.Title; model.asset.unit = new assetUnit() { name = "millimeters", meter = 0.001 }; model.asset.up_axis = UpAxisType.Z_UP; library_images images = new library_images(); library_materials materials = new library_materials(); library_effects effects = new library_effects(); library_geometries geometries = new library_geometries(); library_nodes nodes = new library_nodes(); library_cameras cameras = new library_cameras(); library_animations animations = new library_animations(); library_visual_scenes scenes = new library_visual_scenes(); COLLADAScene colladaScene = new COLLADAScene(); model.Items = new Object[] { images, materials, effects, geometries, nodes, cameras, animations, scenes }; model.scene = colladaScene; // colors and materials List<effect> listEffects = new List<effect>(); List<material> listMaterials = new List<material>(); List<image> listImages = new List<image>(); // effects effect effectPallet; material materialPallet; CreateMaterial(palletProperties.Color, null, null, "Pallet", out effectPallet, out materialPallet); listEffects.Add(effectPallet); listMaterials.Add(materialPallet); Box box = new Box(0, _palletSolution.Analysis.BProperties); // build list of effects / materials / images uint faceIndex = 0; foreach (Face face in box.Faces) { // build texture image if any string textureName = null; if (face.HasBitmap) { textureName = string.Format("textureFace_{0}", faceIndex); string texturePath = System.IO.Path.Combine( System.IO.Path.GetDirectoryName(filePath) , textureName + ".jpg"); double dimX = 0.0, dimY = 0.0; switch (faceIndex) { case 0: dimX = box.Width; dimY = box.Height; break; case 1: dimX = box.Width; dimY = box.Height; break; case 2: dimX = box.Length; dimY = box.Height; break; case 3: dimX = box.Length; dimY = box.Height; break; case 4: dimX = box.Length; dimY = box.Width; break; case 5: dimX = box.Length; dimY = box.Width; break; default: break; } face.ExtractFaceBitmap(dimX, dimY, _bmpWidth, texturePath); // create image listImages.Add( new image() { id = textureName + ".jpg", name = textureName + ".jpg", Item = @".\" + textureName + @".jpg" } ); } material materialCase; effect effectCase; CreateMaterial(face.ColorFill, textureName, "0", string.Format("Case{0}", faceIndex), out effectCase, out materialCase); listEffects.Add(effectCase); listMaterials.Add(materialCase); ++faceIndex; } // add to image list images.image = listImages.ToArray(); // case lines material effect effectCaseLines; material materialCaseLines; CreateMaterial(Color.Black, null, null, "CaseLines", out effectCaseLines, out materialCaseLines); listEffects.Add(effectCaseLines); listMaterials.Add(materialCaseLines); effects.effect = listEffects.ToArray(); materials.material = listMaterials.ToArray(); // geometries geometry geomPallet = new geometry() { id = "palletGeometry", name = "palletGeometry" }; geometry geomCase = new geometry() { id = "caseGeometry", name = "caseGeometry" }; geometries.geometry = new geometry[] { geomPallet, geomCase }; // pallet mesh meshPallet = CreatePalletMesh(palletProperties); geomPallet.Item = meshPallet; // case mesh meshCase = CreateCaseMesh(_palletSolution.Analysis.BProperties as BoxProperties); geomCase.Item = meshCase; // library_animations animation animationMain = new animation() { id = "animationMain_ID", name = "animationMain" }; animations.animation = new animation[] { animationMain }; List<object> listAnimationSource = new List<object>(); // library_visual_scenes visual_scene mainScene = new visual_scene() { id = "MainScene", name = "MainScene" }; scenes.visual_scene = new visual_scene[] { mainScene }; List<node> sceneNodes = new List<node>(); sceneNodes.Add(new node() { id = "PalletNode", name = "PalletNode", instance_geometry = new instance_geometry[] { new instance_geometry() { url = "#palletGeometry", bind_material = new bind_material() { technique_common = new instance_material[] { new instance_material() { symbol="materialPallet", target=string.Format("#{0}", materialPallet.id) } } } } } }); uint caseIndex = 0; foreach (ILayer layer in _palletSolution) { BoxLayer bLayer = layer as BoxLayer; if (null == bLayer) continue; foreach (BoxPosition bp in bLayer) { Vector3D translation = bp.Position; Vector3D rotations = bp.Transformation.Rotations; node caseNode = new node() { id = string.Format("CaseNode_{0}_ID", caseIndex), name = string.Format("CaseNode_{0}", caseIndex), ItemsElementName = new ItemsChoiceType2[] { ItemsChoiceType2.translate, ItemsChoiceType2.rotate, ItemsChoiceType2.rotate, ItemsChoiceType2.rotate }, Items = new object[] { new TargetableFloat3() { Values = new double[] { translation.X, translation.Y, translation.Z }, sid = "t", }, new rotate() { Values = new double[] { 1.0, 0.0, 0.0, rotations.X }, sid = "rx" }, new rotate() { Values = new double[] { 0.0, 1.0, 0.0, rotations.Y }, sid = "ry" }, new rotate() { Values = new double[] { 0.0, 0.0, 1.0, rotations.Z }, sid = "rz" } }, instance_geometry = new instance_geometry[] { new instance_geometry() { url="#caseGeometry", bind_material = new bind_material() { technique_common = new instance_material[] { new instance_material() { symbol="materialCase0", target="#material_Case0_ID" }, new instance_material() { symbol="materialCase1", target="#material_Case1_ID" }, new instance_material() { symbol="materialCase2", target="#material_Case2_ID" }, new instance_material() { symbol="materialCase3", target="#material_Case3_ID" }, new instance_material() { symbol="materialCase4", target="#material_Case4_ID" }, new instance_material() { symbol="materialCase5", target="#material_Case5_ID" }, new instance_material() { symbol="materialCaseLines", target="#material_CaseLines_ID"} } } } } }; sceneNodes.Add(caseNode); // animations CreateAnimation(caseIndex, (uint)_palletSolution.CaseCount, listAnimationSource, bp); // increment case index ++caseIndex; } } // add nodes mainScene.node = sceneNodes.ToArray(); animationMain.Items = listAnimationSource.ToArray(); // library_cameras camera cameraCamera = new camera() { id = "Camera-Camera", name = "Camera-Camera" }; cameraOpticsTechnique_commonPerspective cameraPerspective = new cameraOpticsTechnique_commonPerspective() { znear = new TargetableFloat() { sid = "znear", Value = 1.0 }, zfar = new TargetableFloat() { sid = "zfar", Value = 10000.0 } }; cameraCamera.optics = new cameraOptics() { technique_common = new cameraOpticsTechnique_common() { Item = cameraPerspective } }; cameras.camera = new camera[] { cameraCamera }; // colladaScene colladaScene.instance_visual_scene = new InstanceWithExtra() { url = "#MainScene" }; model.Save(filePath); model.Save(System.IO.Path.ChangeExtension(filePath, "xml")); }
public CL.node GetNode(int index, Matrix4x4 transform, string name) { var n = new CL.node(); if (index != 0) { name += "_lod" + index; } n.name = n.id = name; n.Items = new object[] { new CL.matrix() { sid = "transform", Text = MatrixText(transform) } }; n.ItemsElementName = new CL.ItemsChoiceType7[] { CL.ItemsChoiceType7.matrix }; n.instance_geometry = new CL.instance_geometry[] { new CL.instance_geometry { url = "#" + Geometries[index].id, bind_material = new CL.bind_material() { technique_common = GetMaterials(Geometries[index]) } } }; return(n); }
public static Bone FromCollada(node bone, int parentIndex, List<Bone> bones, Dictionary<string, Bone> boneSIDs, Dictionary<string, Bone> boneIDs) { var transMat = ColladaHelpers.TransformFromNode(bone); var colladaBone = new Bone(); colladaBone.TransformSID = transMat.TransformSID; var myIndex = bones.Count; bones.Add(colladaBone); boneSIDs.Add(bone.sid, colladaBone); if (bone.id != null) { boneIDs.Add(bone.id, colladaBone); } colladaBone.ParentIndex = parentIndex; colladaBone.Name = bone.name; colladaBone.LODError = 0; // TODO colladaBone.Transform = transMat.transform; colladaBone.UpdateInverseWorldTransform(bones); if (bone.node1 != null) { foreach (var node in bone.node1) { if (node.type == NodeType.JOINT) { FromCollada(node, myIndex, bones, boneSIDs, boneIDs); } } } return colladaBone; }
static ColladaObject ProcessNode(CL.UpAxisType up, CL.library_geometries geom, CL.node n, CL.library_materials matlib, CL.library_effects fxlib) { var obj = new ColladaObject(); obj.Name = n.name; obj.ID = n.id; if (n.instance_geometry != null && n.instance_geometry.Length > 0) { //Geometry object if (n.instance_geometry.Length != 1) { throw new Exception("How to handle multiple geometries/node?"); } var uri = CheckURI(n.instance_geometry[0].url); var g = geom.geometry.Where((x) => x.id == uri).First(); if (g.Item is CL.mesh) { obj.Geometry = GetGeometry(up, g, matlib, fxlib); } else if (g.Item is CL.spline) { obj.Spline = GetSpline(up, g); } } if (n.Items.OfType <CL.matrix>().Any()) { var tr = n.Items.OfType <CL.matrix>().First(); obj.Transform = GetMatrix(up, tr.Text); } else { Matrix4x4 mat = Matrix4x4.Identity; foreach (var item in n.Items) { if (item is CL.TargetableFloat3) { //var float3 = } } obj.Transform = mat; } if (n.node1 != null && n.node1.Length > 0) { foreach (var node in n.node1) { obj.Children.Add(ProcessNode(up, geom, node, matlib, fxlib)); } } return(obj); }
public static Skeleton FromCollada(node root) { var skeleton = new Skeleton(); skeleton.Bones = new List<Bone>(); skeleton.LODType = 0; skeleton.Name = root.name; skeleton.BonesBySID = new Dictionary<string, Bone>(); skeleton.BonesByID = new Dictionary<string, Bone>(); Bone.FromCollada(root, -1, skeleton.Bones, skeleton.BonesBySID, skeleton.BonesByID); return skeleton; }
public node MakeCollada(string parentName) { var node = new node(); node.id = "Bone_" + Name.Replace(' ', '_'); node.name = Name; // .Replace(' ', '_'); node.sid = Name.Replace(' ', '_'); node.type = NodeType.JOINT; var transforms = new List<object>(); var transformTypes = new List<ItemsChoiceType2>(); if (false) // Separate transforms { var rotationX = new rotate(); rotationX.sid = "RotateX"; transforms.Add(rotationX); transformTypes.Add(ItemsChoiceType2.rotate); var rotationY = new rotate(); rotationY.sid = "RotateY"; transforms.Add(rotationY); transformTypes.Add(ItemsChoiceType2.rotate); var rotationZ = new rotate(); rotationZ.sid = "RotateZ"; transforms.Add(rotationZ); transformTypes.Add(ItemsChoiceType2.rotate); if ((Transform.Flags & (uint)Transform.TransformFlags.HasRotation) != 0) { var rot = Transform.Rotation.Normalized(); //var x = Math.Atan2(2 * (rot.W * rot.X + rot.Y * rot.Z), 1 - 2 * (rot.X * rot.X + rot.Y * rot.Y)); //var y = Math.Asin(2 * (rot.W * rot.Y - rot.X * rot.Z)); //var z = Math.Atan2(2 * (rot.W * rot.Z + rot.X * rot.Y), 1 - 2 * (rot.Y * rot.Y + rot.Z * rot.Z)); //var x = Math.Atan2(2 * rot.Y * rot.W - 2 * rot.X * rot.Z, 1 - 2 * (rot.Y * rot.Y + rot.Z * rot.Z)); //var y = Math.Asin(2 * (rot.X * rot.Y + rot.Z * rot.W)); //var z = Math.Atan2(2 * rot.X * rot.W - 2 * rot.Y * rot.Z, 1 - 2 * (rot.X * rot.X + rot.Z * rot.Z)); var q = new float[] { rot.X, rot.Y, rot.Z, rot.W }; // sedris z-y-x /*var x = Math.Atan2(q[2] * q[3] + q[0] * q[1], 0.5f - (q[1] * q[1] + q[2] * q[2])); var y = Math.Asin(-2 * (q[1] * q[3] - q[0] * q[2])); var z = Math.Atan2(q[1] * q[2] + q[0] * q[3], 0.5f - (q[2] * q[2] + q[3] * q[3]));*/ var sqw = rot.W * rot.W; var sqx = rot.X * rot.X; var sqy = rot.Y * rot.Y; var sqz = rot.Z * rot.Z; var x = Math.Atan2(2.0 * (rot.X * rot.Y + rot.Z * rot.W), (sqx - sqy - sqz + sqw)); var z = Math.Atan2(2.0 * (rot.Y * rot.Z + rot.X * rot.W), (-sqx - sqy + sqz + sqw)); var y = Math.Asin(-2.0 * (rot.X * rot.Z - rot.Y * rot.W) / (sqx + sqy + sqz + sqw)); rotationX.Values = new double[] { 1.0, 0.0, 0.0, x * 180 / Math.PI }; rotationY.Values = new double[] { 0.0, 1.0, 0.0, y * 180 / Math.PI }; rotationZ.Values = new double[] { 0.0, 0.0, 1.0, z * 180 / Math.PI }; var axisAngle = Transform.Rotation.ToAxisAngle(); //rotation.Values = new double[] { axisAngle.X, axisAngle.Y, axisAngle.Z, axisAngle.W * 180 / Math.PI }; //rotationX.Values = new double[] { axisAngle.X, 0.0, 0.0, axisAngle.W * 180 / Math.PI }; //rotationY.Values = new double[] { 0.0, axisAngle.Y, 0.0, axisAngle.W * 180 / Math.PI }; //rotationZ.Values = new double[] { 0.0, 0.0, axisAngle.Z, axisAngle.W * 180 / Math.PI }; /*rotationX.Values = new double[] { 1.0, 0.0, 0.0, axisAngle.X * axisAngle.W * 180 / Math.PI }; rotationY.Values = new double[] { 0.0, 1.0, 0.0, axisAngle.Y * axisAngle.W * 180 / Math.PI }; rotationZ.Values = new double[] { 0.0, 0.0, 1.0, axisAngle.Z * axisAngle.W * 180 / Math.PI };*/ } else { rotationX.Values = new double[] { 1.0, 0.0, 0.0, 0.0 }; rotationY.Values = new double[] { 0.0, 0.0, 0.0, 0.0 }; rotationZ.Values = new double[] { 0.0, 0.0, 0.0, 0.0 }; } var scale = new TargetableFloat3(); scale.sid = "Scale"; transforms.Add(scale); transformTypes.Add(ItemsChoiceType2.scale); if ((Transform.Flags & (uint)Transform.TransformFlags.HasScaleShear) != 0) { var scaleShear = Transform.ScaleShear.Diagonal; scale.Values = new double[] { scaleShear.X, scaleShear.Y, scaleShear.Z }; } else { scale.Values = new double[] { 1.0, 1.0, 1.0 }; } var translate = new TargetableFloat3(); translate.sid = "Translate"; transforms.Add(translate); transformTypes.Add(ItemsChoiceType2.translate); if ((Transform.Flags & (uint)Transform.TransformFlags.HasTranslation) != 0) { var transVec = Transform.Translation; translate.Values = new double[] { transVec.X, transVec.Y, transVec.Z }; } else { translate.Values = new double[] { 0.0, 0.0, 0.0 }; } } else { var transform = new matrix(); transform.sid = "Transform"; var mat = Transform.ToMatrix4(); mat.Transpose(); transform.Values = new double[] { mat[0, 0], mat[0, 1], mat[0, 2], mat[0, 3], mat[1, 0], mat[1, 1], mat[1, 2], mat[1, 3], mat[2, 0], mat[2, 1], mat[2, 2], mat[2, 3], mat[3, 0], mat[3, 1], mat[3, 2], mat[3, 3] }; transforms.Add(transform); transformTypes.Add(ItemsChoiceType2.matrix); } node.Items = transforms.ToArray(); node.ItemsElementName = transformTypes.ToArray(); return node; }
private node FindNodeInTree(node parent, string nodeID) { if (parent.id == null) return null; if (parent.id.Equals(nodeID)) { return parent; } else if (parent.node1 != null && parent.node1.Length > 0) { foreach (node child in parent.node1) { node result = FindNodeInTree(child, nodeID); if (result != null) return result; } } return null; }
private static void ReadNodeTransformations(node nodeNODE, ref Vector3 nodeScale, ref Vector3 nodeRotation, ref Vector3 nodeTranslation) { List<Tuple<Vector3, TransformationType>> transforms = new List<Tuple<Vector3, TransformationType>>(); bool matrixBacked = false; for (int i = 0; i < ((nodeNODE.Items != null) ? nodeNODE.Items.Length : 0); i++) { var item = nodeNODE.Items[i]; if (nodeNODE.ItemsElementName[i].Equals(ItemsChoiceType2.matrix)) { Matrix4 nodeMatrix = Helper.DoubleArrayToMatrix4((item as matrix).Values); Helper.DecomposeSRTMatrix1(nodeMatrix, out nodeScale, out nodeRotation, out nodeTranslation); matrixBacked = true; } else { if (nodeNODE.ItemsElementName[i].Equals(ItemsChoiceType2.translate)) { var translate = item as TargetableFloat3; Vector3 tmp = new Vector3((float)translate.Values[0], (float)translate.Values[1], (float)translate.Values[2]); transforms.Add(new Tuple<Vector3, TransformationType>(tmp, TransformationType.TranslationXYZ)); } else if (nodeNODE.ItemsElementName[i].Equals(ItemsChoiceType2.rotate)) { /* * <rotate sid="rotateZ">0 0 1 0</rotate> * <rotate sid="rotateY">0 1 0 45</rotate> * <rotate sid="rotateX">1 0 0 0</rotate> */ var rotate = item as rotate; TransformationType rotType = GetRotationType(rotate); Vector3 rot = Vector3.Zero; switch (rotType) { case TransformationType.RotationX: rot = new Vector3((float)(rotate.Values[3] * Helper.Deg2Rad), 0.0f, 0.0f); break; case TransformationType.RotationY: rot = new Vector3(0.0f, (float)(rotate.Values[3] * Helper.Deg2Rad), 0.0f); break; case TransformationType.RotationZ: rot = new Vector3(0.0f, 0.0f, (float)(rotate.Values[3] * Helper.Deg2Rad)); break; } transforms.Add(new Tuple<Vector3, TransformationType>(rot, rotType)); } else if (nodeNODE.ItemsElementName[i].Equals(ItemsChoiceType2.scale)) { var scale = item as TargetableFloat3; Vector3 tmp = new Vector3((float)scale.Values[0], (float)scale.Values[1], (float)scale.Values[2]); transforms.Add(new Tuple<Vector3, TransformationType>(tmp, TransformationType.ScaleXYZ)); } } } if (!matrixBacked) { // If matrix not used, multiply each of the transformations in the reverse of the order they appear. // IMPORTANT NOTE: The order must be Scale, Rotation, Translation (appear in file TRzRyRxS) List<Tuple<Vector3, TransformationType>> scale = transforms.Where(tran => tran.Item2.Equals(TransformationType.ScaleXYZ)).ToList(); List<Tuple<Vector3, TransformationType>> rotate = transforms.Where(tran => tran.Item2.Equals(TransformationType.RotationX) || tran.Item2.Equals(TransformationType.RotationY) || tran.Item2.Equals(TransformationType.RotationZ)).ToList(); List<Tuple<Vector3, TransformationType>> translate = transforms.Where(tran => tran.Item2.Equals(TransformationType.TranslationXYZ)).ToList(); if (scale.Count <= 1 && rotate.Count <= 3 && translate.Count <= 1) { // Making an assumption that the order is SRT if less than 5 tranformations, if it's greater than // 5 or there are 5 but not in the order in above condition, use matrix decomposition method. nodeScale = (scale.Count == 1) ? scale[0].Item1 : nodeScale; foreach (Tuple<Vector3, TransformationType> rot in rotate) { if (rot.Item2 == TransformationType.RotationX) { nodeRotation.X = rot.Item1.X; } if (rot.Item2 == TransformationType.RotationY) { nodeRotation.Y = rot.Item1.Y; } if (rot.Item2 == TransformationType.RotationZ) { nodeRotation.Z = rot.Item1.Z; } } nodeTranslation = (translate.Count == 1) ? translate[0].Item1 : nodeTranslation; } else { // If not we need to multiply the matrices and then decompose the final matrix Matrix4 result = Matrix4.Identity; for (int i = transforms.Count - 1; i >= 0; i--) { Tuple<Vector3, TransformationType> current = transforms.ElementAt(i); Vector3 vec = current.Item1; switch (current.Item2) { case TransformationType.ScaleXYZ: Matrix4 mscale = Matrix4.CreateScale(vec); Matrix4.Mult(ref result, ref mscale, out result); break; case TransformationType.RotationX: Matrix4 mxrot = Matrix4.CreateRotationX(vec.X); Matrix4.Mult(ref result, ref mxrot, out result); break; case TransformationType.RotationY: Matrix4 myrot = Matrix4.CreateRotationY(vec.Y); Matrix4.Mult(ref result, ref myrot, out result); break; case TransformationType.RotationZ: Matrix4 mzrot = Matrix4.CreateRotationZ(vec.Z); Matrix4.Mult(ref result, ref mzrot, out result); break; case TransformationType.TranslationXYZ: Matrix4 mtrans = Matrix4.CreateTranslation(vec); Matrix4.Mult(ref result, ref mtrans, out result); break; } } Helper.DecomposeSRTMatrix1(result, out nodeScale, out nodeRotation, out nodeTranslation); } } }
private static bool IsRootNodeOfChild(node parent, node child) { if (parent.node1 == null || parent.node1.Length == 0) return false; else { foreach (node n in parent.node1) { if (child.id.Equals(n.id)) return true; else if (IsRootNodeOfChild(child, n)) return true; } } return false; }
private void ReadNode(node joint, node parent, bool inSkeleton) { string id = (joint.id != null ? joint.id : (joint.name != null ? joint.name : m_Model.m_BoneTree.Count.ToString())); Vector3 nodeScale = Vector3.One; Vector3 nodeRotation = Vector3.Zero; Vector3 nodeTranslation = Vector3.Zero; ReadNodeTransformations(joint, ref nodeScale, ref nodeRotation, ref nodeTranslation); if (joint.instance_geometry != null && joint.instance_geometry.Length > 0) { // Making an assumption that <instance_geometry> will never appear within a skeleton, not sure if it can? ModelBase.BoneDef rootBone = new ModelBase.BoneDef(id); rootBone.SetScale(nodeScale); rootBone.SetRotation(nodeRotation); rootBone.SetTranslation(nodeTranslation); m_Model.m_BoneTree.AddRootBone(rootBone); m_Model.m_BoneTransformsMap.Add(id, m_Model.m_BoneTree.GetBoneIndex(id)); foreach (instance_geometry instanceGeometry in joint.instance_geometry) { string geometryID = instanceGeometry.url.Replace("#", ""); Dictionary<string, string> bindMaterials = new Dictionary<string, string>(); if (instanceGeometry.bind_material != null) { foreach (instance_material instanceMaterial in instanceGeometry.bind_material.technique_common) { bindMaterials.Add(instanceMaterial.symbol, instanceMaterial.target.Replace("#", "")); } } ModelBase.GeometryDef geometry = ReadGeometry(geometryID, id, bindMaterials); rootBone.m_Geometries.Add(geometryID, geometry); } } else if (joint.instance_controller != null && joint.instance_controller.Length > 0) { // Making an assumption that <instance_controller> will never appear within a skeleton, not sure if it can? instance_controller instanceController = joint.instance_controller[0]; string controllerID = instanceController.url.Replace("#", ""); if (instanceController.skeleton != null && instanceController.skeleton.Length > 0) { /*string skeletonRoot = null; foreach (string skel in instanceController.skeleton) { string skeleton = skel.Replace("#", ""); if (skeletonRoot == null) skeletonRoot = skeleton; if (m_Model.m_BoneTree.GetBoneByID(skeleton) != null) continue; ReadSkeleton(skeletonRoot); } // WRONG */ string skeletonRoot = instanceController.skeleton[0].Replace("#", ""); ReadSkeleton(skeletonRoot); controller cntl = this.library_controllers.controller.Where(cntl0 => cntl0.id.Equals(controllerID)).ElementAt(0); if (cntl.Item as skin != null) { // Currently there is only support for skin controllers. Where a skin uses as its source another // controller eg. a morph, we'll just recursively go through until we find a skin with a geometry // as the source and return the geometry's ID. // I've seen a skin use a skin as a source where the first skin gave joint indices of -1 from 3DS Max and // OpenCOLLAD, in cases like this, we do as above and just take the geometry ID and attach the skin being // read to that. string skinSourceID = null; var queue = new Queue<controller>(); queue.Enqueue(cntl); while (queue.Count > 0) { controller cont = queue.Dequeue(); string srcID = (cont.Item as skin).source1.Replace("#", ""); if (this.library_geometries != null && this.library_geometries.geometry.Where(geom0 => geom0.id.Equals(srcID)).Count() < 1) { IEnumerable<controller> res = this.library_controllers.controller.Where(cont0 => cont0.id.Equals(srcID)); if (res.Count() > 0) { queue.Enqueue(res.ElementAt(0)); } } else { skinSourceID = srcID; } } m_Model.m_BoneTransformsMap.Clear(); int[] vertexBoneIDs = ReadSkinController(controllerID, skeletonRoot, skinSourceID); Dictionary<string, string> bindMaterials = new Dictionary<string, string>(); if (instanceController.bind_material != null) { foreach (instance_material instanceMaterial in instanceController.bind_material.technique_common) { bindMaterials.Add(instanceMaterial.symbol, instanceMaterial.target.Replace("#", "")); } } ModelBase.GeometryDef geomDef = ReadGeometry(skinSourceID, skeletonRoot, bindMaterials, vertexBoneIDs); m_Model.m_BoneTree.GetBoneByID(skeletonRoot).m_Geometries.Add(skinSourceID, geomDef); } } } else if (inSkeleton) { ModelBase.BoneDef boneDef = new ModelBase.BoneDef(joint.id); if (joint == parent) { m_Model.m_BoneTree.AddRootBone(boneDef); } else { ModelBase.BoneDef parentBone = m_Model.m_BoneTree.GetBoneByID(parent.id); parentBone.AddChild(boneDef); } boneDef.SetScale(nodeScale); boneDef.SetRotation(nodeRotation); boneDef.SetTranslation(nodeTranslation); if (joint.node1 == null || joint.node1.Length == 0) return; foreach (node child in joint.node1) { if (child.type.Equals(NodeType.NODE)) { Console.WriteLine("Warning: node: " + joint.id + " has a child of type \"NODE\" within a skeleton, failure likely"); } ReadNode(child, joint, true); } } }
protected node AddToCollada(List<material> materials, List<effect> effects, List<geometry> geometries, List<string> visitedAttaches, bool hasTextures) { BasicAttach attach = Attach as BasicAttach; if (attach == null || visitedAttaches.Contains(attach.Name)) goto skipAttach; visitedAttaches.Add(attach.Name); int m = 0; foreach (NJS_MATERIAL item in attach.Material) { materials.Add(new material { id = "material_" + attach.Name + "_" + m, name = "material_" + attach.Name + "_" + m, instance_effect = new instance_effect { url = "#" + "material_" + attach.Name + "_" + m + "_eff" } }); if (hasTextures & item.UseTexture) { effects.Add(new effect { id = "material_" + attach.Name + "_" + m + "_eff", name = "material_" + attach.Name + "_" + m + "_eff", Items = new effectFx_profile_abstractProfile_COMMON[] { new effectFx_profile_abstractProfile_COMMON { Items = new object[] { new common_newparam_type { sid = "material_" + attach.Name + "_" + m + "_eff_surface", /*Item = new Collada141.fx_sampler2D_common() { instance_image = new Collada141.instance_image() { url = "#image_" + (item.TextureID + 1).ToString(System.Globalization.NumberFormatInfo.InvariantInfo) } }, ItemElementName = Collada141.ItemChoiceType.sampler2D*/ Item = new fx_surface_common { type = fx_surface_type_enum.Item2D, init_from = new fx_surface_init_from_common[] { new fx_surface_init_from_common { Value = "image_" + (item.TextureID + 1).ToString(NumberFormatInfo.InvariantInfo) } } }, ItemElementName = ItemChoiceType.surface } }, technique = new effectFx_profile_abstractProfile_COMMONTechnique { sid = "standard", Item = new effectFx_profile_abstractProfile_COMMONTechniquePhong { ambient = new common_color_or_texture_type { Item = new common_color_or_texture_typeTexture { texture = "material_" + attach.Name + "_" + m + "_eff_surface", texcoord = "CHANNEL0" } }, diffuse = new common_color_or_texture_type { Item = new common_color_or_texture_typeColor { Values = new double[] { item.DiffuseColor.R / 255d, item.DiffuseColor.G / 255d, item.DiffuseColor.B / 255d, item.UseAlpha ? item.DiffuseColor.A / 255d : 1 } } } } } } } }); } else { effects.Add(new effect { id = "material_" + attach.Name + "_" + m + "_eff", name = "material_" + attach.Name + "_" + m + "_eff", Items = new effectFx_profile_abstractProfile_COMMON[] { new effectFx_profile_abstractProfile_COMMON { technique = new effectFx_profile_abstractProfile_COMMONTechnique { sid = "standard", Item = new effectFx_profile_abstractProfile_COMMONTechniquePhong { diffuse = new common_color_or_texture_type { Item = new common_color_or_texture_typeColor { Values = new double[] { item.DiffuseColor.R / 255d, item.DiffuseColor.G / 255d, item.DiffuseColor.B / 255d, item.UseAlpha ? item.DiffuseColor.A / 255d : 1 } } } } } } } }); } m++; } List<double> verts = new List<double>(); foreach (Vertex item in attach.Vertex) { verts.Add(item.X); verts.Add(item.Y); verts.Add(item.Z); } source pos = new source { id = attach.Name + "_position", Item = new float_array { id = attach.Name + "_position_array", count = (ulong)verts.Count, Values = verts.ToArray() }, technique_common = new sourceTechnique_common { accessor = new accessor { source = "#" + attach.Name + "_position_array", count = (ulong)(verts.Count / 3), stride = 3, param = new param[] { new param { name = "X", type = "float" }, new param { name = "Y", type = "float" }, new param { name = "Z", type = "float" } } } } }; verts = new List<double>(); foreach (Vertex item in attach.Normal) { verts.Add(item.X); verts.Add(item.Y); verts.Add(item.Z); } source nor = new source { id = attach.Name + "_normal", Item = new float_array { id = attach.Name + "_normal_array", count = (ulong)verts.Count, Values = verts.ToArray() }, technique_common = new sourceTechnique_common { accessor = new accessor { source = "#" + attach.Name + "_normal_array", count = (ulong)(verts.Count / 3), stride = 3, param = new param[] { new param { name = "X", type = "float" }, new param { name = "Y", type = "float" }, new param { name = "Z", type = "float" } } } } }; List<source> srcs = new List<source> { pos, nor }; foreach (NJS_MESHSET mitem in attach.Mesh) { if (mitem.UV != null) { verts = new List<double>(); foreach (UV item in mitem.UV) { verts.Add(item.U); verts.Add(-item.V); } srcs.Add(new source { id = mitem.UVName, Item = new float_array { id = mitem.UVName + "_array", count = (ulong)verts.Count, Values = verts.ToArray() }, technique_common = new sourceTechnique_common { accessor = new accessor { source = "#" + mitem.UVName + "_array", count = (ulong)(verts.Count / 2), stride = 2, param = new param[] { new param { name = "S", type = "float" }, new param { name = "T", type = "float" } } } } }); } } List<triangles> tris = new List<triangles>(); foreach (NJS_MESHSET mesh in attach.Mesh) { bool hasVColor = mesh.VColor != null; bool hasUV = mesh.UV != null; uint currentstriptotal = 0; foreach (Poly poly in mesh.Poly) { List<uint> inds = new List<uint>(); switch (mesh.PolyType) { case Basic_PolyType.Triangles: for (uint i = 0; i < 3; i++) { inds.Add(poly.Indexes[i]); if (hasUV) inds.Add(currentstriptotal + i); } currentstriptotal += 3; break; case Basic_PolyType.Quads: for (uint i = 0; i < 3; i++) { inds.Add(poly.Indexes[i]); if (hasUV) inds.Add(currentstriptotal + i); } for (uint i = 1; i < 4; i++) { inds.Add(poly.Indexes[i]); if (hasUV) inds.Add(currentstriptotal + i); } currentstriptotal += 4; break; case Basic_PolyType.NPoly: case Basic_PolyType.Strips: bool flip = !((Strip)poly).Reversed; for (int k = 0; k < poly.Indexes.Length - 2; k++) { flip = !flip; if (!flip) { for (uint i = 0; i < 3; i++) { inds.Add(poly.Indexes[k + i]); if (hasUV) inds.Add(currentstriptotal + i); } } else { inds.Add(poly.Indexes[k + 1]); if (hasUV) inds.Add(currentstriptotal + 1); inds.Add(poly.Indexes[k]); if (hasUV) inds.Add(currentstriptotal); inds.Add(poly.Indexes[k + 2]); if (hasUV) inds.Add(currentstriptotal + 2); } currentstriptotal += 1; } currentstriptotal += 2; break; } string[] indstr = new string[inds.Count]; for (int i = 0; i < inds.Count; i++) indstr[i] = inds[i].ToString(NumberFormatInfo.InvariantInfo); List<InputLocalOffset> inp = new List<InputLocalOffset> { new InputLocalOffset { semantic = "VERTEX", offset = 0, source = "#" + attach.Name + "_vertices" } }; if (hasUV) { inp.Add(new InputLocalOffset { semantic = "TEXCOORD", offset = 1, source = "#" + mesh.UVName, setSpecified = true }); } tris.Add(new triangles { material = "material_" + attach.Name + "_" + mesh.MaterialID, count = (ulong)(inds.Count / (hasUV ? 6 : 3)), input = inp.ToArray(), p = string.Join(" ", indstr) }); } } geometries.Add(new geometry { id = attach.Name, name = attach.Name, Item = new mesh { source = srcs.ToArray(), vertices = new vertices { id = attach.Name + "_vertices", input = new InputLocal[] { new InputLocal { semantic = "POSITION", source = "#" + attach.Name + "_position" }, new InputLocal { semantic = "NORMAL", source = "#" + attach.Name + "_normal" } } }, Items = tris.ToArray() } }); skipAttach: node node = new node { id = Name, name = Name, Items = new object[] { new TargetableFloat3 { sid = "translate", Values = new double[] { Position.X, Position.Y, Position.Z } }, new rotate { sid = "rotateZ", Values = new double[] { 0, 0, 1, Rotation.ZDeg } }, new rotate { sid = "rotateX", Values = new double[] { 1, 0, 0, Rotation.XDeg } }, new rotate { sid = "rotateY", Values = new double[] { 0, 1, 0, Rotation.YDeg } }, new TargetableFloat3 { sid = "scale", Values = new double[] { Scale.X, Scale.Y, Scale.Z } } }, ItemsElementName = new ItemsChoiceType2[] { ItemsChoiceType2.translate, ItemsChoiceType2.rotate, ItemsChoiceType2.rotate, ItemsChoiceType2.rotate, ItemsChoiceType2.scale } }; if (attach != null) { List<instance_material> mats = new List<instance_material>(); foreach (NJS_MESHSET item in attach.Mesh) { mats.Add(new instance_material { symbol = "material_" + attach.Name + "_" + item.MaterialID, target = "#" + "material_" + attach.Name + "_" + item.MaterialID }); } node.instance_geometry = new instance_geometry[] { new instance_geometry { url = "#" + attach.Name, bind_material = new bind_material { technique_common = mats.ToArray() } } }; } List<node> childnodes = new List<node>(); foreach (NJS_OBJECT item in Children) childnodes.Add(item.AddToCollada(materials, effects, geometries, visitedAttaches, hasTextures)); node.node1 = childnodes.ToArray(); return node; }
public static TransformMatrix TransformFromNode(node node) { var transform = new TransformMatrix { matrix = Matrix4.Identity, transform = new Transform(), TransformSID = null }; if (node.ItemsElementName != null) { for (int i = 0; i < node.ItemsElementName.Length; i++) { var name = node.ItemsElementName[i]; var item = node.Items[i]; switch (name) { case ItemsChoiceType2.translate: { var translation = item as TargetableFloat3; ApplyTranslation(transform, translation); break; } case ItemsChoiceType2.rotate: { var rotation = item as rotate; ApplyRotation(transform, rotation); break; } case ItemsChoiceType2.scale: { var scale = item as TargetableFloat3; ApplyScale(transform, scale); break; } case ItemsChoiceType2.matrix: { var mat = item as matrix; transform.TransformSID = mat.sid; ApplyMatrixTransform(transform, mat); break; } } } } return transform; }
static ColladaObject ProcessNode(CL.UpAxisType up, CL.library_geometries geom, CL.node n) { var obj = new ColladaObject(); obj.Name = n.name; obj.ID = n.id; if (n.instance_geometry != null && n.instance_geometry.Length > 0) { //Geometry object if (n.instance_geometry.Length != 1) { throw new Exception("How to handle multiple geometries/node?"); } var uri = CheckURI(n.instance_geometry[0].url); var g = geom.geometry.Where((x) => x.id == uri).First(); if (g.Item is CL.mesh) { obj.Geometry = GetGeometry(up, g); } else if (g.Item is CL.spline) { obj.Spline = GetSpline(up, g); } } if (n.Items.OfType <CL.matrix>().Any()) { var tr = n.Items.OfType <CL.matrix>().First(); obj.Transform = GetMatrix(tr.Text); } else { //TODO: Non-matrix transforms } if (n.node1 != null && n.node1.Length > 0) { foreach (var node in n.node1) { obj.Children.Add(ProcessNode(up, geom, node)); } } return(obj); }