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";
        }
Exemple #3
0
        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);
        }