private unsafe void UpdateGeometry() { DestroyGeometry(); Curve positionCurve = GetPositionCurve(); Curve radiusCurve = null; { bool existsSpecialRadius = false; foreach (MapCurvePoint point in Points) { RenderableCurvePoint point2 = point as RenderableCurvePoint; if (point2 != null && point2.OverrideRadius >= 0) { existsSpecialRadius = true; break; } } if (existsSpecialRadius) { switch (radiusCurveType) { case RadiusCurveTypes.UniformCubicSpline: radiusCurve = new UniformCubicSpline(); break; case RadiusCurveTypes.Bezier: radiusCurve = new BezierCurve(); break; case RadiusCurveTypes.Line: radiusCurve = new LineCurve(); break; } for (int n = 0; n < Points.Count; n++) { MapCurvePoint point = Points[n]; if (!point.Editor_IsExcludedFromWorld()) { float rad = radius; RenderableCurvePoint renderableCurvePoint = point as RenderableCurvePoint; if (renderableCurvePoint != null && renderableCurvePoint.OverrideRadius >= 0) { rad = renderableCurvePoint.OverrideRadius; } radiusCurve.AddValue(point.Time, new Vec3(rad, 0, 0)); } } } } //create mesh Vertex[] vertices = null; int[] indices = null; if (positionCurve != null && positionCurve.Values.Count > 1 && Points.Count >= 2) { Vec3 positionOffset = -Position; int steps = (Points.Count - 1) * pathSteps + 1; int vertexCount = steps * (shapeSegments + 1); int indexCount = (steps - 1) * shapeSegments * 2 * 3; vertices = new Vertex[vertexCount]; indices = new int[indexCount]; //fill data { int currentVertex = 0; int currentIndex = 0; float currentDistance = 0; Vec3 lastPosition = Vec3.Zero; Quat lastRot = Quat.Identity; for (int nStep = 0; nStep < steps; nStep++) { int startStepVertexIndex = currentVertex; float coefficient = (float)nStep / (float)(steps - 1); Vec3 pos = CalculateCurvePointByCoefficient(coefficient) + positionOffset; Quat rot; { Vec3 v = CalculateCurvePointByCoefficient(coefficient + .3f / (float)(steps - 1)) - CalculateCurvePointByCoefficient(coefficient); if (v != Vec3.Zero) { rot = Quat.FromDirectionZAxisUp(v.GetNormalize()); } else { rot = lastRot; } } if (nStep != 0) { currentDistance += (pos - lastPosition).Length(); } float rad; if (radiusCurve != null) { Range range = new Range(radiusCurve.Times[0], radiusCurve.Times[radiusCurve.Times.Count - 1]); float t = range.Minimum + (range.Maximum - range.Minimum) * coefficient; rad = radiusCurve.CalculateValueByTime(t).X; } else { rad = radius; } for (int nSegment = 0; nSegment < shapeSegments + 1; nSegment++) { float rotateCoefficient = ((float)nSegment / (float)(shapeSegments)); float angle = rotateCoefficient * MathFunctions.PI * 2; Vec3 p = pos + rot * new Vec3(0, MathFunctions.Cos(angle) * rad, MathFunctions.Sin(angle) * rad); Vertex vertex = new Vertex(); vertex.position = p; Vec3 pp = p - pos; if (pp != Vec3.Zero) { vertex.normal = pp.GetNormalize(); } else { vertex.normal = Vec3.XAxis; } //vertex.normal = ( p - pos ).GetNormalize(); vertex.texCoord = new Vec2(currentDistance * textureCoordinatesTilesPerMeter, rotateCoefficient + .25f); vertex.tangent = new Vec4(rot.GetForward(), 1); vertices[currentVertex++] = vertex; } if (nStep < steps - 1) { for (int nSegment = 0; nSegment < shapeSegments; nSegment++) { indices[currentIndex++] = startStepVertexIndex + nSegment; indices[currentIndex++] = startStepVertexIndex + nSegment + 1; indices[currentIndex++] = startStepVertexIndex + nSegment + 1 + shapeSegments + 1; indices[currentIndex++] = startStepVertexIndex + nSegment + 1 + shapeSegments + 1; indices[currentIndex++] = startStepVertexIndex + nSegment + shapeSegments + 1; indices[currentIndex++] = startStepVertexIndex + nSegment; } } lastPosition = pos; lastRot = rot; } if (currentVertex != vertexCount) { Log.Fatal("RenderableCurve: UpdateRenderingGeometry: currentVertex != vertexCount."); } if (currentIndex != indexCount) { Log.Fatal("RenderableCurve: UpdateRenderingGeometry: currentIndex != indexCount."); } } if (vertices.Length != 0 && indices.Length != 0) { //create mesh string meshName = MeshManager.Instance.GetUniqueName( string.Format("__RenderableCurve_{0}_{1}", Name, uniqueMeshIdentifier)); uniqueMeshIdentifier++; //string meshName = MeshManager.Instance.GetUniqueName( string.Format( "__RenderableCurve_{0}", Name ) ); mesh = MeshManager.Instance.CreateManual(meshName); SubMesh subMesh = mesh.CreateSubMesh(); subMesh.UseSharedVertices = false; //init vertexData VertexDeclaration declaration = subMesh.VertexData.VertexDeclaration; declaration.AddElement(0, 0, VertexElementType.Float3, VertexElementSemantic.Position); declaration.AddElement(0, 12, VertexElementType.Float3, VertexElementSemantic.Normal); declaration.AddElement(0, 24, VertexElementType.Float2, VertexElementSemantic.TextureCoordinates, 0); declaration.AddElement(0, 32, VertexElementType.Float4, VertexElementSemantic.Tangent, 0); fixed(Vertex *pVertices = vertices) { subMesh.VertexData = VertexData.CreateFromArray(declaration, (IntPtr)pVertices, vertices.Length * Marshal.SizeOf(typeof(Vertex))); } subMesh.IndexData = IndexData.CreateFromArray(indices, 0, indices.Length, false); //set material subMesh.MaterialName = materialName; //set mesh gabarites Bounds bounds = Bounds.Cleared; foreach (Vertex vertex in vertices) { bounds.Add(vertex.position); } mesh.SetBoundsAndRadius(bounds, bounds.GetRadius()); } } //create MeshObject, SceneNode if (mesh != null) { meshObject = SceneManager.Instance.CreateMeshObject(mesh.Name); if (meshObject != null) { meshObject.SetMaterialNameForAllSubObjects(materialName); meshObject.CastShadows = true; sceneNode = new SceneNode(); sceneNode.Attach(meshObject); //apply offset sceneNode.Position = Position; MapObject.AssociateSceneNodeWithMapObject(sceneNode, this); } } //create collision body if (mesh != null && collision) { Vec3[] positions = new Vec3[vertices.Length]; for (int n = 0; n < vertices.Length; n++) { positions[n] = vertices[n].position; } string meshPhysicsMeshName = PhysicsWorld.Instance.AddCustomMeshGeometry(positions, indices, null, MeshShape.MeshTypes.TriangleMesh, 0, 0); collisionBody = PhysicsWorld.Instance.CreateBody(); collisionBody.Static = true; collisionBody._InternalUserData = this; collisionBody.Position = Position; MeshShape shape = collisionBody.CreateMeshShape(); shape.MeshName = meshPhysicsMeshName; shape.MaterialName = CollisionMaterialName; shape.ContactGroup = (int)ContactGroup.Collision; //shape.VehicleDrivableSurface = collisionVehicleDrivableSurface; collisionBody.PushedToWorld = true; } needUpdate = false; }
private void CreateMesh() { Vec3 size = new Vec3(.97f, .97f, .1f); Vec3[] positions; Vec3[] normals; int[] indices; GeometryGenerator.GenerateBox(size, out positions, out normals, out indices); string meshName = MeshManager.Instance.GetUniqueName( string.Format("JigsawPuzzlePiece[{0},{1}]", index.X, index.Y)); mesh = MeshManager.Instance.CreateManual(meshName); //create submesh SubMesh subMesh = mesh.CreateSubMesh(); subMesh.UseSharedVertices = false; //init VertexData VertexDeclaration declaration = subMesh.VertexData.VertexDeclaration; declaration.AddElement(0, 0, VertexElementType.Float3, VertexElementSemantic.Position); declaration.AddElement(0, 12, VertexElementType.Float3, VertexElementSemantic.Normal); declaration.AddElement(0, 24, VertexElementType.Float2, VertexElementSemantic.TextureCoordinates, 0); VertexBufferBinding bufferBinding = subMesh.VertexData.VertexBufferBinding; HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( 32, positions.Length, HardwareBuffer.Usage.StaticWriteOnly); bufferBinding.SetBinding(0, vertexBuffer, true); subMesh.VertexData.VertexCount = positions.Length; unsafe { Vertex *buffer = (Vertex *)vertexBuffer.Lock(HardwareBuffer.LockOptions.Normal); for (int n = 0; n < positions.Length; n++) { Vertex vertex = new Vertex(); vertex.position = positions[n]; vertex.normal = normals[n]; if (JigsawPuzzleManager.Instance != null) { Vec2I pieceCount = JigsawPuzzleManager.Instance.PieceCount; Vec2I i = index; if (vertex.position.X > 0) { i.X++; } if (vertex.position.Y > 0) { i.Y++; } vertex.texCoord = new Vec2( (float)i.X / (float)pieceCount.X, 1.0f - (float)i.Y / (float)pieceCount.Y); } *buffer = vertex; buffer++; } vertexBuffer.Unlock(); } //calculate mesh bounds Bounds bounds = Bounds.Cleared; float radius = 0; foreach (Vec3 position in positions) { bounds.Add(position); float r = position.Length(); if (r > radius) { radius = r; } } mesh.SetBoundsAndRadius(bounds, radius); //init IndexData subMesh.IndexData = IndexData.CreateFromArray(indices, 0, indices.Length, false); //init material subMesh.MaterialName = "JigsawPuzzleImage"; }
private void buttonExport_Click(object sender, EventArgs e) { lastOutputMapName = textBoxOutputFileName.Text; string fileName = textBoxOutputFileName.Text.Trim(); bool rooted; try { rooted = Path.IsPathRooted(fileName); } catch { rooted = false; } if (!rooted) { Log.Warning(Translate("Invalid file name.")); return; } string caption = Translate("Export To 3D Model Add-on"); if (File.Exists(fileName)) { string template = Translate("The file with the name \"{0}\" is already exists. Overwrite?"); string text = string.Format(template, fileName); if (MessageBox.Show(text, caption, MessageBoxButtons.OKCancel, MessageBoxIcon.Question) != DialogResult.OK) { return; } } try { using (new CursorKeeper(Cursors.WaitCursor)) { //get selected entities List <Entity> selectedEntities; if (checkBoxExportSelectedObjectsOnly.Checked) { selectedEntities = MapEditorInterface.Instance.GetSelectedEntities(); } else { selectedEntities = new List <Entity>(); } Set <Entity> selectedEntitiesSet = new Set <Entity>(); foreach (Entity entity in selectedEntities) { selectedEntitiesSet.AddWithCheckAlreadyContained(entity); } string extension = Path.GetExtension(fileName); ModelImportLoader loader = MeshManager.Instance.GetModeImportLoaderByExtension(extension); if (loader == null) { Log.Warning(Translate("File extension \"{0}\" is not supported."), extension); return; } List <ModelImportLoader.SaveGeometryItem> geometry = new List <ModelImportLoader.SaveGeometryItem>(); List <VertexData> vertexDatasToDispose = new List <VertexData>(); List <IndexData> indexDatasToDispose = new List <IndexData>(); Set <string> names = new Set <string>(); //SceneNodes foreach (SceneNode sceneNode in SceneManager.Instance.SceneNodes) { Entity entity = sceneNode._InternalUserData as Entity; if (entity != null) { if (selectedEntities.Count == 0 || selectedEntitiesSet.Contains(entity)) { foreach (MovableObject movableObject in sceneNode.MovableObjects) { MeshObject meshObject = movableObject as MeshObject; if (meshObject != null) { foreach (SubMesh subMesh in meshObject.Mesh.SubMeshes) { string uniqueName = GetUniqueName(names, entity); VertexData vertexData = subMesh.UseSharedVertices ? subMesh.Parent.SharedVertexData : subMesh.VertexData; IndexData indexData = subMesh.IndexData; ModelImportLoader.SaveGeometryItem item = new ModelImportLoader.SaveGeometryItem( vertexData, indexData, sceneNode.Position, sceneNode.Rotation, sceneNode.Scale, uniqueName); geometry.Add(item); names.Add(uniqueName); } } } } } } foreach (Entity entity in Map.Instance.Children) { if (selectedEntities.Count == 0 || selectedEntitiesSet.Contains(entity)) { //StaticMesh StaticMesh staticMesh = entity as StaticMesh; if (staticMesh != null) { Mesh mesh = MeshManager.Instance.Load(staticMesh.MeshName); if (mesh != null) { foreach (SubMesh subMesh in mesh.SubMeshes) { string uniqueName = GetUniqueName(names, entity); VertexData vertexData = subMesh.UseSharedVertices ? subMesh.Parent.SharedVertexData : subMesh.VertexData; IndexData indexData = subMesh.IndexData; ModelImportLoader.SaveGeometryItem item = new ModelImportLoader.SaveGeometryItem(vertexData, indexData, staticMesh.Position, staticMesh.Rotation, staticMesh.Scale, uniqueName); geometry.Add(item); names.Add(uniqueName); } } } //HeightmapTerrain if (entity.Type.Name == "HeightmapTerrain") { try { MethodInfo method = entity.GetType().GetMethod("GetBodies"); Body[] bodies = (Body[])method.Invoke(entity, new object[0]); foreach (Body body in bodies) { foreach (Shape shape in body.Shapes) { //MeshShape MeshShape meshShape = shape as MeshShape; if (meshShape != null) { Vec3[] vertices; int[] indices; if (meshShape.GetData(out vertices, out indices)) { VertexData vertexData = CreateVertexData(vertices); if (vertexData != null) { vertexDatasToDispose.Add(vertexData); } IndexData indexData = IndexData.CreateFromArray( indices, 0, indices.Length, false); if (indexData != null) { indexDatasToDispose.Add(indexData); } if (vertexData != null && indexData != null) { string uniqueName = GetUniqueName(names, entity); ModelImportLoader.SaveGeometryItem item = new ModelImportLoader.SaveGeometryItem(vertexData, indexData, body.Position, body.Rotation, new Vec3(1, 1, 1), uniqueName); if (item != null) { geometry.Add(item); names.Add(uniqueName); } } } } //HeightFieldShape HeightFieldShape heightFieldShape = shape as HeightFieldShape; if (heightFieldShape != null) { Vec3[] vertices; int[] indices; heightFieldShape.GetVerticesAndIndices(false, false, out vertices, out indices); VertexData vertexData = CreateVertexData(vertices); if (vertexData != null) { vertexDatasToDispose.Add(vertexData); } IndexData indexData = IndexData.CreateFromArray( indices, 0, indices.Length, false); if (indexData != null) { indexDatasToDispose.Add(indexData); } if (vertexData != null && indexData != null) { string uniqueName = GetUniqueName(names, entity); ModelImportLoader.SaveGeometryItem item = new ModelImportLoader.SaveGeometryItem(vertexData, indexData, body.Position, body.Rotation, new Vec3(1, 1, 1), uniqueName); if (item != null) { geometry.Add(item); names.Add(uniqueName); } } } } } } catch { } } } } ////StaticMeshObjects //foreach( StaticMeshObject staticMeshObject in SceneManager.Instance.StaticMeshObjects ) //{ // Entity entity = staticMeshObject._InternalUserData as Entity; // if( entity != null ) // { // if( selectedEntities.Count == 0 || selectedEntitiesSet.Contains( entity ) ) // { // string name = entity.Name; // if( string.IsNullOrEmpty( name ) ) // name = entity.ToString(); // string uniqueName; // for( int n = 1; ; n++ ) // { // uniqueName = name; // if( n != 1 ) // uniqueName += n.ToString(); // if( !names.Contains( uniqueName ) ) // break; // } // ModelImportLoader.SaveGeometryItem item = new ModelImportLoader.SaveGeometryItem( // staticMeshObject.VertexData, staticMeshObject.IndexData, staticMeshObject.Position, // staticMeshObject.Rotation, staticMeshObject.Scale, uniqueName ); // geometry.Add( item ); // names.Add( uniqueName ); // } // } //} if (geometry.Count == 0) { Log.Warning(Translate("No data to export.")); return; } if (!loader.Save(geometry, fileName)) { return; } foreach (VertexData vertexData in vertexDatasToDispose) { vertexData.Dispose(); } foreach (IndexData indexData in indexDatasToDispose) { indexData.Dispose(); } } } catch (Exception ex) { Log.Warning(Translate("Error.") + "\n\n" + ex.Message); return; } MessageBox.Show(Translate("The geometry successfully exported!"), caption); }