public aiNode FindNode(string name) { IntPtr cPtr = AssimpPINVOKE.aiNode_FindNode__SWIG_1(swigCPtr, name); aiNode ret = (cPtr == IntPtr.Zero) ? null : new aiNode(cPtr, false); return(ret); }
//------------------------------------------------------------------------------- // Calculate the boundaries of a given node and all of its children // The boundaries are in Worldspace (AABB) // piNode Input node // min/max Receives the min/max boundaries // piMatrix Transformation matrix of the graph at this position //------------------------------------------------------------------------------- private void CalculateBounds(aiNode piNode, ref Vector3 min, ref Vector3 max, Matrix piMatrix) { Debug.Assert(null != piNode); var mTemp = piNode.mTransformation.ToMatrix(); var aiMe = mTemp * piMatrix; var meshes = piNode.mMeshes; var numMeshes = meshes.Count; for (int i = 0; i < numMeshes; ++i) { var mesh = meshes[i]; var meshMin = Vector3.TransformCoordinate(meshBoundsMin[mesh], aiMe); var meshMax = Vector3.TransformCoordinate(meshBoundsMax[mesh], aiMe); min.X = Math.Min(min.X, meshMin.X); min.Y = Math.Min(min.Y, meshMin.Y); min.Z = Math.Min(min.Z, meshMin.Z); max.X = Math.Max(max.X, meshMax.X); max.Y = Math.Max(max.Y, meshMax.Y); max.Z = Math.Max(max.Z, meshMax.Z); } var children = piNode.mChildren; var numChildren = children.Count; for (int i = 0; i < numChildren; ++i) { CalculateBounds(children[i], ref min, ref max, aiMe); } }
private BoneContent createSkel(aiNode root) { BoneContent BoneContent = null; if (ainodetocontent.ContainsKey(root.mName.Data)) { aiBone b = bones.Find((a) => a.mName.Data == root.mName.Data); if (b != null) { BoneContent = new BoneContent(); BoneContent.Name = b.mName.Data; BoneContent.Transform = tomatrix(b.mOffsetMatrix); foreach (var item in root.mChildren) { BoneContent bon = createSkel(item); if (bon != null) { BoneContent.Children.Add(bon); } } return(BoneContent); } } return(null); }
public aiNode FindNode(aiString name) { IntPtr cPtr = AssimpPINVOKE.aiNode_FindNode__SWIG_0(swigCPtr, aiString.getCPtr(name)); aiNode ret = (cPtr == IntPtr.Zero) ? null : new aiNode(cPtr, false); if (AssimpPINVOKE.SWIGPendingException.Pending) { throw AssimpPINVOKE.SWIGPendingException.Retrieve(); } return(ret); }
private static uint CountNodes(aiNode node) { uint result = 1; using (aiNodeArray children = node.Children) { uint children_size = children.Size(); for (uint i = 0; i < children_size; i++) { using (aiNode child = children.Get(i)) { result += CountNodes(child); } } } return(result); }
private NodeContent extractNo(aiNode node) { NodeContent nodeContent = new NodeContent(); nodeContent.Name = node.mName.Data; nodeContent.Transform = tomatrix(node.mTransformation); ainodetocontent.Add(node.mName.Data, nodeContent); wbone.Clear(); for (int i = 0; i < node.mNumMeshes; i++) { for (int j = 0; j < scene.mMeshes[(int)node.mMeshes[i]].mNumBones; j++) { aiBone b = scene.mMeshes[(int)node.mMeshes[i]].mBones[j]; for (int w = 0; w < b.mNumWeights; w++) { aiVertexWeight vw = b.GetmWeights()[w]; if (!wbone.ContainsKey((int)vw.mVertexId)) { wbone[(int)vw.mVertexId] = new List <KeyValuePair <string, float> >(); } wbone[(int)vw.mVertexId].Add(new KeyValuePair <string, float>(b.mName.Data, vw.mWeight)); } bones.Add(b); } log("model " + node.mMeshes[i].ToString()); MeshContent MeshContent = ExtractMesh(scene.mMeshes[(int)node.mMeshes[i]]); MeshHelper.SwapWindingOrder(MeshContent); MeshHelper.OptimizeForCache(MeshContent); nodeContent.Children.Add(MeshContent); } foreach (var item in node.mChildren) { nodeContent.Children.Add(extractNo(item)); } return(nodeContent); }
private void RenderNode(aiNode node, Matrix parentMatrix) { var nodeMatrix = node.mTransformation.ToMatrix() * parentMatrix; var children = node.mChildren; var numChildren = node.mNumChildren; for (int i = 0; i < numChildren; ++i) { var child = children[i]; RenderNode(child, nodeMatrix); } device.Transform.World = nodeMatrix; var meshes = node.mMeshes; var numMeshes = meshes.Count; for (int i = 0; i < numMeshes; ++i) { var meshId = (int)meshes[i]; var mesh = scene.mMeshes[meshId]; var materialId = (int)mesh.mMaterialIndex; var dxMaterial = materialCache[materialId]; device.Material = dxMaterial.Material3D; Texture dxTexture = null; if (!string.IsNullOrEmpty(dxMaterial.TextureFilename)) { textureCache.TryGetValue(dxMaterial.TextureFilename, out dxTexture); } device.SetTexture(0, dxTexture); var dxMesh = meshCache[meshId]; RenderMesh(dxMesh); } }
internal static HandleRef getCPtr(aiNode obj) { return((obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr); }
public IEnumerator ToAssimp(Module.Export.Assimp.Context context, string filename, aiPostProcessSteps steps, Module.ExporterSuccessCallback return_callback, Module.ProgressCallback progress_callback) { bool success = false; string extension = System.IO.Path.GetExtension(filename).Remove(0, 1).ToLower(); uint export_format_count = context.exporter.GetExportFormatCount(); bool found_exporter = false; for (uint i = 0; i < export_format_count; i++) { using (aiExportFormatDesc desc = context.exporter.GetExportFormatDescription(i)) { if (extension == desc.fileExtension.ToLower()) { using (aiScene scene = new aiScene()) { InitProgress(context, progress_callback, this); context.scene = scene; // Export nodes IResult nodes_result = context.threads.AddTask(() => { using (aiNode root = root_node.ToAssimp(context, this, null)) { scene.mRootNode = root.Unmanaged(); } }); // Export materials. context.threads.AddTask(() => Material.ToAssimp(context, this)); // We must wait for all the nodes to be processed before exporting meshes because indexes are computed during parsing. while (!nodes_result.Done) { context.progress.Display(); yield return(null); } // Export meshes context.threads.AddTask(() => Mesh.ToAssimp(context, this)); // Wait for all tasks to be completed IEnumerator it = context.threads.WaitForTasksCompletion(); while (it.MoveNext()) { context.progress.Display(); yield return(it.Current); } // Do the final export using Assimp now that we created the complete structure in the C++ DLL. Result <aiReturn> status = context.threads.AddTask(() => context.exporter.Export(scene, desc.id, filename, steps)); // Wait for export to complete while (!status.Done) { context.progress.Display(); yield return(null); } if (progress_callback != null) { progress_callback(1f); } context.Clean(); // Check export status if (status.Success && status.Value == aiReturn.aiReturn_SUCCESS) { success = true; } else { Debug.LogErrorFormat("Failed to export to: {0}. \nThe exporter reported the following error: {1}", filename, context.exporter.GetErrorString()); } } found_exporter = true; break; } } } if (!found_exporter) { Debug.LogErrorFormat("No exporter for format '{0}' was found in Assimp.", extension); } if (return_callback != null) { return_callback(success); } }
public aiNode ToAssimp(Module.Export.Assimp.Context context, Scene scene, aiNode parent) { uint index = 0; aiNode node_object = new aiNode(name); // Set parent node_object.mParent = parent; // Set transform using (aiVector3D assimp_scale = Assimp.Convert.UnityToAssimp.Vector3(scale)) { using (aiQuaternion assimp_rotation = Assimp.Convert.UnityToAssimp.Quaternion(rotation)) { using (aiVector3D assimp_position = Assimp.Convert.UnityToAssimp.Vector3(position)) { using (aiMatrix4x4 matrix = new aiMatrix4x4(assimp_scale, assimp_rotation, assimp_position)) { node_object.mTransformation = matrix.Unmanaged(); } } } } // Parse the children nodes if (children != null && children.Length > 0) { using (aiNodeArray assimp_children = node_object.Children) { assimp_children.Reserve((uint)children.Length, true); index = 0; foreach (Node child in children) { using (aiNode assimp_child = child.ToAssimp(context, scene, node_object)) { if (assimp_child != null) { assimp_children.Set(index++, assimp_child.Unmanaged()); } } } } } // Parse the mesh objects if (meshes != null && meshes.Length > 0) { using (aiUIntArray assimp_meshes = node_object.Meshes) { assimp_meshes.Reserve((uint)meshes.Length, true); index = 0; foreach (GraphicMesh graphic_mesh in meshes) { Mesh mesh = scene.meshes[graphic_mesh.meshIndex]; int nb_materials = (graphic_mesh.materialsIndexes != null ? graphic_mesh.materialsIndexes.Length : 0); // Handle unity submeshes by creating new meshes for each submesh for (int i = 0; i < mesh.SubMeshesCount; i++) { // Assimp meshes can only have one material. Therefore, mutliple instances of one mesh // using different materials must be detected and replaced by different output meshes. uint assimp_mesh_index; int mat_index = (i < nb_materials ? graphic_mesh.materialsIndexes[i] : 0 /*Assimp default*/); Module.Export.Assimp.Mesh key = new Module.Export.Assimp.Mesh(graphic_mesh.meshIndex, i, mat_index); if (!context.meshes.TryGetValue(key, out assimp_mesh_index)) { assimp_mesh_index = (uint)context.meshes.Count; context.meshes.Add(key, assimp_mesh_index); } assimp_meshes.Set(index++, assimp_mesh_index); } } } } // Parse the node metadata if (components != null) { foreach (UnityComponent component in components) { aiMetadata assimp_meta = component.ToAssimpMetadata(); if (assimp_meta != null) { node_object.mMetaData = assimp_meta.Unmanaged(); break; } } } context.progress.Update(ASSIMP_PROGRESS_FACTOR); return(node_object); }
public static Node FromAssimp(Module.Import.Assimp.Context context, aiScene scene, aiNode assimp_node) { // Create new node object Node node = new Node(); // Get node ID node.id = context.id++; // Get node name node.name = Assimp.Convert.Name(assimp_node.mName, "node"); // Get node metadata using (aiMetadata meta = assimp_node.mMetaData) { UnityComponent metadata = UnityComponent.FromAssimpMetadata(meta); if (metadata != null) { node.components = new UnityComponent[] { metadata }; } } // Parse children recursively using (aiNodeArray children = assimp_node.Children) { uint children_size = children.Size(); if (children_size > 0) { node.children = new Node[children_size]; for (uint i = 0; i < children_size; i++) { aiNode child = children.Get(i); // ParseNode must dispose of the given node afterward // We must use a proxy method for saving the result into the array because the index i is captured by the lambda otherwise and it's value is indefinite across multiple threads. context.threads.ExecAndSaveToArray(node.children, (int)i, () => FromAssimp(context, scene, child)); } } } // Parse meshes associated to this node using (aiUIntArray meshes = assimp_node.Meshes) { uint meshes_size = meshes.Size(); if (meshes_size > 0) { int global_meshes_size = (int)scene.Meshes.Size(); node.meshes = new GraphicMesh[meshes_size]; for (uint j = 0; j < meshes_size; j++) { node.meshes[j] = new GraphicMesh(); if (j < global_meshes_size) { uint mesh_index = meshes.Get(j); node.meshes[j].meshIndex = (int)mesh_index; } } } } // Get the transform of this node using (aiVector3D position = new aiVector3D()) { using (aiVector3D scaling = new aiVector3D()) { using (aiQuaternion rotation = new aiQuaternion()) { assimp_node.mTransformation.Decompose(scaling, rotation, position); node.position = Assimp.Convert.AssimpToUnity.Vector3(position); node.rotation = Assimp.Convert.AssimpToUnity.Quaternion(rotation); node.scale = Assimp.Convert.AssimpToUnity.Vector3(scaling); } } } // We must dispose of the given parameter to avoid memory leaks assimp_node.Dispose(); context.progress.Update(ASSIMP_PROGRESS_FACTOR); return(node); }
internal static HandleRef getCPtr(aiNode obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; }
/// <summary> /// The importer's entry point. /// Called by the framework when importing a game asset. /// </summary> /// <param name="filename">Name of a game asset file.</param> /// <param name="context"> /// Contains information for importing a game asset, such as a logger interface. /// </param> /// <returns>Resulting game asset.</returns> public override NodeContent Import(string filename, ContentImporterContext context) { // Uncomment the following line to debug: //System.Diagnostics.Debugger.Launch(); importerContext = context; // Reset all importer state // See field declarations for more information rootNode = new NodeContent(); meshBuilder = null; this.filename = filename; // Model identity is tied to the file it is loaded from rootNode.Identity = new ContentIdentity(filename); var flags = (ppsteps | aiPostProcessSteps.aiProcess_GenSmoothNormals | // generate smooth normal vectors if not existing aiPostProcessSteps.aiProcess_SplitLargeMeshes | // split large, unrenderable meshes into submeshes aiPostProcessSteps.aiProcess_Triangulate | // triangulate polygons with more than 3 edges aiPostProcessSteps.aiProcess_ConvertToLeftHanded | // convert everything to D3D left handed space aiPostProcessSteps.aiProcess_SortByPType | // make 'clean' meshes which consist of a single typ of primitives aiPostProcessSteps.aiProcess_FixInfacingNormals | aiPostProcessSteps.aiProcess_FlipWindingOrder | (aiPostProcessSteps)0); Importer importer = new Importer(); scene = importer.ReadFile(filename, flags); if (scene != null) { directory = Path.GetDirectoryName(filename); } else { throw new InvalidContentException("Failed to open file: " + filename + ". Either Assimp screwed up or the path is not valid."); } ///animacoes Dictionary <String, AnimationContent> AnimNameToAcontent = new Dictionary <string, AnimationContent>(); for (int i = 0; i < scene.mNumAnimations; i++) { AnimationContent AnimationContent = new AnimationContent(); AnimationContent.Duration = TimeSpan.FromMilliseconds(scene.mAnimations[i].mDuration); if (String.IsNullOrEmpty(scene.mAnimations[i].mName.Data)) { scene.mAnimations[i].mName.Data = "EMPTY"; } AnimationContent.Name = scene.mAnimations[i].mName.Data; AnimNameToAcontent.Add(scene.mAnimations[i].mName.Data, AnimationContent); for (int j = 0; j < scene.mAnimations[i].mNumChannels; j++) { AnimationChannel AnimationChannel; String boneName = scene.mAnimations[i].mChannels[j].mNodeName.Data; if (AnimationContent.Channels.ContainsKey(boneName)) { AnimationChannel = AnimationContent.Channels[boneName]; } else { AnimationChannel = new AnimationChannel(); AnimationContent.Channels.Add(boneName, AnimationChannel); } Dictionary <double, Vector3> position = new Dictionary <double, Vector3>(); Dictionary <double, Vector3> scales = new Dictionary <double, Vector3>(); Dictionary <double, Quaternion> rots = new Dictionary <double, Quaternion>(); SortedSet <double> set = new SortedSet <double>(); for (int w = 0; w < scene.mAnimations[i].mChannels[j].mNumPositionKeys; w++) { position.Add(scene.mAnimations[i].mChannels[j].mPositionKeys[w].mTime, new Vector3(scene.mAnimations[i].mChannels[j].mPositionKeys[w].mValue.x, scene.mAnimations[i].mChannels[j].mPositionKeys[w].mValue.y, scene.mAnimations[i].mChannels[j].mPositionKeys[w].mValue.z)); set.Add(scene.mAnimations[i].mChannels[j].mPositionKeys[w].mTime); } for (int w = 0; w < scene.mAnimations[i].mChannels[j].mNumScalingKeys; w++) { scales.Add(scene.mAnimations[i].mChannels[j].mScalingKeys[w].mTime, new Vector3(scene.mAnimations[i].mChannels[j].mScalingKeys[w].mValue.x, scene.mAnimations[i].mChannels[j].mScalingKeys[w].mValue.y, scene.mAnimations[i].mChannels[j].mScalingKeys[w].mValue.z)); set.Add(scene.mAnimations[i].mChannels[j].mScalingKeys[w].mTime); } for (int w = 0; w < scene.mAnimations[i].mChannels[j].mNumRotationKeys; w++) { rots.Add(scene.mAnimations[i].mChannels[j].mRotationKeys[w].mTime, new Quaternion(scene.mAnimations[i].mChannels[j].mRotationKeys[w].mValue.x, scene.mAnimations[i].mChannels[j].mRotationKeys[w].mValue.y, scene.mAnimations[i].mChannels[j].mRotationKeys[w].mValue.z, scene.mAnimations[i].mChannels[j].mRotationKeys[w].mValue.w)); set.Add(scene.mAnimations[i].mChannels[j].mRotationKeys[w].mTime); } foreach (var item in set) { Vector3 pos; Vector3 sca; Quaternion rot; if (position.TryGetValue(item, out pos) == false) { pos = Vector3.Zero; } if (rots.TryGetValue(item, out rot) == false) { rot = Quaternion.Identity; } if (scales.TryGetValue(item, out sca) == false) { sca = Vector3.One; } Matrix world = Matrix.CreateScale(sca) * Matrix.CreateFromQuaternion(rot) * Matrix.CreateTranslation(pos); AnimationChannel.Add(new AnimationKeyframe(TimeSpan.FromMilliseconds(item), world)); } } } rootNode.Children.Add(extractNo(scene.mRootNode)); aiNode boneRoot = null; aiBone broot = null; int distance = int.MaxValue; ///pega o root manow foreach (var item in bones) { aiNode ainode = scene.mRootNode.FindNode(item.mName); aiNode n = ainode; int d = 0; //find the closest to the root =P while (n.mParent != null) { d++; n = n.mParent; } if (d < distance) { broot = item; boneRoot = ainode; distance = d; } } if (broot != null) { BoneContent BoneContent = new BoneContent(); BoneContent.Name = broot.mName.Data; BoneContent.Transform = tomatrix(broot.mOffsetMatrix); rootNode.Children.Add(BoneContent); foreach (var item2 in AnimNameToAcontent) { BoneContent.Animations.Add(item2.Key, item2.Value); } foreach (var item in boneRoot.mChildren) { BoneContent.Children.Add(createSkel(boneRoot)); } ClearTree(rootNode); } return(rootNode); }