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>(); 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)) { ModelImportLoader.SaveGeometryItem.Vertex[] vertices2 = new ModelImportLoader.SaveGeometryItem.Vertex[vertices.Length]; for (int n = 0; n < vertices.Length; n++) { vertices2[n] = new ModelImportLoader.SaveGeometryItem.Vertex(vertices[n]); } string uniqueName = GetUniqueName(names, entity); ModelImportLoader.SaveGeometryItem item = new ModelImportLoader.SaveGeometryItem(vertices2, indices, false, 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); ModelImportLoader.SaveGeometryItem.Vertex[] vertices2 = new ModelImportLoader.SaveGeometryItem.Vertex[vertices.Length]; for (int n = 0; n < vertices.Length; n++) { vertices2[n] = new ModelImportLoader.SaveGeometryItem.Vertex(vertices[n]); } string uniqueName = GetUniqueName(names, entity); ModelImportLoader.SaveGeometryItem item = new ModelImportLoader.SaveGeometryItem(vertices2, indices, false, 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; } } } catch (Exception ex) { Log.Warning(Translate("Error.") + "\n\n" + ex.Message); return; } MessageBox.Show(Translate("The geometry successfully exported!"), caption); }
private void CreateDecalForStaticObject(ShapeTriangleID startTriangle, Vec3 pos, Vec3 normal, MapObject parentMapObject) { bool existsNormalsMore45Degrees = false; //find near triangles //Set<ShapeTriangleID> triangleIDs = new Set<ShapeTriangleID>(); { Sphere checkSphere = new Sphere(pos, Type.Size * .5f * 1.41f);//Sqrt(2) //Set<ShapeTriangleID> checkedTriangles = new Set<ShapeTriangleID>(); //Stack<ShapeTriangleID> trianglesForCheck = new Stack<ShapeTriangleID>( 16 ); trianglesForCheck.Push(startTriangle); while (trianglesForCheck.Count != 0) { ShapeTriangleID triangle = trianglesForCheck.Pop(); //add to checked triangles if (!checkedTriangles.AddWithCheckAlreadyContained(triangle)) { //ignore already checked triangles continue; } //get triangle points Vec3 p0, p1, p2; { switch (triangle.shape.ShapeType) { case Shape.Type.Mesh: MeshShape meshShape = (MeshShape)triangle.shape; meshShape.GetTriangle(triangle.triangleID, true, out p0, out p1, out p2); break; case Shape.Type.HeightField: HeightFieldShape heightFieldShape = (HeightFieldShape)triangle.shape; heightFieldShape.GetTriangle(triangle.triangleID, true, out p0, out p1, out p2); break; default: Log.Fatal("DecalCreator: CreateDecalForStaticObject: Not supported shape type ({0}).", triangle.shape.ShapeType); return; } } //cull by checkBounds if (!checkSphere.TriangleIntersection(p0, p1, p2)) { continue; } //check normal bool correctNormal = false; if (Type.SpreadType != DecalCreatorType.SpreadTypes.Directional) { Plane plane = Plane.FromPoints(p0, p1, p2); if (plane.GetSide(pos + normal) == Plane.Side.Positive) { Radian angle = MathFunctions.ACos(Vec3.Dot(normal, plane.Normal)); if (angle <= new Degree(70.0f).InRadians()) { if (!existsNormalsMore45Degrees && angle >= new Degree(45.0f).InRadians()) { existsNormalsMore45Degrees = true; } correctNormal = true; } } } else { correctNormal = true; } if (correctNormal) { //add triangle to result list triangleIDs.Add(triangle); } //add near triangles to check list { //expand vertices const float border = .001f; Vec3 center = (p0 + p1 + p2) * (1.0f / 3.0f); Vec3 diff0 = p0 - center; Vec3 diff1 = p1 - center; Vec3 diff2 = p2 - center; if (diff0 != Vec3.Zero && diff1 != Vec3.Zero && diff2 != Vec3.Zero) { p0 += diff0.GetNormalize() * border; p1 += diff1.GetNormalize() * border; p2 += diff2.GetNormalize() * border; Vec3 p01 = (p0 + p1) * .5f; Vec3 p12 = (p1 + p2) * .5f; Vec3 p20 = (p2 + p0) * .5f; //find triangles for (int n = 0; n < 3; n++) { Vec3 p = Vec3.Zero; switch (n) { case 0: p = p01; break; case 1: p = p12; break; case 2: p = p20; break; } RayCastResult[] piercingResult = PhysicsWorld.Instance.RayCastPiercing(new Ray( p + normal * .025f, -normal * .05f), (int)ContactGroup.CastOnlyCollision); foreach (RayCastResult result in piercingResult) { if (result.Shape != null) { trianglesForCheck.Push(new ShapeTriangleID( result.Shape, result.TriangleID)); } } } } } } checkedTriangles.Clear(); } if (triangleIDs.Count == 0) { return; } //calculate perpendiculars to normal Vec3 side1Normal; Vec3 side2Normal; { if (Math.Abs(normal.X) > .001f || Math.Abs(normal.Y) > .001f) { side1Normal = Mat3.FromRotateByZ(MathFunctions.PI / 2) * new Vec3(normal.X, normal.Y, 0); side1Normal.Normalize(); } else { side1Normal = new Vec3(1, 0, 0); } side2Normal = Vec3.Cross(normal, side1Normal); } //generate clip planes Plane[] clipPlanes = new Plane[6]; { float halfSize = Type.Size * .5f; if (existsNormalsMore45Degrees) { halfSize *= 1.41f; } Plane p; p = Plane.FromVectors(normal, -side2Normal, Position); clipPlanes[0] = new Plane(p.Normal, p.Distance + halfSize); p = Plane.FromVectors(normal, side2Normal, Position); clipPlanes[1] = new Plane(p.Normal, p.Distance + halfSize); p = Plane.FromVectors(normal, -side1Normal, Position); clipPlanes[2] = new Plane(p.Normal, p.Distance + halfSize); p = Plane.FromVectors(normal, side1Normal, Position); clipPlanes[3] = new Plane(p.Normal, p.Distance + halfSize); p = Plane.FromVectors(side1Normal, side2Normal, Position); clipPlanes[4] = new Plane(p.Normal, p.Distance + halfSize); //clipPlanes[ 4 ] = new Plane( p.Normal, p.Distance + halfSize * .5f ); p = Plane.FromVectors(side1Normal, -side2Normal, Position); clipPlanes[5] = new Plane(p.Normal, p.Distance + halfSize); //clipPlanes[ 5 ] = new Plane( p.Normal, p.Distance + halfSize * .5f ); } //generate vertices and indices by triangles //List<Decal.Vertex> vertices = new List<Decal.Vertex>( triangleIDs.Count * 3 ); //List<int> indices = new List<int>( triangleIDs.Count * 3 ); List <Decal.Vertex> vertices = tempVertices; List <int> indices = tempIndices; vertices.Clear(); indices.Clear(); { foreach (ShapeTriangleID triangle in triangleIDs) { Vec3 p0, p1, p2; { switch (triangle.shape.ShapeType) { case Shape.Type.Mesh: MeshShape meshShape = (MeshShape)triangle.shape; meshShape.GetTriangle(triangle.triangleID, true, out p0, out p1, out p2); break; case Shape.Type.HeightField: HeightFieldShape heightFieldShape = (HeightFieldShape)triangle.shape; heightFieldShape.GetTriangle(triangle.triangleID, true, out p0, out p1, out p2); break; default: Log.Fatal("DecalCreator: CreateDecalForStaticObject: Not supported shape type ({0}).", triangle.shape.ShapeType); return; } } List <Vec3> list = new List <Vec3>(); list.Add(p0); list.Add(p1); list.Add(p2); //clip by planes foreach (Plane plane in clipPlanes) { list = CutConvexPlanePolygonByPlane(list, plane); if (list == null) { break; } } //add to vertices and indices lists if (list != null) { int vertexCount = vertices.Count; Vec3 norm = Plane.FromPoints(p0, p1, p2).Normal; foreach (Vec3 p in list) { vertices.Add(new Decal.Vertex(p, norm, Vec2.Zero, Vec3.Zero)); } for (int n = 1; n < list.Count - 1; n++) { indices.Add(vertexCount); indices.Add(vertexCount + n); indices.Add(vertexCount + n + 1); } } } } triangleIDs.Clear(); if (indices.Count == 0) { return; } //calculate texCoord and Type.DepthRenderOffset { Plane planeSide1 = Plane.FromVectors(normal, side1Normal, Position); Plane planeSide2 = Plane.FromVectors(normal, side2Normal, Position); float invSize = 1.0f / Type.Size; for (int n = 0; n < vertices.Count; n++) { Decal.Vertex vertex = vertices[n]; //calculate texCoord float distance1 = planeSide1.GetDistance(vertex.position); float distance2 = planeSide2.GetDistance(vertex.position); vertex.texCoord = new Vec2(distance1 * invSize + .5f, distance2 * invSize + .5f); //Add perpendicular to normal offset. //Alternative way: for shader based rendering use DepthOffset property of decal material. //if( !RenderSystem.Instance.HasShaderModel3() ) { //add Type.DepthRenderOffset vertex.position = vertex.position + normal * Type.DepthRenderOffset; } vertices[n] = vertex; } } //calculate tangent vectors { int triangleCount = indices.Count / 3; for (int nTriangle = 0; nTriangle < triangleCount; nTriangle++) { int index0 = indices[nTriangle * 3 + 0]; int index1 = indices[nTriangle * 3 + 1]; int index2 = indices[nTriangle * 3 + 2]; Decal.Vertex vertex0 = vertices[index0]; Decal.Vertex vertex1 = vertices[index1]; Decal.Vertex vertex2 = vertices[index2]; Vec3 tangent = MathUtils.CalculateTangentSpaceVector( vertex0.position, vertex0.texCoord, vertex1.position, vertex1.texCoord, vertex2.position, vertex2.texCoord); vertex0.tangent += tangent; vertex1.tangent += tangent; vertex2.tangent += tangent; vertices[index0] = vertex0; vertices[index1] = vertex1; vertices[index2] = vertex2; } for (int n = 0; n < vertices.Count; n++) { Decal.Vertex vertex = vertices[n]; if (vertex.tangent != Vec3.Zero) { vertex.tangent.Normalize(); } vertices[n] = vertex; } } //subtract decal position (make local vertices coordinates) { for (int n = 0; n < vertices.Count; n++) { Decal.Vertex vertex = vertices[n]; vertex.position -= Position; vertices[n] = vertex; } } //get material string materialName = null; { string physicsMaterialName = startTriangle.shape.MaterialName; string defaultMaterialName = ""; foreach (DecalCreatorType.MaterialItem item in Type.Materials) { if (item.PhysicsMaterialName == physicsMaterialName) { materialName = item.MaterialName; } if (string.IsNullOrEmpty(item.PhysicsMaterialName)) { defaultMaterialName = item.MaterialName; } } if (materialName == null) { materialName = defaultMaterialName; } } //create Decal Decal decal = (Decal)Entities.Instance.Create("Decal", Map.Instance); decal.Position = Position; decal.Init(this, vertices.ToArray(), indices.ToArray(), materialName, parentMapObject); decal.PostCreate(); Type.AddDecalToCreatedList(decal); decals.Add(decal); }
private static void drawHeightfield(HeightFieldShape heightFieldShape, GraphicsDevice device) { VertexPositionNormalTexture[] cubeVertices; VertexDeclaration basicEffectVertexDeclaration; VertexBuffer vertexBuffer; var white = new Color(1, 1, 1, 1); int vertexNum = (heightFieldShape.HeightField.NumberOfRows - 1) * (heightFieldShape.HeightField.NumberOfColumns - 1) * 3 * 2; var vertices = new VertexPositionColor[vertexNum]; int triangleIndex; Vector3 pos; int vertexIndex = 0; HeightFieldShape.GetTriangleResult triangle; Camera _camera = CamerasManager.Instance.GetActiveCamera(); for (int row = 0; row < heightFieldShape.HeightField.NumberOfRows - 1; row++) { for (int column = 0; column < heightFieldShape.HeightField.NumberOfColumns - 1; column++) { triangleIndex = 2 * (row * heightFieldShape.HeightField.NumberOfColumns + column); triangle = heightFieldShape.GetTriangle(triangleIndex); pos = new Vector3(triangle.WorldTriangle.Vertex2.X, triangle.WorldTriangle.Vertex2.Y, triangle.WorldTriangle.Vertex2.Z); vertices[vertexIndex++] = new VertexPositionColor(pos, white); pos = new Vector3(triangle.WorldTriangle.Vertex1.X, triangle.WorldTriangle.Vertex1.Y, triangle.WorldTriangle.Vertex1.Z); vertices[vertexIndex++] = new VertexPositionColor(pos, white); pos = new Vector3(triangle.WorldTriangle.Vertex0.X, triangle.WorldTriangle.Vertex0.Y, triangle.WorldTriangle.Vertex0.Z); vertices[vertexIndex++] = new VertexPositionColor(pos, white); triangleIndex++; triangle = heightFieldShape.GetTriangle(triangleIndex); pos = new Vector3(triangle.WorldTriangle.Vertex2.X, triangle.WorldTriangle.Vertex2.Y, triangle.WorldTriangle.Vertex2.Z); vertices[vertexIndex++] = new VertexPositionColor(pos, white); pos = new Vector3(triangle.WorldTriangle.Vertex1.X, triangle.WorldTriangle.Vertex1.Y, triangle.WorldTriangle.Vertex1.Z); vertices[vertexIndex++] = new VertexPositionColor(pos, white); pos = new Vector3(triangle.WorldTriangle.Vertex0.X, triangle.WorldTriangle.Vertex0.Y, triangle.WorldTriangle.Vertex0.Z); vertices[vertexIndex++] = new VertexPositionColor(pos, white); } } //inicio do código do cubo //InitializeCube(); basicEffectVertexDeclaration = new VertexDeclaration( device, VertexPositionNormalTexture.VertexElements); var basicEffect = new BasicEffect(device, null); basicEffect.Alpha = 1.0f; basicEffect.DiffuseColor = new Vector3(0.2f, 0.0f, 1.0f); basicEffect.SpecularColor = new Vector3(0.25f, 0.25f, 0.25f); basicEffect.SpecularPower = 5.0f; basicEffect.AmbientLightColor = new Vector3(0.75f, 0.75f, 0.75f); //basicEffect.DirectionalLight0.Enabled = true; //basicEffect.DirectionalLight0.DiffuseColor = Vector3.One; //basicEffect.DirectionalLight0.Direction = Vector3.Normalize(new Vector3(1.0f, -1.0f, -1.0f)); //basicEffect.DirectionalLight0.SpecularColor = Vector3.One; //basicEffect.DirectionalLight1.Enabled = true; //basicEffect.DirectionalLight1.DiffuseColor = new Vector3(0.5f, 0.5f, 0.5f); //basicEffect.DirectionalLight1.Direction = Vector3.Normalize(new Vector3(-1.0f, -1.0f, 1.0f)); //basicEffect.DirectionalLight1.SpecularColor = new Vector3(0.5f, 0.5f, 0.5f); //basicEffect.LightingEnabled = true; basicEffect.World = Matrix.CreateScale(1, 1, 1); basicEffect.View = _camera.View; basicEffect.Projection = _camera.Projection; //NoNameEngine.Instance.Device.Clear(Color.SteelBlue); //NoNameEngine.Instance.Device.RenderState.CullMode = CullMode.CullClockwiseFace; device.VertexDeclaration = basicEffectVertexDeclaration; vertexBuffer = new VertexBuffer( device, VertexPositionColor.SizeInBytes * vertexNum, BufferUsage.None ); vertexBuffer.SetData(vertices); device.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionColor.SizeInBytes); // This code would go between a NoNameEngine.Instance.Device // BeginScene-EndScene block. basicEffect.Begin(); foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) { pass.Begin(); //this.NoNameEngine.Instance.Device.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleList, vertices, 0, vertexNum / 3); device.DrawPrimitives( PrimitiveType.TriangleList, 0, vertexNum / 3 ); //NoNameEngine.Instance.Device.DrawPrimitives( // PrimitiveType.TriangleList, // 0, // 12 // ); pass.End(); } basicEffect.End(); }
unsafe void CreateHeightFieldShape( HeightFieldShape shape, float totalVolume ) { if( sizeof( HeightFieldShape.Sample ) != 4 ) Log.Fatal( "PhysXBody: CreateHeightFieldShape: sizeof( HeightFieldShape.Sample ) != 4." ); if( shape.PerTriangleMaterials != null && shape.PerTriangleMaterials.Length > 127 ) Log.Fatal( "PhysXBody: CreateHeightFieldShape: The amount of per triangle materials can't be more than 127." ); Vec3 position = shape.Position; Quat rotation = shape.Rotation; //rotate by axis. rotation *= new Quat( .5f, .5f, .5f, .5f ); //Mat3 m = rotation.ToMat3(); //m *= Mat3.FromRotateByX( -MathFunctions.PI / 2 ); //m *= Mat3.FromRotateByY( -MathFunctions.PI / 2 ); //rotation = m.ToQuat(); Vec3 samplesScale = shape.SamplesScale; fixed( HeightFieldShape.Sample* pSamples = shape.Samples ) { IntPtr[] materials; if( shape.PerTriangleMaterials != null && shape.PerTriangleMaterials.Length > 0 ) { materials = new IntPtr[ shape.PerTriangleMaterials.Length ]; for( int n = 0; n < materials.Length; n++ ) { HeightFieldShape.PerTriangleMaterial item = shape.PerTriangleMaterials[ n ]; materials[ n ] = PhysXNativeMaterial.Create( item.StaticFriction, item.DynamicFriction, item.Restitution, item.MaterialName, item.VehicleDrivableSurface ); } } else materials = new IntPtr[] { CreateMaterial( shape ) }; fixed( IntPtr* pMaterials = materials ) { PhysXNativeBody.CreateHeightFieldShape( nativeBody, ref position, ref rotation, shape.SampleCount.X, shape.SampleCount.Y, (IntPtr)pSamples, ref samplesScale, shape.Thickness, materials.Length, pMaterials, shape.ContactGroup ); } } }