void openOBJFileButton_Click(object sender, EventArgs e) { OpenFileDialog open = new OpenFileDialog(); open.Filter = "OBJ Files (*.obj)|*.obj|" + "Nif Files (*.nif)|*.nif|" + "All files (*.*)|*.*"; if (open.ShowDialog() == DialogResult.OK) { try { if (open.FileName.ToLower().EndsWith(".obj")) { FileStream stream = new FileStream(open.FileName, FileMode.Open); OBJFile objFile = new OBJFile(stream); this.reference = objFile.Mesh; stream.Close(); this.menu.referenceTextBox.Text = open.FileName; return; } if (open.FileName.ToLower().EndsWith(".nif")) { FileStream stream = new FileStream(open.FileName, FileMode.Open); NifFile nifFile = new NifFile(stream); this.reference = nifFile.MeshData[0]; stream.Close(); this.menu.referenceTextBox.Text = open.FileName; return; } } catch (Exception) { } } }
public OBJFile() { this.vertices = new List <VertexPosition>(); this.triangleFaces = new List <TriangleFace>(); this.quadFaces = new List <QuadFace>(); this.mesh = new MeshBase(); }
//private void GenerateHeightMapObject(float[,] heightData, Color4[] positionColorsArray) private void GenerateHeightMapSceneNodes(MeshBase heightMapMesh, Ab3d.DirectX.Material dxMaterial) { var meshObjectNode = new Ab3d.DirectX.MeshObjectNode(heightMapMesh, dxMaterial); meshObjectNode.Name = "HeightMeshObjectNode"; _disposables.Add(meshObjectNode); var sceneNodeVisual3D = new SceneNodeVisual3D(meshObjectNode); RootContentVisual3D.Children.Add(sceneNodeVisual3D); // If you also want to render back faces of the height map you need to create another MeshObjectNode and set its IsBackFaceMaterial to true. // You can reuse the mesh. But this still requires almost twice the GPU power. var backDiffuseMaterial = new DiffuseMaterial(Brushes.Gray); var backDXMaterial = new Ab3d.DirectX.Materials.WpfMaterial(backDiffuseMaterial); meshObjectNode = new Ab3d.DirectX.MeshObjectNode(heightMapMesh, backDXMaterial); meshObjectNode.IsBackFaceMaterial = true; meshObjectNode.Name = "HeightBackMeshObjectNode"; _disposables.Add(meshObjectNode); sceneNodeVisual3D = new SceneNodeVisual3D(meshObjectNode); RootContentVisual3D.Children.Add(sceneNodeVisual3D); }
public MeshBase CreateMesh() { MeshBase geometry = this.Factory.CreateMesh(this); this.Max = geometry.Max; this.Min = geometry.Min; return(geometry); }
public OBJFile(FileStream stream) { this.vertices = new List <VertexPosition>(); this.triangleFaces = new List <TriangleFace>(); this.quadFaces = new List <QuadFace>(); StreamReader reader = new StreamReader(stream); string text = reader.ReadToEnd(); text = text.Replace("\r", ""); text = text.Replace('.', ','); string[] lines = text.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (string line in lines) { string[] words = line.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); //if (words[0] == "v") //{ // float x = float.Parse(words[1]); // float y = float.Parse(words[2]); // float z = float.Parse(words[3]); // VertexPosition coord = new VertexPosition(x, y, z); // this.vertices.Add(coord); //} switch (words[0]) { case "v": float x = float.Parse(words[1]); float y = float.Parse(words[2]); float z = float.Parse(words[3]); VertexPosition coord = new VertexPosition(x, y, z); this.vertices.Add(coord); break; case "f": if (words.Length == 5) { int a4 = int.Parse(words[1].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int b4 = int.Parse(words[2].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int c4 = int.Parse(words[3].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int d4 = int.Parse(words[4].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); QuadFace face4 = new QuadFace(a4, b4, c4, d4); this.quadFaces.Add(face4); break; } int a = int.Parse(words[1].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int b = int.Parse(words[2].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); int c = int.Parse(words[3].Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries)[0]); TriangleFace face = new TriangleFace(a, b, c); this.triangleFaces.Add(face); break; } } this.mesh = new MeshBase(); this.mesh.QuadFaces = this.quadFaces; this.mesh.TriangleFaces = this.triangleFaces; this.mesh.Vertices = this.vertices; string[] path = stream.Name.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); this.mesh.Name = HeadFile.ReplaceExtention(path[path.Length - 1], ""); }
//save entire GameObject private void SavePrefabToFile(MeshBase meshBase, string name) { CheckFolders("Saved prefabs"); //mesh and it's material need to be saved too SaveMeshToFile(meshBase.C_MF.sharedMesh, meshBase.C_MR.sharedMaterial, name + "'mesh"); PrefabUtility.CreatePrefab("Assets/PSG/Saved prefabs/" + name + ".prefab", meshBase.gameObject); Debug.Log("Prefab \"" + name + ".prefab\" saved succesfully at PSG/Saved prefabs"); }
void openOBJFileButton_Click(object sender, EventArgs e) { OpenFileDialog open = new OpenFileDialog(); open.Filter = "OBJ Files (*.obj)|*.OBJ|" + "Nif Files Files (*.nif)|*.nif|" + "All files (*.*)|*.*"; if (open.ShowDialog() == DialogResult.OK && this.menu.expressionsListView.SelectedItems.Count > 0) { try { FileStream stream = new FileStream(open.FileName, FileMode.Open); ListViewItem item = this.menu.expressionsListView.SelectedItems[0]; Expression exp = (Expression)Enum.Parse(typeof(Expression), item.Text); if (this.expressions.ContainsKey(exp)) { if (open.FileName.ToLower().EndsWith(".obj")) { OBJFile objFile = new OBJFile(stream); MeshBase mesh = objFile.Mesh; this.expressions[exp] = mesh; } else { NifFile nifFile = new NifFile(stream); MeshBase mesh = nifFile.MeshData[0]; this.expressions[exp] = mesh; } } else { if (open.FileName.ToLower().EndsWith(".obj")) { OBJFile objFile = new OBJFile(stream); MeshBase mesh = objFile.Mesh; this.expressions.Add(exp, mesh); } else { NifFile nifFile = new NifFile(stream); MeshBase mesh = nifFile.MeshData[0]; this.expressions.Add(exp, mesh); } } //this.reference = new OBJFile(stream); item.SubItems[2].Text = open.FileName; stream.Close(); } catch (Exception ex) { } } }
private void BuildSelectedMesh(MeshCreator meshCreator) { MeshBase createdMesh = BuildMesh(meshCreator); if (createdMesh != null) { if (meshCreator.setRandomColor) { createdMesh.SetRandomColor(); } createdMesh.SetPhysicsMaterialProperties(meshCreator.bounciness, meshCreator.friction); Undo.RegisterCreatedObjectUndo(createdMesh, "creating " + createdMesh.name); } }
void Start() { //add some shapes to playground AddQuadrangle(new Vector3(4, 0, 0)); AddCircle(new Vector3(-4, 0, 0)); AddTriangle(new Vector3(0, 3, 0)); AddCake(new Vector3(0, -3, 0)); AddRing(new Vector3(-4, -3, 0)); AddPointedCircle(new Vector3(-4, 3, 0)); AddRectangle(new Vector3(4, 3, 0)); AddEllipse(new Vector3(4, -3, 0)); AddStar(new Vector3(1, 1)); AddGear(new Vector3(-1, 1)); AddConvex(Vector3.zero); MeshBase.Join(GameObject.Find("Convex Mesh").GetComponent <MeshBase>(), GameObject.Find("Circle").GetComponent <MeshBase>()); GameObject.Find("Convex Mesh").GetComponent <MeshBase>().JoinTo(GameObject.Find("Triangle").GetComponent <MeshBase>()); }
//save entire GameObject private void SavePrefabToFile(MeshBase meshBase, string name) { CheckFolders("Saved prefabs"); //mesh and it's material need to be saved too SaveMeshToFile(meshBase.C_MF.sharedMesh, name + "'mesh"); try { PrefabUtility.CreatePrefab("Assets/PSG/Saved prefabs/" + name + ".prefab", meshBase.gameObject); Debug.Log("Prefab \"" + name + ".prefab\" saved succesfully at PSG/Saved prefabs"); } catch (Exception e) { Debug.LogError("Saving prefab error! " + e); } }
//standard override public override void OnInspectorGUI() { DrawDefaultInspector(); MeshBase targetScript = (MeshBase)target; //save MeshFilter's content if (GUILayout.Button("Save Mesh Only")) { SaveMeshToFile(targetScript.C_MF.sharedMesh, targetScript.C_MR.sharedMaterial, targetScript.name); } //save GameObject if (GUILayout.Button("Save Prefab")) { SavePrefabToFile(targetScript, targetScript.name); } }
// This method uses low level DXEngine objects to create tube paths. private void AddSpirals_MeshObjectNode(int xCount, int yCount, int spiralLength, bool useMultiThreading) { float circleRadius = 10; int spiralCircles = spiralLength / 20; // One circle in the spiral is created from 20 lines var dxMaterial = new Ab3d.DirectX.Materials.StandardMaterial() { DiffuseColor = Color3.Black, EmissiveColor = Color3.White, Effect = _solidColorEffect }; _disposables.Add(dxMaterial); float xStart = -xCount * circleRadius * 1.5f; float yStart = -yCount * circleRadius * 1.5f; if (useMultiThreading) { // On i7 6700 with 4 cores with hyper-threading the multi-threaded code path is almost 100% faster then single threaded solution. var initializedMeshes = new MeshBase[xCount, yCount]; var dxDevice = MainDXViewportView.DXScene.DXDevice; Parallel.For(0, xCount * yCount, xy => { int x = (int)xy / yCount; int y = (int)xy % yCount; var spiralPositions = CreateSpiralPositions(startPosition: new Vector3(x * circleRadius * 3 + xStart, y * circleRadius * 3 + yStart, 0), circleXDirection: new Vector3(1, 0, 0), circleYDirection: new Vector3(0, 1, 0), oneSpiralCircleDirection: new Vector3(0, 0, -10), circleRadius: circleRadius, segmentsPerCircle: 20, circles: spiralCircles); MeshBase tubePathMesh = CreateTubePathMesh(spiralPositions, radius: 1.0f, segmentsCount: 8, isTubeClosed: true, tubeColor: Color4.White); // Create DirectX resources in the background thread (this creates buffers on the GPU and send data there from the main memory) tubePathMesh.InitializeResources(dxDevice); // Save the mesh initializedMeshes[x, y] = tubePathMesh; }); // Now most of the work was done in multi-threaded way. // So we only need to create the MeshObjectNode and add that to the Scene. This needs to be done on the UI thread. MainViewport.BeginInit(); MainViewport.Children.Clear(); for (int x = 0; x < xCount; x++) { for (int y = 0; y < yCount; y++) { var tubePathMesh = initializedMeshes[x, y]; var meshObjectNode = new Ab3d.DirectX.MeshObjectNode(tubePathMesh, dxMaterial); var tubePathVisual3D = new SceneNodeVisual3D(meshObjectNode); // IMPORTANT: // // In this performance demo we create new spiral positions and new tubePathMesh for each spiral. // But because the spirals are the same, we could create only one spiral positions and one tubePathMesh // and then use that tubePathMesh to create multiple MeshObjectNode and SceneNodeVisual3D objects // each of them with its Transform property set - as shown in the line below. // // Sharing one mesh would provide much better performance and lower memory usage, // but for this demo we want to simulate cration of huge tube paths in the background thread. // //tubePathVisual3D.Transform = new TranslateTransform3D(x * circleRadius * 3 + xStart, y * circleRadius * 3 + yStart, 0); _disposables.Add(tubePathMesh); // We did not add that in the background thread (we would need locking for that) so we need to do that now _disposables.Add(meshObjectNode); MainViewport.Children.Add(tubePathVisual3D); } } MainViewport.EndInit(); } else { // No multi-threading MainViewport.BeginInit(); MainViewport.Children.Clear(); for (int x = 0; x < xCount; x++) { for (int y = 0; y < yCount; y++) { var spiralPositions2 = CreateSpiralPositions(startPosition: new Point3D(x * circleRadius * 3 + xStart, y * circleRadius * 3 + yStart, 0), circleXDirection: new Vector3D(1, 0, 0), circleYDirection: new Vector3D(0, 1, 0), oneSpiralCircleDirection: new Vector3D(0, 0, -10), circleRadius: circleRadius, segmentsPerCircle: 20, circles: spiralCircles); var spiralPositions = spiralPositions2.Select(p => p.ToVector3()).ToArray(); //var spiralPositions = CreateSpiralPositions(startPosition: new Vector3(x * circleRadius * 3 + xStart, y * circleRadius * 3 + yStart, 0), // circleXDirection: new Vector3(1, 0, 0), // circleYDirection: new Vector3(0, 1, 0), // oneSpiralCircleDirection: new Vector3(0, 0, -10), // circleRadius: circleRadius, // segmentsPerCircle: 20, // circles: spiralCircles); var tubePathMesh = CreateTubePathMesh(spiralPositions, radius: 2, segmentsCount: 8, isTubeClosed: true, tubeColor: Color4.White); var meshObjectNode = new Ab3d.DirectX.MeshObjectNode(tubePathMesh, dxMaterial); var tubePathVisual3D = new SceneNodeVisual3D(meshObjectNode); //tubePathVisual3D.Transform = new TranslateTransform3D(x * circleRadius * 3 + xStart, y * circleRadius * 3 + yStart, 0); _disposables.Add(meshObjectNode); MainViewport.Children.Add(tubePathVisual3D); } } MainViewport.EndInit(); } }
/// <summary> /// 初始化顶点位置和索引 /// </summary> /// <param name="gridCoords"></param> protected void Init(MeshBase geometry) { ////TODO:如果用此方式,则必须先将此对象加入scene树,然后再调用Init //OpenGL gl = this.TraverseToRootElement().ParentScene.OpenGL; SetPositions(geometry.Positions); }
//private int _xCount = 10000; //private int _yCount = 2000; // Performance values for the 10000 x 2000 height map on NVIDIA 1080: // DirectXOverlay: render time 0.25 ms (4000 FPS) // DirectXImage - with back face rendering (bottom of the height map): render time around 14 ms (70 FPS) // - without back face rendering: render time around 7 ms (140 FPS) public OptimizedHeightMapGeneration() { InitializeComponent(); TitleTextBlock.Text += string.Format(" ({0}x{1} height values)", XCount, YCount); // First create very simple height map that can be created immediately. // After that we will wait until DXScene is initialized and then start a background worker // that will generate the mesh in the background. When this is done, we will update the 3D scene. _disposables = new DisposeList(); int xCount = XCount / 100; int yCount = YCount / 100; float[,] simpleHeightData; Color4[] simplePositionColorsArray; //GenerateSimpleHeightData(XCount, YCount, out heightData, out positionColorsArray); //GenerateRandomHeightData(XCount, YCount, out heightData, out positionColorsArray); GenerateSinusHeightData(xCount, yCount, null, out simpleHeightData, out simplePositionColorsArray); var simpleHeightMapMesh = GenerateHeightMapMesh(simpleHeightData, dxDevice: null); _simplePositionColorMaterial = GeneratePositionColorMaterial(simplePositionColorsArray, dxDevice: null); _disposables.Add(simpleHeightMapMesh); _disposables.Add(_simplePositionColorMaterial); GenerateHeightMapSceneNodes(simpleHeightMapMesh, _simplePositionColorMaterial); //GenerateHeightMapObject(heightData, positionColorsArray); MainDXViewportView.DXSceneInitialized += delegate(object sender, EventArgs args) { if (MainDXViewportView.DXScene == null) { return; // WPF 3D rendering } MeshBase heightMapMesh = null; _dxMaterial = null; var dxDevice = MainDXViewportView.DXScene.DXDevice; _backgroundWorker = new BackgroundWorker() { WorkerSupportsCancellation = true, WorkerReportsProgress = true }; _backgroundWorker.DoWork += delegate(object o, DoWorkEventArgs eventArgs) { // 1) // Generate height map data in the background. float[,] heightData; Color4[] positionColorsArray; //GenerateSimpleHeightData(XCount, YCount, out heightData, out positionColorsArray); //GenerateRandomHeightData(XCount, YCount, out heightData, out positionColorsArray); GenerateSinusHeightData(XCount, YCount, _backgroundWorker, out heightData, out positionColorsArray); if (_backgroundWorker.CancellationPending) { return; } // 2) // Generate the mesh object and initialize it with dxDevice // This will generate DirectX resources and send them to GPU heightMapMesh = GenerateHeightMapMesh(heightData, dxDevice); if (_backgroundWorker.CancellationPending) { return; } _backgroundWorker.ReportProgress(95); if (_dxMaterial != null) { _dxMaterial.Dispose(); } // 3) // Generate material with position color data and sent that to GPU _dxMaterial = GeneratePositionColorMaterial(positionColorsArray, dxDevice); _backgroundWorker.ReportProgress(100); }; _backgroundWorker.ProgressChanged += delegate(object o, ProgressChangedEventArgs eventArgs) { GenerationProgressBar.Value = eventArgs.ProgressPercentage; }; _backgroundWorker.RunWorkerCompleted += delegate(object o, RunWorkerCompletedEventArgs eventArgs) { // Clean and dispose existing models RootContentVisual3D.Children.Clear(); _disposables.Dispose(); // Create new DisposeList _disposables = new DisposeList(); _disposables.Add(simpleHeightMapMesh); _disposables.Add(_simplePositionColorMaterial); // Generate SceneNode with new heightMapMesh and dxMaterial. // Note that this is a very fast operation if (heightMapMesh != null && _dxMaterial != null) { GenerateHeightMapSceneNodes(heightMapMesh, _dxMaterial); } _backgroundWorker = null; GenerationProgressBar.Visibility = Visibility.Collapsed; MainDXViewportView.Refresh(); }; GenerationProgressBar.Value = 0; GenerationProgressBar.Visibility = Visibility.Visible; _backgroundWorker.RunWorkerAsync(); }; this.Unloaded += delegate(object sender, RoutedEventArgs args) { if (_backgroundWorker != null) { _backgroundWorker.CancelAsync(); } if (_dxMaterial != null) { _dxMaterial.Dispose(); _dxMaterial = null; } if (_simplePositionColorMaterial != null) { _simplePositionColorMaterial.Dispose(); _simplePositionColorMaterial = null; } _disposables.Dispose(); MainDXViewportView.Dispose(); }; }