private void CanCompute_CornerAngles() => this.FlatSquare.Corners.ForEach( corner => { var angle = MeshGeometry.Angle(corner); Assert.True(Math.Abs(angle - 0.5 * Math.PI) < Settings.Tolerance); });
public override void Finish(bool cancel) { if (!cancel) { //calculate mesh in space position var points = MeshGeometry.GetPointPositions(); if (points.Length != 0) { var position = Vector3.Zero; foreach (var point in points) { position += point; } position /= points.Length; CreatingObject.Transform = new Transform(position, Quaternion.Identity); } //attach points to the mesh in space foreach (var point in MeshGeometry.GetPoints()) { Component_ObjectInSpace_Utility.Attach(CreatingObject, point); } //select meshin space and points var toSelect = new List <Component>(); toSelect.Add(CreatingObject); //toSelect.AddRange( points ); EditorAPI.SelectComponentsInMainObjectsWindow(DocumentWindow, toSelect.ToArray()); //update mesh MeshGeometry?.ShouldRecompileMesh(); } base.Finish(cancel); }
private void CanCompute_EdgeLengths() => this.FlatSquare.Edges.ForEach( edge => { var length = MeshGeometry.Length(edge); Assert.True(Math.Abs(length - 1) < Settings.Tolerance); });
public static Mesh LddRoundEdgeMeshToAssimp(MeshGeometry geometry) { var assimpMesh = new Mesh(Assimp.PrimitiveType.Triangle); int indexCounter = 0; foreach (var tri in geometry.Triangles) { foreach (var idx in tri.Indices) { assimpMesh.Vertices.Add(idx.Vertex.Position.ToAssimp()); assimpMesh.Normals.Add(idx.Vertex.Normal.ToAssimp()); for (int i = 0; i < 6; i++) { var uvCoord = idx.RoundEdgeData.Coords[i]; if (RoundEdgeData.EmptyCoord != uvCoord) { uvCoord.X = Math.Abs(uvCoord.X) - 100f; } //uvCoord /= 10f; assimpMesh.TextureCoordinateChannels[i].Add(new Vector3D(uvCoord.X, uvCoord.Y, 0)); } } assimpMesh.Faces.Add(new Face(new int[] { indexCounter++, indexCounter++, indexCounter++ })); } return(assimpMesh); }
public GeometryModel3D CreateGeometryModel3D() { try { if (!this.CheckAccess()) { var ret = default(GeometryModel3D); this.Dispatcher.Invoke(new Action(delegate { ret = CreateGeometryModel3D(); })); return(ret); } { if (MeshGeometry == null) { return(null); } var meshGeometry3D = MeshGeometry.CreateMeshGeometry3D(); if (meshGeometry3D == null) { return(null); } var ret = new GeometryModel3D(meshGeometry3D, new DiffuseMaterial(new SolidColorBrush(MaterialColor))); ret.BackMaterial = (MaterialColor == BackMaterialColor) ? ret.Material : new DiffuseMaterial(new SolidColorBrush(BackMaterialColor)); return(ret); } } catch (System.Exception) { return(null); } }
private void GenerateMesh(VoxelGrid grid) { this.EnqueueWorkerJob(() => { //Thread.Sleep(750); var voxels = this.grid.Data; var vertices = new List <VertexPositionTextureNormal>(voxels.XLength * voxels.YLength * voxels.ZLength); var indices = new List <ushort>(voxels.XLength * voxels.YLength * voxels.ZLength); MeshGenerator.GenerateGridMesh(voxels, (voxel, side, quad) => { var textureOffset = GetTexCoords(voxel, side); indices.Add((ushort)(vertices.Count + 0)); indices.Add((ushort)(vertices.Count + 1)); indices.Add((ushort)(vertices.Count + 3)); indices.Add((ushort)(vertices.Count + 1)); indices.Add((ushort)(vertices.Count + 2)); indices.Add((ushort)(vertices.Count + 3)); vertices.Add(new VertexPositionTextureNormal(quad.A, (textureOffset + new Vector2(0, 128)) / new Vector2(1024, 2048), quad.Normal)); vertices.Add(new VertexPositionTextureNormal(quad.B, (textureOffset + new Vector2(0, 0)) / new Vector2(1024, 2048), quad.Normal)); vertices.Add(new VertexPositionTextureNormal(quad.C, (textureOffset + new Vector2(128, 0)) / new Vector2(1024, 2048), quad.Normal)); vertices.Add(new VertexPositionTextureNormal(quad.D, (textureOffset + new Vector2(128, 128)) / new Vector2(1024, 2048), quad.Normal)); }); if (_meshGeometry == null) { _meshGeometry = new MeshGeometry(); } _meshGeometry.UpdateMesh(vertices.ToArray(), indices.ToArray()); }); }
/// <summary> /// Computes a geodesic on a mesh given a starting point and an initial direction. /// Returns true if successfull and false if something went wrong. /// </summary> /// <param name="meshPoint">Point.</param> /// <param name="vector">Direction.</param> /// <param name="mesh">Mesh.</param> /// <param name="maxIter">Maximum iterations.</param> /// <param name="geodesic">Geodesic curves.</param> /// <returns>True if successful.</returns> public static bool StartDir( MeshPoint meshPoint, Vector3d vector, Mesh mesh, int maxIter, out List <Point3d> geodesic) { // Get initial face on the mesh var initialFace = mesh.Faces[meshPoint.FaceIndex]; // Start iteration // Create variables for current iteration step var thisFace = initialFace; var thisPoint = new Point3d(); var thisDirection = vector; var iter = 0; var geodPoints = new List <Point3d>(); do { var ray = new Ray(thisPoint, thisDirection); // Find intersection between ray and boundary Intersect3D.RayFacePerimeter(ray, thisFace, out var nextPoint, out var halfEdge); // Intersection method should check for correct direction using sign of dot product // Add point to pointlist geodPoints.Add(nextPoint); // Walk to next face var nextFace = halfEdge.Twin.Face; // Flip vector to next face var perpVector = Vector3d.CrossProduct( thisDirection, MeshGeometry.FaceNormal(thisFace)); var nextVector = Vector3d.CrossProduct( MeshGeometry.FaceNormal(nextFace), perpVector); // Assign iteration variables to current thisPoint = nextPoint; thisFace = nextFace; thisDirection = nextVector; // Increase counter iter++; } while (iter < maxIter); // Assign outputs geodesic = geodPoints; return(true); }
private void CanCompute_VertexNormal() => this.FlatTriangle.Vertices.ForEach( vertex => { var normal = MeshGeometry.VertexNormalAngleWeighted(vertex); Assert.Equal(Vector3d.UnitZ, normal); normal = MeshGeometry.VertexNormalEquallyWeighted(vertex); Assert.Equal(Vector3d.UnitZ, normal); normal = MeshGeometry.VertexNormalAreaWeighted(vertex); Assert.Equal(Vector3d.UnitZ, normal); });
public MeshGeometry ConstructFrom(Mesh mesh, Transform[] bones) { var result = new MeshGeometry(); List <Vector3d> verticesList = GetVerticesList(mesh.vertices); List <Tuple <int, int, int> > trianglesList = MeshDataHelper.GetTrianglesList(mesh.triangles); Dictionary <string, Dictionary <int, float> > bonesWeights = GetBonesWeights(mesh.boneWeights, bones); result.vertices = verticesList; result.triangles = trianglesList; result.bonesWeights = bonesWeights; result.normals = MeshDataHelper.GetNormals(mesh.normals); result.uvMaps = MeshDataHelper.GetUvMaps(mesh); return(result); }
public void Reset() { _currentMeshGeometry = null; _currentClump = null; _currentPrototype = null; _currentPrelight = default(Color); _currentTransform = new Matrix4(); _currentMaterial = new Material(); _clumpStack.Clear(); _materialStack.Clear(); _transformStack.Clear(); _model = new Model(); }
private static Node CreateMeshNode(Scene scene, MeshGeometry geometry, string name, int materialIndex, MeshExportOptions exportOptions) { var meshNode = new Node() { Name = name }; var aMesh = exportOptions.IncludeRoundEdgeData ? LddRoundEdgeMeshToAssimp(geometry) : LddMeshToAssimp(geometry); aMesh.MaterialIndex = materialIndex; meshNode.MeshIndices.Add(scene.MeshCount); scene.Meshes.Add(aMesh); return(meshNode); }
// public CreationModePolyhedron(DocumentWindowWithViewport documentWindow, Component creatingObject) : base(documentWindow, creatingObject) { var position = CreatingObject.TransformV.Position; if (CalculatePointPosition(documentWindow.Viewport, out var position2, out _)) { position = position2; } var point = MeshGeometry.CreateComponent <Component_MeshGeometry_PolygonBasedPolyhedron_Point>(enabled: false); point.Name = MeshGeometry.Components.GetUniqueName("Point", false, 1); point.Transform = new Transform(position, Quaternion.Identity); point.Enabled = true; }
private static void SetShaderData(MESH_FILE file, MESH_DATA data, MeshGeometry mesh) { for (int i = 0; i < data.Indices.Length; i++) { var index = data.Indices[i]; if (index.AverageNormalIndex >= 0 && index.AverageNormalIndex < file.AverageNormals.Length) { mesh.Indices[i].AverageNormal = file.AverageNormals[index.AverageNormalIndex]; } if (file.GetShaderDataFromOffset(index.REShaderOffset, out ROUNDEDGE_SHADER_DATA shaderData)) { mesh.Indices[i].RoundEdgeData = new RoundEdgeData(shaderData.Coords.Take(6).ToArray()); } } }
protected override void OnUpdateBeforeOutput(Viewport viewport) { base.OnUpdateBeforeOutput(viewport); lastStartPointRectangle = null; var points = MeshGeometry.GetPointPositions(); if (!heightStage && points.Length > 2) { if (viewport.CameraSettings.ProjectToScreenCoordinates(points[0], out var screenPosition)) { var pos = points[0]; Vector2 maxSize = new Vector2(20, 20); Vector2 minSize = new Vector2(5, 5); double maxDistance = 100; double distance = (pos - viewport.CameraSettings.Position).Length(); if (distance < maxDistance) { Vector2 sizeInPixels = Vector2.Lerp(maxSize, minSize, distance / maxDistance); Vector2 screenSize = sizeInPixels / viewport.SizeInPixels.ToVector2(); screenSize *= 1.5; var rect = new Rectangle(screenPosition - screenSize * .5, screenPosition + screenSize * .5); ColorValue color; if (!viewport.MouseRelativeMode && rect.Contains(viewport.MousePosition)) { color = new ColorValue(1, 1, 0, 0.5); } else { color = new ColorValue(1, 1, 1, 0.3); } viewport.CanvasRenderer.AddQuad(rect, color); lastStartPointRectangle = rect; } } } }
public static Mesh LddMeshToAssimp(MeshGeometry geometry) { var assimpMesh = new Mesh(Assimp.PrimitiveType.Triangle); bool isTextured = geometry.IsTextured; foreach (var v in geometry.Vertices) { assimpMesh.Vertices.Add(v.Position.ToAssimp()); assimpMesh.Normals.Add(v.Normal.ToAssimp()); if (isTextured) { assimpMesh.TextureCoordinateChannels[0].Add(new Vector3D(v.TexCoord.X, v.TexCoord.Y, 0)); } } if (geometry.IsFlexible) { var boneIDs = geometry.Vertices.SelectMany(x => x.BoneWeights).Select(y => y.BoneID).Distinct().ToList(); var boneDict = new Dictionary <int, Bone>(); boneIDs.ForEach(x => boneDict.Add(x, new Bone() { Name = GetBoneName(x) })); for (int vIdx = 0; vIdx < geometry.VertexCount; vIdx++) { foreach (var bw in geometry.Vertices[vIdx].BoneWeights) { boneDict[bw.BoneID].VertexWeights.Add(new VertexWeight(vIdx, bw.Weight)); } } assimpMesh.Bones.AddRange(boneDict.Values); } int[] indices = geometry.GetTriangleIndices(); for (int i = 0; i < indices.Length; i += 3) { assimpMesh.Faces.Add(new Face(new int[] { indices[i], indices[i + 1], indices[i + 2] })); } return(assimpMesh); }
protected override MeshGeometry DeriveMeshGeometryData(Mesh mesh, Transform[] bones) { var parentChannel = bones[0]; var result = new MeshGeometry(); var verticesList = mesh.vertices.Select(x => new Vector3d(x.x, x.y, x.z)).ToList(); Dictionary <string, Dictionary <int, float> > bonesWeights = new Dictionary <string, Dictionary <int, float> >(); Dictionary <int, float> verticesBoneWeights = new Dictionary <int, float>(); for (int i = 0; i < verticesList.Count; i++) { verticesBoneWeights.Add(i, 1.0f); } bonesWeights.Add(parentChannel.name, verticesBoneWeights); result.vertices = verticesList; result.triangles = MeshDataHelper.GetTrianglesList(mesh.triangles); result.bonesWeights = bonesWeights; result.normals = MeshDataHelper.GetNormals(mesh.normals); result.uvMaps = MeshDataHelper.GetUvMaps(mesh); return(result); }
private unsafe void DebugMesh(MeshGeometry mesh) { System.Console.WriteLine("---------Positions-----------------"); UnmanagedArray <Vertex> array = mesh.Vertexes; for (int i = 0; i < array.Length; i++) { Vertex v = array[i]; System.Console.WriteLine(string.Format("({0},{1},{2})", v.X, v.Y, v.Z)); } System.Console.WriteLine("---------Colors-----------------"); UnmanagedArray <ColorF> colors = mesh.VertexColors; for (int i = 0; i < colors.Length; i++) { ColorF c = colors[i]; System.Console.WriteLine(string.Format("({0},{1},{2},{3})", c.R, c.G, c.B, c.A)); } System.Console.WriteLine("---------visibles-----------------"); UnmanagedArray <float> visibles = mesh.Visibles; for (int i = 0; i < visibles.Length; i++) { float c = visibles[i]; System.Console.WriteLine(string.Format("({0})", c)); } System.Console.WriteLine("---------TriangleTrip-----------------"); UnmanagedArray <uint> triangles = mesh.StripTriangles; for (int i = 0; i < triangles.Length; i++) { uint t = triangles[i]; System.Console.WriteLine(string.Format("({0})", t)); } }
public AnimatedExportObjectModel convert(ExportableModel r3AnimatedMesh) { AnimatedExportObjectModel result = new AnimatedExportObjectModel(); result.Name = r3AnimatedMesh.gameObject.name; Dictionary <string, BoneBindPose> bonesBindPoses = GetBonesBindPoseTransforms(r3AnimatedMesh). ToDictionary( x => x.Key, x => new BoneBindPose( x.Key, x.Value.position, x.Value.rotation, x.Value.scale )); MeshGeometry meshGeometry = DeriveMeshGeometryData(GetMesh(r3AnimatedMesh), GetBonesTransforms(r3AnimatedMesh)); TransformModel transformModel = GetTransformModel(r3AnimatedMesh.transform); result.bindBonePoses = bonesBindPoses; result.meshGeometry = meshGeometry; result.transform = transformModel; result.materials = GetMaterials(r3AnimatedMesh); return(result); }
private void Create3DObject(object sender, EventArgs e) { try { int nx = System.Convert.ToInt32(tbNX.Text); int ny = System.Convert.ToInt32(tbNY.Text); int nz = System.Convert.ToInt32(tbNZ.Text); float step = System.Convert.ToSingle(tbColorIndicatorStep.Text); float radius = System.Convert.ToSingle(this.tbRadius.Text); int dimenSize = nx * ny * nz; float dx = System.Convert.ToSingle(this.tbDX.Text); float dy = System.Convert.ToSingle(this.gbDY.Text); float dz = System.Convert.ToSingle(this.tbDZ.Text); float[] dxArray = initArray(dimenSize, dx); float[] dyArray = initArray(dimenSize, dy); float[] dzArray = initArray(dimenSize, dz); // use CatesianGridderSource to fill HexahedronGridderElement's content. CatesianGridderSource source = new CatesianGridderSource() { NX = nx, NY = ny, NZ = nz, DX = dxArray, DY = dyArray, DZ = dzArray, }; source.IBlocks = GridBlockHelper.CreateBlockCoords(nx); source.JBlocks = GridBlockHelper.CreateBlockCoords(ny); source.KBlocks = GridBlockHelper.CreateBlockCoords(nz); //DemoPointSpriteGridderSource source = new DemoPointSpriteGridderSource() { NX = nx, NY = ny, NZ = nz, }; ///模拟获得网格属性 int minValue = 100; int maxValue = 10000; step = (maxValue * 1.0f - minValue * 1.0f) / 10; int[] gridIndexes; float[] gridValues; //设置色标的范围 this.scientificVisual3DControl.SetColorIndicator(minValue, maxValue, step); //获得每个网格上的属性值 HexahedronGridderHelper.RandomValue(source.DimenSize, minValue, maxValue, out gridIndexes, out gridValues); ColorF[] colors = new ColorF[source.DimenSize]; for (int i = 0; i < colors.Length; i++) { colors[i] = (ColorF)this.scientificVisual3DControl.MapToColor(gridValues[i]); } // use HexahedronGridderElement DateTime t0 = DateTime.Now; MeshGeometry mesh = HexahedronGridderHelper.CreateMesh(source); DateTime t1 = DateTime.Now; TimeSpan ts1 = t1 - t0; mesh.VertexColors = HexahedronGridderHelper.FromColors(source, gridIndexes, colors, mesh.Visibles); //this.DebugMesh(mesh); HexahedronGridderElement gridderElement = new HexahedronGridderElement(source, this.scientificVisual3DControl.Scene.CurrentCamera); gridderElement.renderWireframe = false; //method1 //gridderElement.Initialize(this.scientificVisual3DControl.OpenGL); //method2 gridderElement.Initialize(this.scientificVisual3DControl.OpenGL, mesh); DateTime t2 = DateTime.Now; //gridderElement.SetBoundingBox(mesh.Min, mesh.Max); //// use PointSpriteGridderElement //PointSpriteMesh mesh = PointSpriteGridderElementHelper.CreateMesh(source); //mesh.ColorArray = PointSpriteGridderElementHelper.FromColors(source, gridIndexes, colors, mesh.VisibleArray); //PointSpriteGridderElement gridderElement = new PointSpriteGridderElement(source, this.scientificVisual3DControl.Scene.CurrentCamera); //gridderElement.Initialize(this.scientificVisual3DControl.OpenGL, mesh); ////DebugMesh(mesh); // gridderElement.Name = string.Format("element {0}", elementCounter++); this.scientificVisual3DControl.AddModelElement(gridderElement); DateTime t3 = DateTime.Now; // update ModelContainer's BoundingBox. BoundingBox boundingBox = this.scientificVisual3DControl.ModelContainer.BoundingBox; if (this.scientificVisual3DControl.ModelContainer.Children.Count > 1) { boundingBox.Extend(mesh.Min); boundingBox.Extend(mesh.Max); } else { boundingBox.SetBounds(mesh.Min, mesh.Max); } //boundingBox.Expand(); // update ViewType to UserView. this.scientificVisual3DControl.ViewType = ViewTypes.UserView; mesh.Dispose(); StringBuilder msgBuilder = new StringBuilder(); msgBuilder.AppendLine(String.Format("create mesh in {0} secs", (t1 - t0).TotalSeconds)); msgBuilder.AppendLine(String.Format("init SceneElement in {0} secs", (t2 - t1).TotalSeconds)); msgBuilder.AppendLine(String.Format("total load in {0} secs", (t2 - t0).TotalSeconds)); String msg = msgBuilder.ToString(); MessageBox.Show(msg, "Summary", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception error) { MessageBox.Show(error.ToString()); } }
private void TrySetTextureProperties(aiMaterial outMat, Dictionary<string, LayeredTexture> layeredTextures, string propName, aiTextureType target, MeshGeometry mesh) { LayeredTexture it; if (!layeredTextures.TryGetValue(propName, out it)) { return; } var tex = it.Texture; var path = tex.RelativeFilename; outMat.TextureSlotCollection[target].TextureBase = path; var uvTrafo = new AssimpSharp.UVTransform(); uvTrafo.Scaling = tex.UVScaling; uvTrafo.Translation = tex.UVTranslation; outMat.TextureSlotCollection[target].UVTransformBase = uvTrafo; var props = tex.Props; var uvIndex = 0; bool ok; var uvSet = PropertyHelper.PropertyGet<string>(props, "UVSet", out ok); if (ok) { if (uvSet != "default" && !string.IsNullOrEmpty(uvSet)) { var matIndex = Materials.IndexOf(outMat); uvIndex = -1; if (mesh == null) { foreach (var v in MeshesConverted) { var mesh_ = v.Key as MeshGeometry; if (mesh_ == null) { continue; } var mats = mesh_.MaterialIndices; if (!mats.Contains(matIndex)) { continue; } int index = -1; for (int i = 0; i < aiMesh.AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) { if (mesh.GetTextureCoords(i).Count == 0) { break; } var name = mesh.GetTextureCoordChannelName(i); if (name == uvSet) { index = i; break; } } if (index == -1) { FBXImporter.LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); continue; } if (uvIndex == -1) { uvIndex = index; } else { FBXImporter.LogWarn("the UV channel named " + uvSet + " appears at different positions in meshes, results will be wrong"); } } } else { int index = -1; for (int i = 0; i < aiMesh.AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) { if (mesh.GetTextureCoords(i).Count == 0) { break; } var name = mesh.GetTextureCoordChannelName(i); if (name == uvSet) { index = i; break; } } if (index == -1) { FBXImporter.LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); } if (uvIndex == -1) { uvIndex = index; } } if (uvIndex == -1) { FBXImporter.LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); uvIndex = 0; } } } outMat.TextureSlotCollection[target].UVWSrcBase = uvIndex; }
private int ConvertMaterial(Material material, MeshGeometry mesh) { var props = material.Props; // generate empty output material var outMat = new aiMaterial(); this.MaterialsConverted[material] = this.Materials.Count; this.Materials.Add(outMat); // stip Material:: prefix string name = material.Name; if (name.Substring(0, 10) == "Material::") { name = name.Substring(10); } // set material name if not empty - this could happen // and there should be no key for it in this case. if (name.Length > 0) { outMat.Name = name; } // shading stuff and colors SetShadingPropertiesCommon(outMat, props); // texture assignments SetTextureProperties(outMat, material.Textures, mesh); SetTextureProperties(outMat, material.LayeredTextures, mesh); return this.Materials.Count - 1; }
protected override bool OnMouseDown(Viewport viewport, EMouseButtons button) { if (button == EMouseButtons.Left) { bool overStartPoint = !heightStage && lastStartPointRectangle.HasValue && lastStartPointRectangle.Value.Contains(viewport.MousePosition); if (heightStage) { Finish(false); return(true); } else if (overStartPoint) { HeightStageStart(viewport); return(true); } else { var points = MeshGeometry.GetPoints(); if (!viewport.MouseRelativeMode) { if (points.Length >= 3) { var plane = MeshGeometry.GetPolygonPlaneByPoints(); var ray = viewport.CameraSettings.GetRayByScreenCoordinates(viewport.MousePosition); if (plane.Intersects(ray, out double scale)) { var position = ray.GetPointOnRay(scale); var point = MeshGeometry.CreateComponent <Component_MeshGeometry_PolygonBasedPolyhedron_Point>(enabled: false); point.Name = MeshGeometry.Components.GetUniqueName("Point", false, 1); point.Transform = new Transform(position, Quaternion.Identity); point.Enabled = true; return(true); } } else { if (CalculatePointPosition(viewport, out var position, out var collidedWith)) { var point = MeshGeometry.CreateComponent <Component_MeshGeometry_PolygonBasedPolyhedron_Point>(enabled: false); point.Name = MeshGeometry.Components.GetUniqueName("Point", false, 1); point.Transform = new Transform(position, Quaternion.Identity); point.Enabled = true; //detect Clockwise var points2 = MeshGeometry.GetPointPositions(); if (points2.Length == 3) { var normal = Plane.FromPoints(points2[0], points2[1], points2[2]).Normal; var d1 = (points2[0] - viewport.CameraSettings.Position).Length(); var d2 = ((points2[0] + normal) - viewport.CameraSettings.Position).Length(); if (d1 < d2) { MeshGeometry.Clockwise = true; } } return(true); } } } } } return(false); }
public void SetGeometry(MeshGeometry geometry) { Geometry = geometry; }
private List<int> ConvertMeshMultiMaterial(MeshGeometry mesh, Model model, Matrix nodeGlobalTransform) { var mindices = mesh.MaterialIndices; Debug.Assert(mindices.Count > 0); var had = new HashSet<int>(); var indices = new List<int>(); foreach (var index in mindices) { if (!had.Contains(index)) { indices.Add(ConvertMeshMultiMaterial(mesh, model, index, nodeGlobalTransform)); had.Add(index); } } return indices; }
private int ConvertMeshSingleMaterial(MeshGeometry mesh, Model model, Matrix nodeGlobalTransform) { var mindices = mesh.MaterialIndices; var outMesh = SetupEmptyMesh(mesh); var vertices = mesh.Vertices; var faces = mesh.FaceIndexCounts; // copy vertices outMesh.NumVertices = vertices.Count; outMesh.Vertices = new Vector3[vertices.Count]; vertices.CopyTo(outMesh.Vertices); // generate dummy faces outMesh.NumFaces = faces.Count; var fac = outMesh.Faces = new AssimpSharp.Face[faces.Count]; for(int i=0; i<faces.Count; i++) { fac[i] = new AssimpSharp.Face(); } int cursor = 0; var facIndex = 0; foreach(var pcount in faces) { var f = fac[facIndex++]; f.Indices = new int[pcount]; switch(pcount) { case 1: outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Point; break; case 2: outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Line; break; case 3: outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Triangle; break; default: outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Polygon; break; } for(int i=0; i<pcount; ++i) { f.Indices[i] = cursor++; } } // copy normals var normals = mesh.Normals; if (normals.Count > 0) { Debug.Assert(normals.Count == vertices.Count); outMesh.Normals = new Vector3[vertices.Count]; normals.CopyTo(outMesh.Normals); } // copy tangents - assimp requires both tangents and bitangents (binormals) // to be present, or neither of them. Compute binormals from normals // and tangents if needed. var tangents = mesh.Tangents; var binormals = mesh.Binormals; if (tangents.Count > 0) { var tempBinormals = new List<Vector3>(); if (binormals.Count == 0) { if (normals.Count > 0) { tempBinormals = new List<Vector3>(normals.Count); for(int i=0; i<tangents.Count; i++) { tempBinormals.Add(Vector3.Cross(normals[i], tangents[i])); } binormals.Clear(); for(int i=0; i<tempBinormals.Count; i++) { binormals.Add(tempBinormals[i]); } } else { binormals = null; } } if (binormals != null) { Debug.Assert(tangents.Count == vertices.Count); Debug.Assert(binormals.Count == vertices.Count); outMesh.Tangents = new Vector3[vertices.Count]; tangents.CopyTo(outMesh.Tangents); outMesh.Bitangents = new Vector3[vertices.Count]; binormals.CopyTo(outMesh.Bitangents); } } // copy texture coords for (int i=0; i<Mesh.AI_MAX_NUMBER_OF_TEXTURECOORDS; i++) { var uvs = mesh.GetTextureCoords(i); if (uvs.Count == 0) { break; } var outUv = outMesh.TextureCoords[i] = new Vector3[vertices.Count]; for(int j=0; j<uvs.Count; j++) { outUv[j] = new Vector3(uvs[j].X, uvs[j].Y, 0); } } // copy vertex colors for (int i = 0; i < aiMesh.AI_MAX_NUMBER_OF_COLOR_SETS; ++i) { var colors = mesh.GetVertexColors(i); if (colors.Count == 0) { break; } outMesh.Colors[i] = new Color4[vertices.Count]; colors.CopyTo(outMesh.Colors[i]); } if (!Doc.Settings.ReadMaterials || mindices.Count == 0) { //FBXImporter.LogError("no material assigned to mesh, setting default material"); outMesh.MaterialIndex = GetDefaultMaterial(); } else { ConvertMaterialForMesh(outMesh, model, mesh, mindices[0]); } if (Doc.Settings.ReadWeights && mesh.DeformerSkin != null) { ConvertWeights(outMesh, model, mesh, nodeGlobalTransform, NO_MATERIAL_SEPARATION); } return Meshes.Count - 1; }
/// <summary> /// Initialize our basic model /// </summary> /// <param name="device">Direct3D device for use</param> /// <param name="texMgr">Texture manager from which to load texture data</param> /// <param name="filename">Filename of the ASSIMP resource we would like to load (see ASSIMP documentation for supported formats)</param> /// <param name="texturePath">Texture path - base path for textures used by the ASSIMP model</param> public BasicModel(Device device, TextureManager texMgr, string filename, string texturePath) { _subsets = new List<MeshGeometry.Subset>(); _vertices = new List<BasicEffectVertex>(); _indices = new List<ushort>(); DiffuseMapSRV = new List<ShaderResourceView>(); NormalMapSRV = new List<ShaderResourceView>(); Materials = new List<Lighting.Material>(); _modelMesh = new MeshGeometry(); var importer = new AssimpContext(); if (!importer.IsImportFormatSupported(Path.GetExtension(filename))) { throw new ArgumentException($"Model format {Path.GetExtension(filename)} is not supported! Cannot load {filename}", "Outside Engine"); } var model = importer.ImportFile(filename, PostProcessSteps.GenerateSmoothNormals | PostProcessSteps.CalculateTangentSpace); #if DEBUG var logStream = new ConsoleLogStream(); logStream.Attach(); #endif foreach (var mesh in model.Meshes) { // // Vertex processing // var verts = new List<BasicEffectVertex>(); var subset = new MeshGeometry.Subset { VertexCount = mesh.VertexCount, VertexStart = _vertices.Count, FaceStart = _indices.Count / 3, FaceCount = mesh.FaceCount }; _subsets.Add(subset); // TODO KAM: Process bounding box corners for (var i = 0; i < mesh.VertexCount; ++i) { Vector3 pos = mesh.HasVertices ? mesh.Vertices[i].ToVector3() : new Vector3(); var norml = mesh.HasNormals ? mesh.Normals[i].ToVector3() : new Vector3(); var texC = mesh.HasTextureCoords(0) ? mesh.TextureCoordinateChannels[0][i].ToVector3() : new Vector3(); var tan = mesh.HasTangentBasis ? mesh.Tangents[i].ToVector3() : new Vector3(); var v = new BasicEffectVertex(pos, norml, new Vector2(texC.X, texC.Y)); verts.Add(v); } _vertices.AddRange(verts); var indices = mesh.GetIndices().Select(i => (ushort)(i + (uint)subset.VertexStart)).ToList(); _indices.AddRange(indices); // // Material processing // var mat = model.Materials[mesh.MaterialIndex]; var material = mat.ToMaterial(); Materials.Add(material); TextureSlot diffuseSlot; mat.GetMaterialTexture(TextureType.Diffuse, 0, out diffuseSlot); var diffusePath = diffuseSlot.FilePath; if (Path.GetExtension(diffusePath) == ".tga") { throw new InvalidDataException("Cannot use TGA files for textures with DirectX. Sorry about that."); } if (!string.IsNullOrEmpty(diffusePath)) { DiffuseMapSRV.Add(texMgr.GetTexture(Path.Combine(texturePath, diffusePath))); } TextureSlot normalSlot; mat.GetMaterialTexture(TextureType.Normals, 0, out normalSlot); var normalPath = normalSlot.FilePath; if (!string.IsNullOrEmpty(normalPath)) { NormalMapSRV.Add(texMgr.GetTexture(Path.Combine(texturePath, normalPath))); } else { var normalExt = Path.GetExtension(diffusePath); normalPath = Path.GetFileNameWithoutExtension(diffusePath) + "_nmap" + normalExt; NormalMapSRV.Add(texMgr.GetTexture(Path.Combine(texturePath, normalPath))); } } _modelMesh.SetSubsetTable(_subsets); _modelMesh.SetVertices(device, _vertices); _modelMesh.SetIndices(device, _indices); }
private static MESH_DATA SerializeMeshGeometry(MESH_FILE file, ShaderDataHelper shaderData, MeshGeometry meshGeometry) { var meshData = MESH_DATA.Create(meshGeometry.VertexCount, meshGeometry.IndexCount, file.IsTextured, file.IsFlexible); var vertIndexer = new ListIndexer <Vertex>(meshGeometry.Vertices); for (int i = 0; i < meshGeometry.Vertices.Count; i++) { var vert = meshGeometry.Vertices[i]; meshData.Positions[i] = vert.Position; meshData.Normals[i] = vert.Normal; if (file.IsTextured) { meshData.UVs[i] = meshGeometry.IsTextured ? vert.TexCoord : new Vector2(0f); } if (file.IsFlexible && vert.BoneWeights.Any()) { var boneWeights = vert.BoneWeights.Select(x => new MESH_BONE_WEIGHT { BoneID = x.BoneID, Weight = x.Weight }); meshData.Bones[i] = new MESH_BONE_MAPPING(boneWeights); } } for (int i = 0; i < meshGeometry.Indices.Count; i++) { var idx = meshGeometry.Indices[i]; meshData.Indices[i].VertexIndex = vertIndexer.IndexOf(idx.Vertex); meshData.Indices[i].AverageNormalIndex = shaderData.AvgNormals.IndexOf(idx.AverageNormal); int reIdx = shaderData.RoundEdgeData.IndexOf(idx.RoundEdgeData); int reOffset = reIdx * 12 + ((int)Math.Floor(reIdx / 21d) * 4); meshData.Indices[i].REShaderOffset = reOffset; } return(meshData); }
/// <summary> /// The geometry object has a list of polygon faces. /// Take those, and use them to populate the subMesh object. /// TODO: Do I need to compact those first? /// Do I need to build consolidated sets of points that the face indexes can refer to? /// </summary> /// <param name="subMesh">the Axiom SubMesh object that we will populate</param> /// <param name="geometry">the geometry information that contains the polygons</param> /// <param name="indexType">the type of face index (16 bit or 32 bit)</param> protected void ProcessFaces( SubMeshInfo subMeshInfo, MeshGeometry geometry, IndexType indexType ) { SubMesh subMesh = m_AxiomMesh.CreateSubMesh( subMeshInfo.name ); subMesh.MaterialName = subMeshInfo.material; int[ , ] data = geometry.GetFaceData(); subMesh.indexData.indexStart = 0; subMesh.indexData.indexCount = data.GetLength( 0 ) * data.GetLength( 1 ); HardwareIndexBuffer idxBuffer = null; // create the index buffer idxBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( indexType, subMesh.indexData.indexCount, m_AxiomMesh.IndexBufferUsage, m_AxiomMesh.UseIndexShadowBuffer ); HWBuffer.FillBuffer( idxBuffer, subMesh.indexData.indexCount, indexType, data ); // save the index buffer subMesh.indexData.indexBuffer = idxBuffer; }
/// <summary> /// Compute the intersection between a mesh face perimeter and a ray tangent to the face. /// </summary> /// <param name="ray">The tangent ray.</param> /// <param name="face">The mesh face.</param> /// <param name="result">The resulting intersection point.</param> /// <param name="halfEdge">The half-edge on where the intersection lies.</param> /// <returns>Intersection result.</returns> public static ISRayFacePerimeter RayFacePerimeter(Ray ray, MeshFace face, out Point3d result, out MeshHalfEdge halfEdge) { Vector3d faceNormal = MeshGeometry.FaceNormal(face); Vector3d biNormal = Vector3d.CrossProduct(ray.Direction, faceNormal); Plane perpPlane = new Plane(ray.Origin, ray.Direction, faceNormal, biNormal); List <MeshVertex> vertices = face.AdjacentVertices(); Point3d temp = new Point3d(); Line line = new Line(vertices[0], vertices[1]); if (LinePlane(line, perpPlane, out temp) != ISLinePlane.Point) { result = null; halfEdge = null; return(ISRayFacePerimeter.Point); } // No intersection found if (temp != ray.Origin && temp != null) { result = temp; halfEdge = null; return(ISRayFacePerimeter.Point); } // Intersection found line = new Line(vertices[1], vertices[2]); if (LinePlane(line, perpPlane, out temp) != ISLinePlane.Point) { result = null; halfEdge = null; return(ISRayFacePerimeter.NoIntersection); } // No intersection found if (temp != ray.Origin && temp != null) { result = temp; halfEdge = null; return(ISRayFacePerimeter.Point); } // Intersection found line = new Line(vertices[2], vertices[0]); if (LinePlane(line, perpPlane, out temp) != ISLinePlane.Point) { result = null; halfEdge = null; return(ISRayFacePerimeter.NoIntersection); } if (temp != ray.Origin && temp != null) { result = temp; halfEdge = null; return(ISRayFacePerimeter.Point); } else { result = null; halfEdge = null; return(ISRayFacePerimeter.Error); } }
/// <summary> /// Compute the intersection between a mesh face perimeter and a ray tangent to the face. /// </summary> /// <param name="ray">The tangent ray.</param> /// <param name="face">The mesh face.</param> /// <param name="result">The resulting intersection point.</param> /// <param name="halfEdge">The half-edge on where the intersection lies.</param> /// <returns>Intersection result.</returns> public static RayFacePerimeterIntersectionStatus RayFacePerimeter( Ray ray, MeshFace face, out Point3d result, out MeshHalfEdge halfEdge) { var faceNormal = MeshGeometry.FaceNormal(face); var biNormal = Vector3d.CrossProduct(ray.Direction, faceNormal); var perpPlane = new Plane(ray.Origin, ray.Direction, faceNormal, biNormal); var vertices = face.AdjacentVertices(); var temp = new Point3d(); var line = new Line(vertices[0], vertices[1]); if (LinePlane(line, perpPlane, out temp) != LinePlaneIntersectionStatus.Point) { result = null; halfEdge = null; return(RayFacePerimeterIntersectionStatus.Point); } // No intersection found if (temp != ray.Origin && temp != null) { result = temp; halfEdge = null; return(RayFacePerimeterIntersectionStatus.Point); } // Intersection found line = new Line(vertices[1], vertices[2]); if (LinePlane(line, perpPlane, out temp) != LinePlaneIntersectionStatus.Point) { result = null; halfEdge = null; return(RayFacePerimeterIntersectionStatus.NoIntersection); } if (temp != ray.Origin && temp != null) { result = temp; halfEdge = null; return(RayFacePerimeterIntersectionStatus.Point); } line = new Line(vertices[2], vertices[0]); if (LinePlane(line, perpPlane, out temp) != LinePlaneIntersectionStatus.Point) { result = null; halfEdge = null; return(RayFacePerimeterIntersectionStatus.NoIntersection); } if (temp != ray.Origin && temp != null) { result = temp; halfEdge = null; return(RayFacePerimeterIntersectionStatus.Point); } result = null; halfEdge = null; return(RayFacePerimeterIntersectionStatus.Error); }
protected void BuildOneVertexBuffer( Matrix4 worldTransform, Matrix4 bindShapeMatrix, MeshGeometry geometry ) { VertexData vertexData = geometry.VertexData; vertexData.vertexStart = 0; vertexData.vertexCount = geometry.IndexSets.Count; List<InputSource> geometryInputs = geometry.GetAllInputSources(); #region Texture stuff // We need to build a compact set of texture coordinates. There can be multiple // sets of texture coordinates, but the indices must start at 0 to work for all // graphics cards. Dictionary<InputSource, int> inputSetMap = new Dictionary<InputSource, int>(); int maxInputSet = -1; Dictionary<int, List<InputSource>> unnumberedInputs = new Dictionary<int, List<InputSource>>(); // First make a pass through, storing the index sets for the inputs for( int accessIndex = 0; accessIndex < geometryInputs.Count; ++accessIndex ) { InputSource input = geometryInputs[ accessIndex ]; if( input.Set != -1 ) { inputSetMap[ input ] = input.Set; if( input.Set > maxInputSet ) maxInputSet = input.Set; } else AddUnnumberedInput( input, unnumberedInputs ); } // If we have stuff associated with input set 0, we need to find // out where to put the default data, such as position and normals. // We would like to assign input set 0 to these as well, but if // those are already used, we need to move whatever is there. if( unnumberedInputs.Count > 0 ) { // We have some items that need a set. If there is no // collision with the inputs associated with 0, we can just // assign these entries to 0. In that case, if there is no // collision with the lowest numbered set, we will also // want to move the lowest numbered set down to zero. List<int> keys = new List<int>( unnumberedInputs.Keys ); keys.Sort(); keys.Reverse(); foreach( int i in keys ) AddUnnumberedInputs( unnumberedInputs[ i ], inputSetMap ); } // Now build a mapping from input sets to texture indices // This collapses the set and removes gaps Dictionary<int, int> textureIndexMap = new Dictionary<int, int>(); int maxTextureIndex = -1; List<int> inputIndices = new List<int>( inputSetMap.Values ); inputIndices.Sort(); foreach( int inputSetId in inputIndices ) { if( textureIndexMap.ContainsKey( inputSetId ) ) continue; textureIndexMap[ inputSetId ] = ++maxTextureIndex; } #endregion Texture stuff // What is the offset into point components of the given input for( int accessIndex = 0; accessIndex < geometryInputs.Count; ++accessIndex ) { InputSource input = geometryInputs[ accessIndex ]; int textureIndex = textureIndexMap[ inputSetMap[ input ] ]; m_Log.InfoFormat( "Assigned texture index {0} to input {1} with set {2}", textureIndex, input.Source, input.Set ); ProcessInput( geometry, input, accessIndex, textureIndex, geometry.IndexSets.Count ); } // If we are a pose target, we want to skip building the faces // and the submesh, and just skip to the next section where we // transform the geometry. if( !geometry.GeometrySet.IsPoseTarget ) { foreach( SubMeshInfo smInfo in geometry.SubMeshes ) { // Ok, now use the geometry to make a submesh IndexType indexType = IndexType.Size16; if( geometry.IndexSets.Count > short.MaxValue ) { indexType = IndexType.Size32; m_Log.Warn( "Warning: submesh requires 32 bit index. This will not work on DirectX 6 cards such as the common Intel series." ); } ProcessFaces( smInfo, geometry, indexType ); } if( geometry.SubMeshes.Count > 1 ) { if( m_AxiomMesh.SharedVertexData != null ) { m_Log.Error( "Failed to load file: multiple shared submeshes" ); throw new Exception( "Failed to load file: multiple shared submeshes" ); } m_AxiomMesh.SharedVertexData = vertexData; foreach( SubMeshInfo smInfo in geometry.SubMeshes ) { SubMesh subMesh = m_AxiomMesh.GetSubMesh( smInfo.name ); subMesh.useSharedVertices = true; } } else if( geometry.SubMeshes.Count == 1 ) { string subMeshName = geometry.SubMeshes[ 0 ].name; SubMesh subMesh = m_AxiomMesh.GetSubMesh( subMeshName ); subMesh.vertexData = vertexData; subMesh.useSharedVertices = false; } } // Do the 'freeze transforms' step where we bake the transform // of this geometry into the data. This is only the first part // of this. We will also need to multiply it by the transform // matrix that was passed in via the command line. Finally, we // generally need to transform this data to reskin it to the // skeleton's bind pose. // TODO: At some point, I could handle instanced geometry here by // generating other submeshes. geometry.Transform( worldTransform * bindShapeMatrix ); }
public static void BuildBoundingBox( Mesh mesh, MeshGeometry geometry ) { Vector3 max = mesh.BoundingBox.Maximum; Vector3 min = mesh.BoundingBox.Minimum; foreach( VertexDataEntry vde in geometry.VertexDataEntries ) { if( vde.semantic != VertexElementSemantic.Position ) continue; for( int i = 0; i < geometry.VertexData.vertexCount; ++i ) { if( vde.fdata[ i, 0 ] < min.x ) min.x = vde.fdata[ i, 0 ]; if( vde.fdata[ i, 0 ] > max.x ) max.x = vde.fdata[ i, 0 ]; if( vde.fdata[ i, 1 ] < min.y ) min.y = vde.fdata[ i, 1 ]; if( vde.fdata[ i, 1 ] > max.y ) max.y = vde.fdata[ i, 1 ]; if( vde.fdata[ i, 2 ] < min.z ) min.z = vde.fdata[ i, 2 ]; if( vde.fdata[ i, 2 ] > max.z ) max.z = vde.fdata[ i, 2 ]; } } mesh.BoundingBox = new AxisAlignedBox( min, max ); }
private void CanCompute_MeshArea() { var area = MeshGeometry.TotalArea(this.FlatTriangle); Assert.True(Math.Abs(area - 0.5) < Settings.Tolerance); }
public ModelMesh(MeshGeometry geometry) { Geometry = geometry; UpdateMeshProperties(); }
private int ConvertMeshMultiMaterial(MeshGeometry mesh, Model model, int index, Matrix nodeGlobalTransform) { var outMesh = SetupEmptyMesh(mesh); var mindices = mesh.MaterialIndices; var vertices = mesh.Vertices; var faces = mesh.FaceIndexCounts; var processWeights = Doc.Settings.ReadWeights && (mesh.DeformerSkin != null); int countFaces = 0; int countVertices = 0; // count faces var itf = faces.GetEnumerator(); foreach(var it in mindices) { itf.MoveNext(); if (it != index) { continue; } ++countFaces; countVertices += (int)itf.Current; } Debug.Assert(countFaces > 0); Debug.Assert(countVertices > 0); // mapping from output indices to DOM indexing, needed to resolve weights var reverseMappigng = new int[0]; if (processWeights) { reverseMappigng = new int[countVertices]; } // allocate output data arrays, but don't fill them yet outMesh.Vertices = new Vector3[countVertices]; var fac = outMesh.Faces = new AssimpSharp.Face[countFaces]; // allocate normals var normals = mesh.Normals; if (normals.Count > 0) { Debug.Assert(normals.Count == vertices.Count); outMesh.Normals = new Vector3[vertices.Count]; } // allocate tangents, binormals. var tangets = mesh.Tangents; var binormals = mesh.Binormals; if (tangets.Count > 0) { Vector3[] tempBinormals = new Vector3[0]; if (binormals.Count == 0) { if (normals.Count > 0) { // XXX this computes the binormals for the entire mesh, not only // the part for which we need them. tempBinormals = new Vector3[normals.Count]; for (int i = 0; i < tangets.Count; i++) { tempBinormals[i] = Vector3.Cross(normals[i], tangets[i]); } binormals.Clear(); for (int i = 0; i < tempBinormals.Length; i++) { binormals.Add(tempBinormals[i]); } } else { binormals = null; } } if (binormals.Count > 0) { Debug.Assert(tangets.Count == vertices.Count); Debug.Assert(binormals.Count == vertices.Count); outMesh.Tangents = new Vector3[vertices.Count]; outMesh.Bitangents = new Vector3[vertices.Count]; } } // allocate texture coords int numUvs = 0; for (int i = 0; i < AssimpSharp.Mesh.AI_MAX_NUMBER_OF_TEXTURECOORDS; i++, numUvs++) { var uvs = mesh.GetTextureCoords(i); if (uvs.Count == 0) { break; } outMesh.TextureCoords[i] = new Vector3[vertices.Count]; outMesh.NumUVComponents[i] = 2; } // allocate vertex colors int numVcs = 0; for (int i = 0; i < AssimpSharp.Mesh.AI_MAX_NUMBER_OF_COLOR_SETS; i++, numVcs++) { var colors = mesh.GetVertexColors(i); if (colors.Count == 0) { break; } outMesh.Colors[i] = new Color4[vertices.Count]; } int cursor = 0; int inCursor = 0; int facesIndex = 0; int facIndex = 0; foreach (var it in mindices) { int pcount = (int)faces[facesIndex]; if (it != index) { inCursor += pcount; continue; } var f = fac[facIndex++] = new Face(); f.Indices = new int[pcount]; switch (pcount) { case 1: outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Point; break; case 2: outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Line; break; case 3: outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Triangle; break; default: outMesh.PrimitiveTypes |= AssimpSharp.PrimitiveType.Polygon; break; } for (int i = 0; i < pcount; ++i, ++cursor, ++inCursor) { f.Indices[i] = cursor; if (reverseMappigng.Length > 0) { reverseMappigng[cursor] = inCursor; } outMesh.Vertices[cursor] = vertices[inCursor]; if (outMesh.Normals.Length > 0) { outMesh.Normals[cursor] = normals[inCursor]; } if (outMesh.Tangents.Length > 0) { outMesh.Tangents[cursor] = tangets[inCursor]; outMesh.Bitangents[cursor] = binormals[inCursor]; } for (int j = 0; j < numUvs; j++) { var uvs = mesh.GetTextureCoords(j); outMesh.TextureCoords[j][cursor] = new Vector3(uvs[inCursor], 0.0f); } for (int j = 0; j < numVcs; j++) { var cols = mesh.GetVertexColors(j); outMesh.Colors[j][cursor] = cols[inCursor]; } } } ConvertMaterialForMesh(outMesh, model, mesh, index); if (processWeights) { ConvertWeights(outMesh, model, mesh, nodeGlobalTransform, index, reverseMappigng); } return Meshes.Count - 1; }
private void SetTextureProperties(aiMaterial outMat, Dictionary<string, LayeredTexture> layeredTextures, MeshGeometry mesh) { TrySetTextureProperties(outMat, layeredTextures, "DiffuseColor", aiTextureType.Diffuse, mesh); TrySetTextureProperties(outMat, layeredTextures, "AmbientColor", aiTextureType.Ambient, mesh); TrySetTextureProperties(outMat, layeredTextures, "EmissiveColor", aiTextureType.Emissive, mesh); TrySetTextureProperties(outMat, layeredTextures, "SpecularColor", aiTextureType.Specular, mesh); TrySetTextureProperties(outMat, layeredTextures, "TransparentColor", aiTextureType.Opacity, mesh); TrySetTextureProperties(outMat, layeredTextures, "ReflectionColor", aiTextureType.Reflection, mesh); TrySetTextureProperties(outMat, layeredTextures, "DisplacementColor", aiTextureType.Displacement, mesh); TrySetTextureProperties(outMat, layeredTextures, "NormalMap", aiTextureType.Normals, mesh); TrySetTextureProperties(outMat, layeredTextures, "Bump", aiTextureType.Height, mesh); TrySetTextureProperties(outMat, layeredTextures, "ShininessExponent", aiTextureType.Shininess, mesh); }
public MeshFile(MeshGeometry geometry) { Geometry = geometry; Type = geometry.GetMeshType(); Cullings = new List <MeshCulling>(); }
public virtual void ReadPolygon( MeshGeometry geometry, bool doubleSided, XmlNode node ) { string[] indices = node.InnerText.Split( (char[]) null, StringSplitOptions.RemoveEmptyEntries ); int inputCount = geometry.InputCount; // How many vertices are in this polygon int vertexCount = indices.Length / inputCount; // Indices (into currentPoint) of the points in a polygon. // This is temporary, and is reset for each polygon List<int> cwPolyPoints = geometry.BeginPolygon(); List<int> ccwPolyPoints = geometry.BeginPolygon(); for( int vertex = 0; vertex < vertexCount; ++vertex ) { PointComponents currentPoint = geometry.BeginPoint(); foreach( int inputIndex in geometry.InputSources.Keys ) { List<InputSourceCollection> inputs = geometry.InputSources[ inputIndex ]; int ptIndex = int.Parse( indices[ vertex * inputCount + inputIndex ] ); foreach( InputSourceCollection isc in inputs ) { foreach( InputSource source in isc.GetSources() ) geometry.AddPointComponent( currentPoint, ptIndex ); // Set the vertex index of this point. This is used by // combiners, which reference vertices by their position // in the vertex array. if( isc is VertexInputSource ) currentPoint.VertexIndex = ptIndex; } } geometry.EndPoint( currentPoint, cwPolyPoints, ccwPolyPoints ); } geometry.EndPolygon( cwPolyPoints ); if( doubleSided ) { ccwPolyPoints.Reverse(); geometry.EndPolygon( ccwPolyPoints ); } }
private int[] ConvertMesh(MeshGeometry mesh, Model model, Matrix nodeGlobalTransform) { List<int> temp; if (MeshesConverted.TryGetValue(mesh, out temp)) { return temp.ToArray(); } else { temp = new List<int>(); } var vertices = mesh.Vertices; var faces = mesh.FaceIndexCounts; if (vertices.Count == 0 || faces.Count == 0) { Debug.WriteLine("ignore empty geometry: " + mesh.Name); return temp.ToArray(); } var mindices = mesh.MaterialIndices; if (Doc.Settings.ReadMaterials && !(mindices.Count == 0)) { var b = mindices[0]; foreach (var index in mindices) { if (index != b) { return ConvertMeshMultiMaterial(mesh, model, nodeGlobalTransform).ToArray(); } } } temp.Add(ConvertMeshSingleMaterial(mesh, model, nodeGlobalTransform)); return temp.ToArray(); }
/// <summary> /// ReadPolygons basically corresponds to reading in a SubMesh. /// The grandparent of this node is probably the geometry node /// with the submesh name. /// </summary> /// <param name="node">The node corresponding to the 'polygons' element</param> public void ReadPolygons( MeshGeometry geometry, Dictionary<string, VertexSet> vertexSets, XmlNode node, ColladaMeshInfo meshInfo ) { bool doubleSided = false; Dictionary<int, List<InputSourceCollection>> inputSources = new Dictionary<int, List<InputSourceCollection>>(); // First pass to get params and inputs foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "param": if( childNode.Attributes[ "name" ].Value == "DOUBLE_SIDED" ) doubleSided = bool.Parse( childNode.InnerText ); break; case "input": ReadInput( inputSources, vertexSets, childNode, meshInfo ); break; case "p": // ignore on this pass break; default: DebugMessage( childNode ); break; } } foreach( int inputIndex in inputSources.Keys ) geometry.AddInputs( inputIndex, inputSources[ inputIndex ] ); // TODO: If we are double sided, we probably need to build a // negated version of the normals. // second pass to handle the 'p' entries foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "param": case "input": // ignore on this pass break; case "p": ReadPolygon( geometry, doubleSided, childNode ); break; default: DebugMessage( childNode ); break; } } string materialId = null; string submeshName = geometry.Id; if( node.Attributes[ "material" ] != null && node.Attributes[ "material" ].Value != null ) { materialId = node.Attributes[ "material" ].Value; // strip off the leading '#' if( materialId.StartsWith( "#" ) ) { log.InfoFormat( "Material {0} starts with '#'", materialId ); materialId = materialId.Substring( 1 ); } // I used to append the material name to the submesh name, // but now I want to leave it alone. //submeshName = submeshName + "/" + materialId; } SubMeshInfo smInfo = new SubMeshInfo(); smInfo.name = submeshName; if( materialId != null ) { if( MaterialScriptBuilder.MaterialNamespace != null ) smInfo.material = MaterialScriptBuilder.MaterialNamespace + "." + materialId; else smInfo.material = materialId; } else { smInfo.material = "BaseWhite"; } geometry.AddSubMesh( smInfo ); }
private void ConvertMaterialForMesh(aiMesh result, Model model, MeshGeometry geo, int materialIndex) { // locate source materials for this mesh var mats = model.Materials; if (materialIndex >= mats.Count || materialIndex < 0) { FBXImporter.LogError("material index out of bounds, setting default material"); result.MaterialIndex = GetDefaultMaterial(); return; } var mat = mats[materialIndex]; int it; if (MaterialsConverted.TryGetValue(mat, out it)) { result.MaterialIndex = it; return; } result.MaterialIndex = ConvertMaterial(mat, geo); this.MaterialsConverted[mat] = result.MaterialIndex; }
public virtual void ReadMesh( string geometryName, XmlNode node, ColladaMeshInfo meshInfo ) { Dictionary<int, List<InputSourceCollection>> inputSources = new Dictionary<int, List<InputSourceCollection>>(); Dictionary<string, VertexSet> vertexSets = new Dictionary<string, VertexSet>(); foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "source": ReadSource( null, childNode, meshInfo ); break; case "vertices": // Read in inputs and vertex sets that should apply to all // the sub-portions of this geometry. ReadVertices( vertexSets, childNode, meshInfo ); break; case "lines": case "linestrips": case "triangles": case "trifans": case "tristrips": case "polygons": // Handle this in the second pass break; default: DebugMessage( childNode ); break; } } int submeshIndex = 0; foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "source": case "vertices": // these were handled in the first pass break; case "polygons": case "triangles": { string name = string.Format( "{0}.{1}", geometryName, submeshIndex++ ); if( !meshInfo.Geometries.ContainsKey( geometryName ) ) meshInfo.Geometries[ geometryName ] = new GeometrySet( geometryName ); GeometrySet geoSet = meshInfo.Geometries[ geometryName ]; MeshGeometry geometry = new MeshGeometry( name, geoSet ); foreach( VertexSet vertexSet in vertexSets.Values ) geometry.AddVertexSet( vertexSet ); foreach( int inputIndex in inputSources.Keys ) geometry.AddInputs( inputIndex, inputSources[ inputIndex ] ); geoSet.Add( geometry ); ReadPolygons( geometry, vertexSets, childNode, meshInfo ); break; } case "lines": case "linestrips": case "trifans": case "tristrips": default: DebugMessage( childNode ); break; } } }
public BasicModel(Device device, TextureManager texMgr, string filename, string texturePath) { _subsets = new List<MeshGeometry.Subset>(); _vertices = new List<PosNormalTexTan>(); _indices = new List<short>(); DiffuseMapSRV = new List<ShaderResourceView>(); NormalMapSRV = new List<ShaderResourceView>(); Materials = new List<Material>(); _modelMesh = new MeshGeometry(); var importer = new AssimpImporter(); if (!importer.IsImportFormatSupported(Path.GetExtension(filename))) { throw new ArgumentException("Model format " + Path.GetExtension(filename) + " is not supported! Cannot load {1}", "filename"); } #if DEBUG importer.AttachLogStream(new ConsoleLogStream()); importer.VerboseLoggingEnabled = true; #endif var model = importer.ImportFile(filename, PostProcessSteps.GenerateSmoothNormals | PostProcessSteps.CalculateTangentSpace); var min = new Vector3(float.MaxValue); var max = new Vector3(float.MinValue); var verts = new List<PosNormalTexTan>(); foreach (var mesh in model.Meshes) { var subset = new MeshGeometry.Subset { VertexCount = mesh.VertexCount, VertexStart = _vertices.Count, FaceStart = _indices.Count / 3, FaceCount = mesh.FaceCount }; _subsets.Add(subset); // bounding box corners for (var i = 0; i < mesh.VertexCount; i++) { var pos = mesh.HasVertices ? mesh.Vertices[i].ToVector3() : new Vector3(); min = Vector3.Minimize(min, pos); max = Vector3.Maximize(max, pos); var norm = mesh.HasNormals ? mesh.Normals[i] : new Vector3D(); var texC = mesh.HasTextureCoords(0) ? mesh.GetTextureCoords(0)[i] : new Vector3D(); var tan = mesh.HasTangentBasis ? mesh.Tangents[i] : new Vector3D(); var v = new PosNormalTexTan(pos, norm.ToVector3(), texC.ToVector2(), tan.ToVector3()); verts.Add(v); } _vertices.AddRange(verts); var indices = mesh.GetIndices().Select(i => (short)(i + (uint)subset.VertexStart)).ToList(); _indices.AddRange(indices); var mat = model.Materials[mesh.MaterialIndex]; var material = mat.ToMaterial(); Materials.Add(material); var diffusePath = mat.GetTexture(TextureType.Diffuse, 0).FilePath; if (Path.GetExtension(diffusePath) == ".tga") { // DirectX doesn't like to load tgas, so you will need to convert them to pngs yourself with an image editor diffusePath = diffusePath.Replace(".tga", ".png"); } if (!string.IsNullOrEmpty(diffusePath)) { DiffuseMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, diffusePath))); } var normalPath = mat.GetTexture(TextureType.Normals, 0).FilePath; if (!string.IsNullOrEmpty(normalPath)) { NormalMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, normalPath))); } else { var normalExt = Path.GetExtension(diffusePath); normalPath = Path.GetFileNameWithoutExtension(diffusePath) + "_nmap" + normalExt; NormalMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, normalPath))); } } BoundingBox = new BoundingBox(min, max); _modelMesh.SetSubsetTable(_subsets); _modelMesh.SetVertices(device, _vertices); _modelMesh.SetIndices(device, _indices); }
private BasicModel() { _subsets = new List<MeshGeometry.Subset>(); _vertices = new List<PosNormalTexTan>(); _indices = new List<short>(); DiffuseMapSRV = new List<ShaderResourceView>(); NormalMapSRV = new List<ShaderResourceView>(); Materials = new List<Material>(); _modelMesh = new MeshGeometry(); }
private aiMesh SetupEmptyMesh(MeshGeometry mesh) { var outMesh = new aiMesh(); this.Meshes.Add(outMesh); if (MeshesConverted.ContainsKey(mesh)) { this.MeshesConverted[mesh].Add(this.Meshes.Count - 1); } else { this.MeshesConverted[mesh] = new List<int>() {this.Meshes.Count - 1 }; } // set name var name = mesh.Name; if (name.StartsWith("Geometry::")) { name = name.Substring(10); } if (!string.IsNullOrEmpty(name)) { outMesh.Name = name; } return outMesh; }
private void CanCompute_FaceNormal() { var normal = MeshGeometry.FaceNormal(this.FlatTriangle.Faces[0]); Assert.Equal(Vector3d.UnitZ, normal); }
public SkinnedModel(Device device, TextureManager texMgr, string filename, string texturePath, bool flipTexY = false) { // initialize collections _subsets = new List<MeshGeometry.Subset>(); _vertices = new List<PosNormalTexTanSkinned>(); _indices = new List<short>(); DiffuseMapSRV = new List<ShaderResourceView>(); NormalMapSRV = new List<ShaderResourceView>(); Materials = new List<Material>(); var importer = new AssimpImporter(); #if DEBUG importer.AttachLogStream(new ConsoleLogStream()); importer.VerboseLoggingEnabled = true; #endif var model = importer.ImportFile(filename, PostProcessSteps.GenerateSmoothNormals | PostProcessSteps.CalculateTangentSpace ); // Load animation data Animator = new SceneAnimator(); Animator.Init(model); // create our vertex-to-boneweights lookup var vertToBoneWeight = new Dictionary<uint, List<VertexWeight>>(); // create bounding box extents _min = new Vector3(float.MaxValue); _max = new Vector3(float.MinValue); foreach (var mesh in model.Meshes) { ExtractBoneWeightsFromMesh(mesh, vertToBoneWeight); var subset = new MeshGeometry.Subset { VertexCount = mesh.VertexCount, VertexStart = _vertices.Count, FaceStart = _indices.Count / 3, FaceCount = mesh.FaceCount }; _subsets.Add(subset); var verts = ExtractVertices(mesh, vertToBoneWeight, flipTexY); _vertices.AddRange(verts); // extract indices and shift them to the proper offset into the combined vertex buffer var indices = mesh.GetIndices().Select(i => (short)(i + (uint)subset.VertexStart)).ToList(); _indices.AddRange(indices); // extract materials var mat = model.Materials[mesh.MaterialIndex]; var material = mat.ToMaterial(); Materials.Add(material); // extract material textures var diffusePath = mat.GetTexture(TextureType.Diffuse, 0).FilePath; if (!string.IsNullOrEmpty(diffusePath)) { DiffuseMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, diffusePath))); } var normalPath = mat.GetTexture(TextureType.Normals, 0).FilePath; if (!string.IsNullOrEmpty(normalPath)) { NormalMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, normalPath))); } else { // for models created without a normal map baked, we'll check for a texture with the same // filename as the diffure texture, and _nmap suffixed // this lets us add our own normal maps easily var normalExt = Path.GetExtension(diffusePath); normalPath = Path.GetFileNameWithoutExtension(diffusePath) + "_nmap" + normalExt; if (File.Exists(Path.Combine(texturePath, normalPath))) { NormalMapSRV.Add(texMgr.CreateTexture(Path.Combine(texturePath, normalPath))); } } } BoundingBox = new BoundingBox(_min, _max); _modelMesh = new MeshGeometry(); _modelMesh.SetSubsetTable(_subsets); _modelMesh.SetVertices(device, _vertices); _modelMesh.SetIndices(device, _indices); }
/// <summary> /// Take the data from input, and use it to build a two dimensional /// array of data which will be added to the geometry's /// VertexDataElements. /// </summary> /// <param name="geometry">the mesh geometry that owns the data</param> /// <param name="input">the input source with the information to populate the vertex data</param> /// <param name="accessIndex">the index where our data is in the source</param> /// <param name="textureIndex">the texture index when appropriate or 0</param> /// <param name="vertexCount">the number of vertices</param> protected void ProcessInput( MeshGeometry geometry, InputSource input, int accessIndex, int textureIndex, int vertexCount ) { VertexDataEntry vde = null; switch( input.Semantic ) { case "POSITION": case "BIND_SHAPE_POSITION": vde = HWBuffer.ExtractData( VertexElementSemantic.Position, vertexCount, input, geometry.IndexSets, accessIndex ); break; case "NORMAL": case "BIND_SHAPE_NORMAL": vde = HWBuffer.ExtractData( VertexElementSemantic.Normal, vertexCount, input, geometry.IndexSets, accessIndex ); break; case "COLOR": vde = HWBuffer.ExtractData( VertexElementSemantic.Diffuse, vertexCount, input, geometry.IndexSets, accessIndex ); break; case "UV": case "TEXCOORD": vde = HWBuffer.ExtractData( VertexElementSemantic.TexCoords, vertexCount, input, geometry.IndexSets, accessIndex ); break; case "TANGENT": case "TEXTANGENT": vde = HWBuffer.ExtractData( VertexElementSemantic.Tangent, vertexCount, input, geometry.IndexSets, accessIndex ); break; case "BINORMAL": case "TEXBINORMAL": vde = HWBuffer.ExtractData( VertexElementSemantic.Binormal, vertexCount, input, geometry.IndexSets, accessIndex ); break; default: m_Log.WarnFormat( "Not yet handling input semantic: {0}", input.Semantic ); break; } if( vde != null ) { vde.textureIndex = textureIndex; geometry.VertexDataEntries.Add( vde ); } }
public static MeshFile ReadMesh(Stream stream) { try { var meshFile = ReadMeshFile(stream); var meshType = (MeshType)meshFile.Header.MeshType; bool isTextured = meshType == MeshType.StandardTextured || meshType == MeshType.FlexibleTextured; bool isFlexible = meshType == MeshType.Flexible || meshType == MeshType.FlexibleTextured; var mainMesh = MeshGeometry.Create(meshFile.Geometry); SetShaderData(meshFile, meshFile.Geometry, mainMesh); var mesh = new MeshFile(mainMesh); if (stream is FileStream fs) { mesh.Filename = fs.Name; } mesh.SetGeometry(mainMesh); for (int i = 0; i < meshFile.Cullings.Length; i++) { var data = meshFile.Cullings[i]; var culling = new MeshCulling((MeshCullingType)data.Type) { FromIndex = data.FromIndex, IndexCount = data.IndexCount, FromVertex = data.FromVertex, VertexCount = data.VertexCount, }; if (data.Studs != null && data.Studs.Length > 0) { for (int j = 0; j < data.Studs.Length; j++) { culling.Studs.Add(new Custom2DFieldReference(data.Studs[j])); } } if (data.AdjacentStuds != null && data.AdjacentStuds.Length > 0) { for (int j = 0; j < data.AdjacentStuds.Length; j++) { culling.AdjacentStuds.Add(new Custom2DFieldReference(data.AdjacentStuds[j])); } } if (data.AlternateMesh.HasValue) { var geom = MeshGeometry.Create(data.AlternateMesh.Value); SetShaderData(meshFile, data.AlternateMesh.Value, geom); culling.ReplacementMesh = geom; } mesh.Cullings.Add(culling); } return(mesh); } catch { throw; } }
protected override void SolveInstance(IGH_DataAccess DA) { // --- variables --- MeshGeometry mesh = new MeshGeometry(); List <string> bctxt = new List <string>(); List <string> loadtxt = new List <string>(); List <string> deftxt = new List <string>(); Material material = new Material(); Boolean opt = false; // --- input --- if (!DA.GetData(0, ref mesh)) { return; } if (!DA.GetDataList(1, bctxt)) { return; } if (!DA.GetDataList(2, loadtxt)) { return; } if (!DA.GetDataList(3, deftxt)) { return; } if (!DA.GetData(4, ref material)) { return; } // --- setup --- List <List <int> > connectivity = mesh.GetConnectivity(); List <Point3d> globalPoints = mesh.GetGlobalPoints(); List <Node> nodes = mesh.GetNodeList(); BrepGeometry brp = mesh.GetBrep(); Brep origBrep = brp.GetBrep(); int sizeOfMatrix = mesh.GetSizeOfMatrix(); int removableElements = FindRemovableElements(nodes, mesh.GetElements()); int totalElements = mesh.GetElements().Count; int numberElements = mesh.GetElements().Count; double removableVolume = mesh.GetOptVolume(); double minElements = totalElements - Math.Floor(totalElements * removableVolume / 100); // --- solve --- if (removableVolume != 0) { opt = true; } Boolean first = true; double max = 0; int removeElem = -1; List <int> removeNodeNr = new List <int>(); DataTree <double> defTree = new DataTree <double>(); while (numberElements > minElements && max < material.GetY() || first) //Requirements for removal { first = false; for (int i = 0; i < nodes.Count; i++) { nodes[i].CleanStress(); } List <Element> elements = mesh.GetElements(); //Remove selected element from last iterations, and update afftected nodes if (removeElem != -1 && opt == true) { RemoveElementAndUpdateNodes(elements, removeElem, removeNodeNr); } //Create Ktot and B Matrix <double> Ktot = CreateGlobalStiffnessMatrix(sizeOfMatrix, material, elements); //Create boundary condition list AND predeformations (List <int> bcNodes, List <double> reatrains) = CreateBCList(bctxt, globalPoints); (List <int> predefNodes, List <double> predef) = CreateBCList(deftxt, globalPoints); //Setter 0 i hver rad med bc og predef, og diagonal til 1. Ktot = ApplyBCrow(Ktot, bcNodes); Ktot = ApplyBCrow(Ktot, predefNodes); //Needs to take the predefs into account Vector <double> Rdef = Vector <double> .Build.Dense(sizeOfMatrix); if (deftxt.Any()) { Rdef = ApplyPreDef(Ktot, predefNodes, predef, sizeOfMatrix); } //double[] R_array = SetLoads(sizeOfM, loadtxt); double[] Rload = AssignLoadsDefAndBC(loadtxt, predefNodes, predef, bcNodes, globalPoints); //Adding R-matrix for pre-deformations. var V = Vector <double> .Build; Vector <double> R = (V.DenseOfArray(Rload)).Subtract(Rdef); //Apply boundary condition and predeformations (Puts 0 in columns of K) Ktot = ApplyBCcol(Ktot, bcNodes); Ktot = ApplyBCcol(Ktot, predefNodes); //Removing row and column in K and R, and nodes with removeNodeNr if (opt == true) { List <Node> nodes_removed = mesh.GetNodeList().ConvertAll(x => x); (Ktot, R, nodes) = UpdateKandR(removeNodeNr, Ktot, R, nodes_removed); } //Inverting K matrix. Singular when all elements belonging to a node is removed Matrix <double> KtotInverse = Ktot.Inverse(); //Caluculation of the displacement vector u Vector <double> u = KtotInverse.Multiply(R); //Creating tree for output of deformation. Structured in x,y,z for each node. As well as asigning deformation to each node class defTree = DefToTree(u, nodes); //Calculatin strains for each node in elements CalcStrainAndStress(elements, material); //Calculate global stresses from strain CalcStrainAndStressGlobal(nodes, material); SetAverageStresses(elements); //Find element to be removed next if (opt == true) { (max, removeElem) = mesh.RemoveOneElement(); numberElements = mesh.GetElements().Count; } } DataTree <double> strainTree = new DataTree <double>(); DataTree <double> stressTree = new DataTree <double>(); for (int i = 0; i < nodes.Count; i++) { strainTree.AddRange(nodes[i].GetGlobalStrain(), new GH_Path(new int[] { 0, i })); stressTree.AddRange(nodes[i].GetGlobalStress(), new GH_Path(new int[] { 0, i })); } //FOR PREVIEW OF HEADLINE //Setting up reference values (double refLength, Point3d centroid) = GetRefValues(origBrep); //Creating text-information for showing in VR (string headText, double headSize, Plane headPlane, Color headColor) = CreateHeadline(centroid, refLength); //---output--- DA.SetDataTree(0, defTree); DA.SetDataTree(1, strainTree); DA.SetDataTree(2, stressTree); DA.SetData(3, headText); DA.SetData(4, headSize); DA.SetData(5, headPlane); DA.SetData(6, headColor); }
public override void ReadMesh( string geometryName, XmlNode node, ColladaMeshInfo meshInfo ) { Dictionary<int, List<InputSourceCollection>> inputSources = new Dictionary<int, List<InputSourceCollection>>(); Dictionary<string, VertexSet> vertexSets = new Dictionary<string, VertexSet>(); int submeshIndex = 0; foreach( XmlNode childNode in node.ChildNodes ) { switch( childNode.Name ) { case "source": ReadSource( null, childNode, meshInfo ); break; case "vertices": // Read in inputs and vertex sets that should apply to all // the sub-portions of this geometry. ReadVertices( vertexSets, childNode, meshInfo ); break; case "polygons": case "polylist": case "triangles": { string name = string.Format( "{0}.{1}", geometryName, submeshIndex++ ); if( !meshInfo.Geometries.ContainsKey( geometryName ) ) meshInfo.Geometries[ geometryName ] = new GeometrySet( geometryName ); GeometrySet geoSet = meshInfo.Geometries[ geometryName ]; MeshGeometry geometry = new MeshGeometry( name, geoSet ); foreach( VertexSet vertexSet in vertexSets.Values ) geometry.AddVertexSet( vertexSet ); geoSet.Add( geometry ); if( childNode.Name == "triangles" ) ReadTriangles( geometry, vertexSets, childNode, meshInfo ); else if( childNode.Name == "polygons" ) ReadPolygons( geometry, vertexSets, childNode, meshInfo ); else if( childNode.Name == "polylist" ) log.Error( "TODO: Add support for polylist" ); break; } case "lines": case "linestrips": case "trifans": case "tristrips": default: DebugMessage( childNode ); break; } } }
private void ConvertWeights(aiMesh result, Model model, MeshGeometry geo, Matrix nodeGlobalTransform, int materialIndex = FbxConverter.NO_MATERIAL_SEPARATION, int[] outputVertStartIndices = null) { Debug.Assert(geo.DeformerSkin != null); var outIndices = new List<int>(); var indexOutIndices = new List<int>(); var countOutIndices = new List<int>(); var sk = geo.DeformerSkin; var bones = new List<aiBone>(sk.Clusters.Count); var noMatCheck = (materialIndex == FbxConverter.NO_MATERIAL_SEPARATION); Debug.Assert(noMatCheck || outputVertStartIndices != null); try { foreach (var cluster in sk.Clusters) { Debug.Assert(cluster != null); var indices = cluster.Indices; if (indices.Count == 0) { continue; } var mats = geo.MaterialIndices; var ok = false; int noIndexSentine = int.MaxValue; countOutIndices.Clear(); indexOutIndices.Clear(); outIndices.Clear(); foreach (var index in indices) { var outIdx = geo.ToOutputVertexIndex((uint)index); var count = outIdx.Count; // ToOutputVertexIndex only returns NULL if index is out of bounds // which should never happen Debug.Assert(outIdx.Count > 0); indexOutIndices.Add(noIndexSentine); countOutIndices.Add(0); for (int i = 0; i < count; i++) { if (noMatCheck || mats[(int)geo.FaceForVertexIndex((uint)outIdx.Array[i+outIdx.Offset])] == materialIndex) { if (indexOutIndices[indexOutIndices.Count] == noIndexSentine) { indexOutIndices[indexOutIndices.Count] = outIndices.Count; } if (noMatCheck) { outIndices.Add((int)outIdx.Array[i+outIdx.Offset]); } else { int it; for (it = 0; it < outputVertStartIndices.Length; it++) { if (outIdx.Array[i+outIdx.Offset] == outputVertStartIndices[it]) { break; } } outIndices.Add(it); } countOutIndices[countOutIndices.Count] += 1; ok = true; } } } // if we found at least one, generate the output bones // XXX this could be heavily simplified by collecting the bone // data in a single step. if (ok) { ConvertCluster(bones, model, cluster, outIndices.ToArray(), indexOutIndices.ToArray(), countOutIndices.ToArray(), nodeGlobalTransform); } } } catch (Exception e) { bones.Clear(); throw (e); } if (bones.Count == 0) { return; } result.Bones = bones.ToArray(); result.NumBones = bones.Count; }