public static Model3D CreateModel(ModelData modelData)
        {
            Model3D model = new Model3D();

             foreach (var mesh in modelData.Meshes)
            model.AddMesh(CreateModelMesh(mesh));

             return model;
        }
Пример #2
0
        public async void OnInsertAgain(string scene3DModelObj)
        {
            var _previousCursor = Mouse.OverrideCursor;

            Mouse.OverrideCursor = Cursors.Wait;

            //sync code
            //ModelVisual3D device = new ModelVisual3D();
            //device.Content = Scene3DLib.Scene3D.getModel(scene3DModelObj);
            //OnInsertAgain(scene3DModelObj, device, _previousCursor);

            //ATTENTION: Viewport3D seems to have a problem with non-ui-thread-loaded 3D objects !!!
            //This API was accessed with arguments from the wrong context.
            //Der aufrufende Thread kann nicht auf dieses Objekt zugreifen, da sich das Objekt im Besitz eines anderen Threads befindet.
            //https://www.google.ca/search?q=This%20API%20was%20accessed%20with%20arguments%20from%20the%20wrong%20context.&cad=h
            //solution: load Model3D & Freeze it!

            TaskScheduler uiScheduler  = TaskScheduler.FromCurrentSynchronizationContext();
            Dispatcher    uiDispatcher = Application.Current.Dispatcher;

            var     syncContext = SynchronizationContext.Current;
            Model3D model3D     = await Scene3DObjLoader.GetInstance().LoadObjectWithTaskAsync(scene3DModelObj);

            await         syncContext;
            ModelVisual3D device = new ModelVisual3D();

            device.Content = model3D;
            OnInsertAgain(scene3DModelObj, device, _previousCursor);

            /*
             * Model3D model3D = await Scene3DObjLoader.GetInstance().LoadObjectWithTaskAsync(scene3DModelObj).;
             *
             * Task.Factory.StartNew(() =>
             * {
             *  ModelVisual3D device1 = Scene3DObjLoader.GetInstance().LoadOjbect(scene3DModelObj);
             *  return device1;
             * }).ContinueWith((device2) =>
             * {
             *  OnInsertAgain(scene3DModelObj, device2.Result, _previousCursor);
             *
             * }, CancellationToken.None, TaskCreationOptions.None, uiScheduler);
             * /
             * /*
             * var syncContext = SynchronizationContext.Current;
             * ModelVisual3D device = await Scene3DObjLoader.GetInstance().LoadObjectWithTaskAsync(scene3DModelObj);
             * await syncContext;
             * /
             * var syncContext = SynchronizationContext.Current;
             * ModelVisual3D device = null;
             * await Task.Factory.StartNew(() => {
             *  device = Scene3DObjLoader.GetInstance().LoadOjbect(scene3DModelObj);
             *
             * }, TaskCreationOptions.LongRunning);
             * await syncContext;  //This API was accessed with arguments from the wrong context.
             *
             * Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
             * {
             *  //uiDispatcher.Invoke(new OnInsertAgainDelegate(OnInsertAgain), scene3DModelObj, device, _previousCursor));
             *  uiDispatcher.Invoke(new Action(() => OnInsertAgain(scene3DModelObj, device, _previousCursor)));
             * }));
             */
        }
Пример #3
0
        private void AddModel(Model3D originalModel3D, Point3D position, PositionTypes positionType, Size3D size, bool preserveAspectRatio = true)
        {
            // Create a new Model3DGroup that will hold the originalModel3D.
            // This allows us to have different transformation for each originalModel3D (transformation is on Model3DGroup)
            var model3DGroup = new Model3DGroup();

            model3DGroup.Children.Add(originalModel3D);

            Ab3d.Utilities.ModelUtils.PositionAndScaleModel3D(model3DGroup, position, positionType, size, preserveAspectRatio);

            // Add the model
            var modelVisual3D = new ModelVisual3D()
            {
                Content = model3DGroup
            };

            SolidObjectsVisual3D.Children.Add(modelVisual3D);



            // Now add red WireCrossVisual3D at the specified position
            var wireCrossVisual3D = new Ab3d.Visuals.WireCrossVisual3D()
            {
                Position    = position,
                LinesLength = 30,
                LineColor   = Colors.Red
            };

            SolidObjectsVisual3D.Children.Add(wireCrossVisual3D);


            // Now show a WireBoxVisual3D (box from 3D lines) that would represent the position, positionType and size.

            // To get the correct CenterPosition of the WireBoxVisual3D,
            // we start with creating a bounding box (Rect3D) that would be used when CenterPosition would be set to (0, 0, 0):
            var wireboxInitialBounds = new Point3D(-size.X * 0.5, -size.Y * 0.5, -size.Z * 0.5);

            // Then we use that bounding box and call GetModelTranslationVector3D method
            // that will tell us how much we need to move the bounding box so that it will be positioned at position and for positionType:
            var wireboxCenterOffset = Ab3d.Utilities.ModelUtils.GetModelTranslationVector3D(new Rect3D(wireboxInitialBounds, size), position, positionType);

            // Now we can use the result wireboxCenterOffset as a CenterPosition or a WireBoxVisual3D

            var wireBoxVisual3D = new WireBoxVisual3D()
            {
                CenterPosition = new Point3D(wireboxCenterOffset.X, wireboxCenterOffset.Y, wireboxCenterOffset.Z),
                Size           = size,
                LineColor      = Colors.Green,
                LineThickness  = 1
            };

            SolidObjectsVisual3D.Children.Add(wireBoxVisual3D);


            // Finally we add TextBlockVisual3D to show position and size information for this model
            // Note that the TextBlockVisual3D is added to the TransparentObjectsVisual3D.
            // The reason for this is that TextBlockVisual3D uses semi-transparent background.
            // To correctly show other object through semi-transparent, the semi-transparent must be added to the scene after solid objects.
            var infoText = string.Format("Position: {0:0}\r\nPositionType: {1}\r\nSize: {2:0}", position, positionType, size);

            if (!preserveAspectRatio)
            {
                infoText += "\r\npreserveAspectRatio: false";
            }

            var textBlockVisual3D = new TextBlockVisual3D()
            {
                Position      = new Point3D(model3DGroup.Bounds.GetCenterPosition().X, -15, 55), // Show so that X center position is the same as model center position
                PositionType  = PositionTypes.Center,
                TextDirection = new Vector3D(1, 0, 0),
                UpDirection   = new Vector3D(0, 1, -1), // angled at 45 degrees
                Size          = new Size(80, 0),        // y size will be calculated automatically based on x size (80) and size of the text

                Text            = infoText,
                BorderBrush     = Brushes.DimGray,
                BorderThickness = new Thickness(1, 1, 1, 1),
                Background      = new SolidColorBrush(Color.FromArgb(180, 200, 200, 200)),
                TextPadding     = new Thickness(5, 2, 5, 2)
            };

            TransparentObjectsVisual3D.Children.Add(textBlockVisual3D);
        }
Пример #4
0
        public void drawEverything()
        {
            if (Globals.renderCollisionMap)
            {
                collision.drawCollisionMap(false);
            }
            else
            {
                AreaModel.drawModel(Vector3.One, Quaternion.Identity, Vector3.Zero);
            }

            for (int i = 0; i < Objects.Count; i++)
            {
                Object3D obj   = Objects[i];
                Vector3  scale = Vector3.One;
                // Need to slighting increase the model's size, just in-case of overlapping bounding boxes.
                if (isObjectSelected(0, i))
                {
                    scale = new Vector3(1.001f, 1.001f, 1.001f);
                }
                Quaternion rotation = new Quaternion(obj.xRot, obj.yRot, obj.zRot, 1.0f);
                Vector3    position = new Vector3(obj.xPos, obj.yPos, obj.zPos);
                if (obj.ModelID != 0 && parent.ModelIDs.ContainsKey(obj.ModelID))
                {
                    Model3D model = parent.ModelIDs[obj.ModelID];
                    if (Globals.drawObjectModels)
                    {
                        model.drawModel(scale, rotation, position);
                    }
                    BoundingBox.draw(scale, rotation, position,
                                     isObjectSelected(0, i) ? Globals.SelectedObjectColor : Globals.ObjectColor,
                                     model.UpperBoundary + boundOff, model.LowerBoundary - boundOff);
                }
                else
                {
                    BoundingBox.draw(scale, rotation, position,
                                     isObjectSelected(0, i) ? Globals.SelectedObjectColor : Globals.ObjectColor,
                                     new Vector3(150.0f, 150.0f, 150.0f),
                                     new Vector3(-150.0f, -150.0f, -150.0f));
                }
            }
            for (int i = 0; i < MacroObjects.Count; i++)
            {
                Object3D   obj      = MacroObjects[i];
                Vector3    scale    = Vector3.One;
                Quaternion rotation = new Quaternion(obj.xRot, obj.yRot, obj.zRot, 1.0f);
                Vector3    position = new Vector3(obj.xPos, obj.yPos, obj.zPos);
                if (obj.ModelID != 0 && parent.ModelIDs.ContainsKey(obj.ModelID))
                {
                    Model3D model = parent.ModelIDs[obj.ModelID];
                    if (Globals.drawObjectModels)
                    {
                        model.drawModel(scale, rotation, position);
                    }
                    BoundingBox.draw(scale, rotation, position,
                                     isObjectSelected(1, i) ? Globals.SelectedObjectColor : Globals.MacroObjectColor,
                                     model.UpperBoundary + boundOff, model.LowerBoundary - boundOff);
                }
                else
                {
                    BoundingBox.draw(scale, rotation, position,
                                     isObjectSelected(1, i) ? Globals.SelectedObjectColor : Globals.MacroObjectColor,
                                     new Vector3(150.0f, 150.0f, 150.0f),
                                     new Vector3(-150.0f, -150.0f, -150.0f));
                }
            }
            for (int i = 0; i < SpecialObjects.Count; i++)
            {
                Object3D   obj      = SpecialObjects[i];
                Vector3    scale    = Vector3.One;
                Quaternion rotation = new Quaternion(obj.xRot, obj.yRot, obj.zRot, 1.0f);
                Vector3    position = new Vector3(obj.xPos, obj.yPos, obj.zPos);
                if (obj.ModelID != 0 && parent.ModelIDs.ContainsKey(obj.ModelID))
                {
                    Model3D model = parent.ModelIDs[obj.ModelID];
                    if (Globals.drawObjectModels)
                    {
                        model.drawModel(scale, rotation, position);
                    }
                    BoundingBox.draw(scale, rotation, position,
                                     isObjectSelected(2, i) ? Globals.SelectedObjectColor : Globals.SpecialObjectColor,
                                     model.UpperBoundary + boundOff, model.LowerBoundary - boundOff);
                }
                else
                {
                    BoundingBox.draw(scale, rotation, position,
                                     isObjectSelected(2, i) ? Globals.SelectedObjectColor : Globals.SpecialObjectColor,
                                     new Vector3(150.0f, 150.0f, 150.0f),
                                     new Vector3(-150.0f, -150.0f, -150.0f));
                }
            }
        }
Пример #5
0
        private static void CMD_1D(ref Model3D mdl, byte[] cmd)
        {
            uint scale = bytesToInt(cmd, 4, 4);

            mdl.builder.currentScale = (float)scale / 65536.0f;
        }
Пример #6
0
 public void HandleWheels()
 {
     if (!hasWheels)
     {
         Model mod = TheServer.Models.GetModel(model);
         if (mod == null) // TODO: mod should return a cube when all else fails?
         {
             return;
         }
         Model3D scene = mod.Original;
         if (scene == null) // TODO: Scene should return a cube when all else fails?
         {
             return;
         }
         SetOrientation(Quaternion.Identity);
         List <Model3DNode>       nodes       = GetNodes(scene.RootNode);
         List <VehiclePartEntity> frontwheels = new List <VehiclePartEntity>();
         for (int i = 0; i < nodes.Count; i++)
         {
             string name = nodes[i].Name.ToLowerFast();
             if (name.Contains("wheel"))
             {
                 Matrix      mat   = nodes[i].MatrixA;
                 Model3DNode tnode = nodes[i].Parent;
                 while (tnode != null)
                 {
                     mat   = tnode.MatrixA * mat;
                     tnode = tnode.Parent;
                 }
                 Location          pos   = GetPosition() + new Location(mat.M14, mat.M34, mat.M24) + offset; // NOTE: wtf happened to this matrix?
                 VehiclePartEntity wheel = new VehiclePartEntity(TheRegion, "vehicles/" + vehName + "_wheel", true);
                 wheel.SetPosition(pos);
                 wheel.SetOrientation(Quaternion.Identity);
                 wheel.Gravity = Gravity;
                 wheel.CGroup  = CGroup;
                 wheel.SetMass(30);
                 wheel.mode = ModelCollisionMode.CONVEXHULL;
                 TheRegion.SpawnEntity(wheel);
                 wheel.SetPosition(pos);
                 if (name.After("wheel").StartsWith("f"))
                 {
                     SteeringMotors.Add(ConnectWheel(wheel, false, true));
                     frontwheels.Add(wheel);
                 }
                 else if (name.After("wheel").StartsWith("b"))
                 {
                     DrivingMotors.Add(ConnectWheel(wheel, true, true));
                 }
                 else
                 {
                     ConnectWheel(wheel, true, false);
                 }
                 wheel.Body.ActivityInformation.Activate();
             }
         }
         if (frontwheels.Count == 2)
         {
             JointSpinner js = new JointSpinner(frontwheels[0], frontwheels[1], new Location(1, 0, 0));
             TheRegion.AddJoint(js);
         }
         hasWheels = true;
     }
 }
Пример #7
0
        private void LoadModel(string fileName)
        {
            // Create an instance of AssimpWpfImporter
            var assimpWpfImporter = new Ab3d.Assimp.AssimpWpfImporter();

            string fileExtension = System.IO.Path.GetExtension(fileName);

            Model3D readModel3D = null;
            object  readCamera  = null;

            if (fileExtension.Equals(".wpf3d", StringComparison.OrdinalIgnoreCase))
            {
                // Use Wpf3DFile importer to read wpf3d file format

                var wpf3DFile = new Ab3d.Utilities.Wpf3DFile();

                // We could read only header (description and thumbnail without any model data):
                //wpf3DFile.ReadFileHeader(fileName);

                try
                {
                    Mouse.OverrideCursor = Cursors.Wait;

                    readModel3D = wpf3DFile.ReadFile(fileName);
                    readCamera  = wpf3DFile.Camera;
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error reading file with Wpf3DFile:\r\n" + ex.Message);
                }
                finally
                {
                    Mouse.OverrideCursor = null;
                }
            }
            else if (assimpWpfImporter.IsImportFormatSupported(fileExtension))
            {
                // Use assimp importer to read many other file formats

                try
                {
                    Mouse.OverrideCursor = Cursors.Wait;

                    assimpWpfImporter.DefaultMaterial        = new DiffuseMaterial(Brushes.Silver);
                    assimpWpfImporter.AssimpPostProcessSteps = PostProcessSteps.Triangulate;
                    assimpWpfImporter.ReadPolygonIndices     = true;

                    // Read model from file
                    readModel3D = assimpWpfImporter.ReadModel3D(fileName, texturesPath: null); // we can also define a textures path if the textures are located in some other directory (this is parameter can be skipped, but is defined here so you will know that you can use it)
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error reading file with Assimp importer:\r\n" + ex.Message);
                }
                finally
                {
                    // Dispose unmanaged resources
                    assimpWpfImporter.Dispose();

                    Mouse.OverrideCursor = null;
                }
            }
            else
            {
                MessageBox.Show("Not supported file extension: " + fileExtension);
            }

            // Show the model
            if (readModel3D != null)
            {
                ShowModel(readModel3D, readCamera);
                _fileName = fileName;
            }
        }
Пример #8
0
        private void CreateScene()
        {
            // IMPORTANT:
            // Before the Form is closed, we need to dispose all the DXEngine objects that we created (all that implement IDisposable).
            // This means that all materials, Mesh objects and SceneNodes need to be disposed.
            // To make this easier, we can use the DisposeList collection that will hold IDisposable objects.
            _disposables = new DisposeList();


            //
            // 1)
            //
            // The easiest way to add 3D models to DXEngine's scene is to add WPF's Visual3D objects to Viewport3D.Children collection:

            var pyramidVisual3D = new Ab3d.Visuals.PyramidVisual3D()
            {
                BottomCenterPosition = new Point3D(-100, 0, 0),
                Size     = new Size3D(80, 50, 80),
                Material = new DiffuseMaterial(Brushes.Blue)
            };

            pyramidVisual3D.SetName("PyramidVisual3D");

            MainViewport.Children.Add(pyramidVisual3D);


            // We could also start from PyramidMesh3D and then create GeometryModel3D and ModelVisual3D
            //var pyramidMeshGeometry3D = new Ab3d.Meshes.PyramidMesh3D(new Point3D(100, 0, 0), new Size3D(80, 50, 80)).Geometry;

            //if (pyramidMeshGeometry3D.Normals.Count == 0)
            //    pyramidMeshGeometry3D.Normals = Ab3d.Utilities.MeshUtils.CalculateNormals(pyramidMeshGeometry3D);

            //var geometryModel3D = new GeometryModel3D(pyramidMeshGeometry3D, diffuseMaterial);
            //var modelVisual3D = new ModelVisual3D()
            //{
            //    Content = geometryModel3D
            //};

            //MainViewport.Children.Add(modelVisual3D);



            // DXEngine internally converts WPF objects into SceneNodes.
            // You can get the string that describes the SceneNodes with opening Visual Studio Immediate Window and execting the following:
            // MainDXViewportView.DXScene.DumpSceneNodes();
            //
            // Usually this is the best was to define the 3D scene.
            //
            // But if you have very complex objects with a lot of positions, it might be good to create the SceneNodes manually.
            // This allows faster initialization because WPF 3D objects are not created.
            // Also all the memory used by WPF 3D objects can be freed.
            //
            // Because WPF uses double type for Point3D and Vector3D types instead of float as in DirectX and DXEngine,
            // the memory size required for a 3D objects in WPF is almost twice the size of what is required in DXEngine.
            //
            // For example if your object has 100.000 positions, the the memory requirements are the following:
            //
            // In WPF:
            // Positions:           100.000 * 3 (x,y,z) * 8 (8 bytes for one double value) = 2.400.000 bytes
            // Normals:             100.000 * 3 (x,y,z) * 8 (8 bytes for one double value) = 2.400.000 bytes
            // Texture coordinates: 100.000 * 2 (u,y) * 8 (8 bytes for one double value)   = 1.600.000 bytes
            // Triangle indices:    100.000 * 4 (4 bytes for one Int32)                    =   400.000 bytes (the actual number of triangle indices may be different - depends on how many positions are shared between triangles)
            // TOTAL:                                                                      = 6.800.000 bytes = 6.7 MB
            //
            // In DXEngine:
            // Positions:           100.000 * 3 (x,y,z) * 4 (4 bytes for one float value) = 1.200.000 bytes
            // Normals:             100.000 * 3 (x,y,z) * 4 (4 bytes for one float value) = 1.200.000 bytes
            // Texture coordinates: 100.000 * 2 (u,y) * 4 (4 bytes for one float value)   =   800.000 bytes
            // Triangle indices:    100.000 * 4 (4 bytes for one Int32)                   =   400.000 bytes
            // TOTAL:                                                                     = 3.600.000 bytes = 3.5 MB
            //
            // Usually both objects need to be initialized (takes CPU time) and are stored in memory.
            //
            //
            // When the DXEngine's SceneNodes are manually created, the WPF objects can be cleared from memory
            // or event the SceneNodes can be created without the intermediate WPF objects.
            //
            // One the SceneNode is created it can be added to the scene with using SceneNodeVisual3D.
            // This is a Visual3D and can be added to the Viewport3D.Children collection.
            // The object also provides a way to add Transformation to the SceneNode.
            //
            // A disadvantage of creating SceneNodes is that such objects cannot be shown when WPF 3D rendering is used (for example in case when DXEngine falls back to WPF 3D rendering because of problems with DirectX initialization).
            // Another disadvantage is that it is more complicated to create and modify SceneNodes.
            //
            // Usually, when memory usage is not problematic, it is better to use standard WPF 3D objects.

            //
            // 2)
            //
            // Create MeshObjectNode from GeometryMesh with providing arrays (IList<T>) for positions, normals, textureCoordinates and triangleIndices:

            Vector3[] positions;
            Vector3[] normals;
            Vector2[] textureCoordinates;
            int[]     triangleIndices;

            // Get Pyramid mesh data
            GetObjectDataArrays(out positions, out normals, out textureCoordinates, out triangleIndices);


            // The easiest way to create DXEngine's material is to use Ab3d.DirectX.Materials.WpfMaterial that takes a WPF material and converts it into DXEngine's material
            var diffuseMaterial = new DiffuseMaterial(Brushes.Green);
            var dxMaterial      = new Ab3d.DirectX.Materials.WpfMaterial(diffuseMaterial);

            _disposables.Add(dxMaterial);

            // Create SceneNode
            // First create GeometryMesh object from the mesh arrays
            var geometryMesh = new Ab3d.DirectX.GeometryMesh(positions, normals, textureCoordinates, triangleIndices, "PyramidMesh3D");

            _disposables.Add(geometryMesh);

            // NOTE:
            // We could also create GeometryMesh from WPF's MeshGeometry with help from DXMeshGeometry3D:
            //var wpfPyramidMesh = new Meshes.PyramidMesh3D(bottomCenterPosition: new System.Windows.Media.Media3D.Point3D(0, 0, 0),
            //                                              size: new System.Windows.Media.Media3D.Size3D(30, 20, 10));

            //var geometryMesh = new Ab3d.DirectX.Models.DXMeshGeometry3D(wpfPyramidMesh.Geometry, "PyramidMesh");


            // Use GeometryMesh to create MeshObjectNode (SceneNode from GeometryMesh object)
            var meshObjectNode = new Ab3d.DirectX.MeshObjectNode(geometryMesh, dxMaterial);

            meshObjectNode.Name = "MeshObjectNode-from-GeometryMesh";

            _disposables.Add(meshObjectNode);

            // Use SceneNodeVisual3D to show SceneNode in DXViewportView
            var sceneNodeVisual3D = new SceneNodeVisual3D(meshObjectNode);

            //sceneNodeVisual3D.Transform = new TranslateTransform3D(0, 0, 0);

            MainViewport.Children.Add(sceneNodeVisual3D);


            //
            // 3)
            //
            // Create MeshObjectNode from SimpleMesh<T> with providing VertexBufferArray and IndexBufferArray:
            // This option provides faster initialization, because the VertexBufferArray is already generated and it can be directly used to create DirectX vertex buffer.
            // In the previous sample the VertexBufferArray was generated in the GeometryMesh from positions, normals, textureCoordinates arrays.
            //
            // If you can store your 3D models in disk (or some other location) in a form of VertexBuffer and IndexBuffer,
            // then this is the fastes way to initialize 3D objects.

            //
            // 3a)
            //
            // The standard way to create a SimpleMesh is to use the PositionNormalTexture or some other struct that defines the data for one array:

            PositionNormalTexture[] vertexBuffer;
            int[] indexBuffer;
            GetVertexAndIndexBuffer(out vertexBuffer, out indexBuffer);

            var simpleMesh = new SimpleMesh <PositionNormalTexture>(vertexBuffer,
                                                                    indexBuffer,
                                                                    inputLayoutType: InputLayoutType.Position | InputLayoutType.Normal | InputLayoutType.TextureCoordinate,
                                                                    name: "SimpleMesh-from-PositionNormalTexture-array");

            _disposables.Add(simpleMesh);

            diffuseMaterial = new DiffuseMaterial(Brushes.Red);
            dxMaterial      = new Ab3d.DirectX.Materials.WpfMaterial(diffuseMaterial);

            _disposables.Add(dxMaterial);

            meshObjectNode      = new Ab3d.DirectX.MeshObjectNode(simpleMesh, dxMaterial);
            meshObjectNode.Name = "MeshObjectNode-from-SimpleMesh";

            _disposables.Add(meshObjectNode);

            sceneNodeVisual3D           = new SceneNodeVisual3D(meshObjectNode);
            sceneNodeVisual3D.Transform = new TranslateTransform3D(100, 0, 0);

            MainViewport.Children.Add(sceneNodeVisual3D);



            //
            // 3b)
            //
            // It is also possible to create SimpleMesh with a base type - for example float (for example if we read data from file).
            // In this case we need to set the ArrayStride property.
            //
            // A drawback of using a non-standard vertex buffer (Vector3, PositionNormalTexture, PositionNormal or PositionTexture)
            // is that such mesh does not support hit testing.
            // In this sample this is demonstrated with camera rotation around mouse hit object - it is not possible to rotate around SimpleMesh<float>.

            float[] floatVertexBuffer;
            GetFloatVertexAndIndexBuffer(out floatVertexBuffer, out indexBuffer);

            var floatSimpleMesh = new SimpleMesh <float>(floatVertexBuffer,
                                                         indexBuffer,
                                                         inputLayoutType: InputLayoutType.Position | InputLayoutType.Normal | InputLayoutType.TextureCoordinate,
                                                         name: "SimpleMesh-from-float-array");

            _disposables.Add(floatSimpleMesh);

            // IMPORTANT:
            // When we do not use PositionNormalTexture or PositionNormal, the DXEngine cannot calculate Bounds of the SimpleMesh for us.
            // In this case we need to calculate and specify Bounds manually:
            // Defined bounds for the following mesh: new Ab3d.Meshes.PyramidMesh3D(new Point3D(0, 0, 0), new Size3D(80, 50, 80))
            floatSimpleMesh.Bounds = new Bounds(new BoundingBox(minimum: new Vector3(-40, -25, -40), maximum: new Vector3(40, 25, 40)));

            // Because we created SimpleMesh with a base type (float),
            // we need to specify how many array elements define one Vertex.
            // This is 8 in our case: 3 (position x,y,z) + 3 (normal x,y,z) + 2 (texture coordinate u,v) = 8
            floatSimpleMesh.ArrayStride = 8;


            diffuseMaterial = new DiffuseMaterial(Brushes.Orange);
            dxMaterial      = new Ab3d.DirectX.Materials.WpfMaterial(diffuseMaterial);

            _disposables.Add(dxMaterial);

            meshObjectNode      = new Ab3d.DirectX.MeshObjectNode(floatSimpleMesh, dxMaterial);
            meshObjectNode.Name = "MeshObjectNode-from-FloatSimpleMesh";

            _disposables.Add(meshObjectNode);

            sceneNodeVisual3D           = new SceneNodeVisual3D(meshObjectNode);
            sceneNodeVisual3D.Transform = new TranslateTransform3D(200, 0, 0);

            MainViewport.Children.Add(sceneNodeVisual3D);



            //
            // 3c)
            //
            // Instead of float array elements, it is also possible to use byte array to create SimpleMesh.
            //
            // As before, a drawback of using a non-standard vertex buffer (Vector3, PositionNormalTexture, PositionNormal or PositionTexture)
            // is that such mesh does not support hit testing.
            // In this sample this is demonstrated with camera rotation around mouse hit object - it is not possible to rotate around SimpleMesh<float>.

            byte[] byteVertexBuffer;
            GetByteVertexAndIndexBuffer(out byteVertexBuffer, out indexBuffer);

            var byteSimpleMesh = new SimpleMesh <byte>(byteVertexBuffer,
                                                       indexBuffer,
                                                       inputLayoutType: InputLayoutType.Position | InputLayoutType.Normal | InputLayoutType.TextureCoordinate,
                                                       name: "SimpleMesh-from-byte-array");

            _disposables.Add(byteSimpleMesh);

            // IMPORTANT:
            // When we do not use PositionNormalTexture or PositionNormal, the DXEngine cannot calculate Bounds of the SimpleMesh for us.
            // In this case we need to calculate and specify Bounds manually:
            // Defined bounds for the following mesh: new Ab3d.Meshes.PyramidMesh3D(new Point3D(0, 0, 0), new Size3D(80, 50, 80))
            byteSimpleMesh.Bounds = new Bounds(new BoundingBox(minimum: new Vector3(-40, -25, -40), maximum: new Vector3(40, 25, 40)));

            // Because we created SimpleMesh with a base type (byte),
            // we need to specify how many array elements define one Vertex.
            // This is 32 in our case: 8 (8x float value) * 4 (4 bytes for one float) = 32
            byteSimpleMesh.ArrayStride = 32;


            diffuseMaterial = new DiffuseMaterial(Brushes.Yellow);
            dxMaterial      = new Ab3d.DirectX.Materials.WpfMaterial(diffuseMaterial);

            _disposables.Add(dxMaterial);

            meshObjectNode      = new Ab3d.DirectX.MeshObjectNode(byteSimpleMesh, dxMaterial);
            meshObjectNode.Name = "MeshObjectNode-from-ByteSimpleMesh";

            _disposables.Add(meshObjectNode);

            sceneNodeVisual3D           = new SceneNodeVisual3D(meshObjectNode);
            sceneNodeVisual3D.Transform = new TranslateTransform3D(300, 0, 0);

            MainViewport.Children.Add(sceneNodeVisual3D);


            //
            // 4)
            //
            // When a frozen Model3DGroup is added to the DXViewportView, it is converted into the WpfOptimizedModel3DGroupNode (derived from SceneNode).
            // In this case both WPF and DXEngine's 3D objects data are stored in memory.
            //
            // To release the WPF 3D objects data, it is possible to create the WpfOptimizedModel3DGroupNode manually and
            // then clear the used WPF 3D objects.
            // This can be done with setting the AutomaticallyClearWpfObjectsAfterInitialization property on WpfOptimizedModel3DGroupNode to true,
            // or by calling the ClearWpfObjects method on WpfOptimizedModel3DGroupNode.

            string dragonModelFileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources\\Models\\dragon_vrip_res3.obj");

            var     readerObj   = new Ab3d.ReaderObj();
            Model3D readModel3D = readerObj.ReadModel3D(dragonModelFileName);

            double scale = 100 / readModel3D.Bounds.SizeX; // Scale the model to 100 SizeX

            readModel3D.Transform = new ScaleTransform3D(scale, scale, scale);

            var model3DGroup = readModel3D as Model3DGroup;

            if (model3DGroup == null)
            {
                model3DGroup = new Model3DGroup();
                model3DGroup.Children.Add(readModel3D);
            }

            model3DGroup.Freeze();


            var wpfOptimizedModel3DGroupNode = new Ab3d.DirectX.Models.WpfOptimizedModel3DGroupNode(model3DGroup, name: "Frozen Model3DGroup");

            wpfOptimizedModel3DGroupNode.AutomaticallyClearWpfObjectsAfterInitialization = true; // This will clear the WPF 3D models that are referenced by WpfOptimizedModel3DGroupNode when the DirectX objects are created

            _disposables.Add(wpfOptimizedModel3DGroupNode);

            sceneNodeVisual3D           = new SceneNodeVisual3D(wpfOptimizedModel3DGroupNode);
            sceneNodeVisual3D.Transform = new TranslateTransform3D(-100, -20, -100);

            MainViewport.Children.Add(sceneNodeVisual3D);


            //
            // 5)
            //
            // The following code shows how to load texture with using TextureLoader

            if (MainDXViewportView.DXScene != null)
            {
                var planeGeometry3D  = new Ab3d.Meshes.PlaneMesh3D(new Point3D(0, 0, 0), new Vector3D(0, 1, 0), new Vector3D(1, 0, 0), new Size(80, 80), 1, 1).Geometry;
                var dxMeshGeometry3D = new DXMeshGeometry3D(planeGeometry3D);
                _disposables.Add(dxMeshGeometry3D);

                // Load texture file into ShaderResourceView (in our case we load dds file; but we could also load png file)
                string textureFileName          = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources/ab4d-logo-220x220.dds");
                var    loadedShaderResourceView = Ab3d.DirectX.TextureLoader.LoadShaderResourceView(MainDXViewportView.DXScene.DXDevice.Device, textureFileName);

                _disposables.Add(loadedShaderResourceView);

                // Now we can create a DXEngine's StandardMaterial
                var standardMaterial = new StandardMaterial()
                {
                    // Set ShaderResourceView into array of diffuse textures
                    DiffuseTextures = new ShaderResourceView[] { loadedShaderResourceView },

                    // When showing texture, the DiffuseColor represents a color mask - each color from texture is multiplied with DiffuseColor (White preserves the original color)
                    DiffuseColor = Colors.White.ToColor3()
                };

                _disposables.Add(standardMaterial);

                meshObjectNode      = new Ab3d.DirectX.MeshObjectNode(dxMeshGeometry3D, standardMaterial);
                meshObjectNode.Name = "MeshObjectNode-from-PlaneMesh3D";

                _disposables.Add(meshObjectNode);

                sceneNodeVisual3D           = new SceneNodeVisual3D(meshObjectNode);
                sceneNodeVisual3D.Transform = new TranslateTransform3D(0, 0, 100);

                MainViewport.Children.Add(sceneNodeVisual3D);
            }



            // Add PointLight
            var pointLight = new PointLight(Colors.White, new Point3D(100, 500, 0));

            MainViewport.Children.Add(pointLight.CreateModelVisual3D());

            Camera1.ShowCameraLight = ShowCameraLightType.Never;
        }
Пример #9
0
        public static MeshGeometry3D GetMesh(this Model3D model)
        {
            var geometryModel = (GeometryModel3D)model;

            return((MeshGeometry3D)geometryModel.Geometry);
        }
Пример #10
0
        /// <summary>
        /// Converts a core Scene to a renderable model.
        /// </summary>
        /// <param name="scene">The backing model.</param>
        /// <param name="name">The name to use.</param>
        /// <param name="engine">The animation engine.</param>
        /// <returns>The model.</returns>
        public Model FromScene(Model3D scene, string name, AnimationEngine engine)
        {
            if (scene.Meshes.Count == 0)
            {
                throw new Exception("Scene has no meshes! (" + name + ")");
            }
            Model model = new Model(name)
            {
                Engine   = this,
                Original = scene,
                Root     = Convert(scene.MatrixA)
            };

            foreach (Model3DMesh mesh in scene.Meshes)
            {
                if (mesh.Name.ToLowerFast().Contains("collision") || mesh.Name.ToLowerFast().Contains("norender"))
                {
                    continue;
                }
                ModelMesh modmesh = new ModelMesh(mesh.Name);
                modmesh.vbo.Prepare();
                bool hastc = mesh.TexCoords.Count == mesh.Vertices.Count;
                bool hasn  = mesh.Normals.Count == mesh.Vertices.Count;
                if (!hasn)
                {
                    SysConsole.Output(OutputType.WARNING, "Mesh has no normals! (" + name + ")");
                }
                if (!hastc)
                {
                    SysConsole.Output(OutputType.WARNING, "Mesh has no texcoords! (" + name + ")");
                }
                for (int i = 0; i < mesh.Vertices.Count; i++)
                {
                    BEPUutilities.Vector3 vertex = mesh.Vertices[i];
                    modmesh.vbo.Vertices.Add(new Vector3((float)vertex.X, (float)vertex.Y, (float)vertex.Z));
                    if (!hastc)
                    {
                        modmesh.vbo.TexCoords.Add(new Vector3(0, 0, 0));
                    }
                    else
                    {
                        modmesh.vbo.TexCoords.Add(new Vector3((float)mesh.TexCoords[i].X, 1 - (float)mesh.TexCoords[i].Y, 0));
                    }
                    if (!hasn)
                    {
                        modmesh.vbo.Normals.Add(new Vector3(0f, 0f, 1f));
                    }
                    else
                    {
                        modmesh.vbo.Normals.Add(new Vector3((float)mesh.Normals[i].X, (float)mesh.Normals[i].Y, (float)mesh.Normals[i].Z));
                    }
                    modmesh.vbo.Colors.Add(new Vector4(1, 1, 1, 1)); // TODO: From the mesh?
                }
                for (int i = 0; i < mesh.Indices.Count; i++)
                {
                    modmesh.vbo.Indices.Add((uint)mesh.Indices[i]);
                }
                int bc = mesh.Bones.Count;
                if (bc > 200)
                {
                    SysConsole.Output(OutputType.WARNING, "Mesh has " + bc + " bones! (" + name + ")");
                    bc = 200;
                }
                modmesh.vbo.BoneIDs      = new Vector4[modmesh.vbo.Vertices.Count].ToList();
                modmesh.vbo.BoneWeights  = new Vector4[modmesh.vbo.Vertices.Count].ToList();
                modmesh.vbo.BoneIDs2     = new Vector4[modmesh.vbo.Vertices.Count].ToList();
                modmesh.vbo.BoneWeights2 = new Vector4[modmesh.vbo.Vertices.Count].ToList();
                int[] pos = new int[modmesh.vbo.Vertices.Count];
                for (int i = 0; i < bc; i++)
                {
                    for (int x = 0; x < mesh.Bones[i].Weights.Count; x++)
                    {
                        int   IDa     = mesh.Bones[i].IDs[x];
                        float Weighta = (float)mesh.Bones[i].Weights[x];
                        int   spot    = pos[IDa]++;
                        if (spot > 7)
                        {
                            //SysConsole.Output(OutputType.WARNING, "Too many bones influencing " + vw.VertexID + "!");
                            ForceSet(modmesh.vbo.BoneWeights, IDa, 3, modmesh.vbo.BoneWeights[IDa][3] + Weighta);
                        }
                        else if (spot > 3)
                        {
                            ForceSet(modmesh.vbo.BoneIDs2, IDa, spot - 4, i);
                            ForceSet(modmesh.vbo.BoneWeights2, IDa, spot - 4, Weighta);
                        }
                        else
                        {
                            ForceSet(modmesh.vbo.BoneIDs, IDa, spot, i);
                            ForceSet(modmesh.vbo.BoneWeights, IDa, spot, Weighta);
                        }
                    }
                }
                model.Meshes.Add(modmesh);
            }
            model.RootNode = new ModelNode()
            {
                Parent = null, Name = scene.RootNode.Name.ToLowerFast()
            };
            List <ModelNode> allNodes = new List <ModelNode>();

            PopulateChildren(model.RootNode, scene.RootNode, model, engine, allNodes);
            for (int i = 0; i < model.Meshes.Count; i++)
            {
                for (int x = 0; x < scene.Meshes[i].Bones.Count; x++)
                {
                    ModelNode nodet = null;
                    string    nl    = scene.Meshes[i].Bones[x].Name.ToLowerFast();
                    for (int n = 0; n < allNodes.Count; n++)
                    {
                        if (allNodes[n].Name == nl)
                        {
                            nodet = allNodes[n];
                            break;
                        }
                    }
                    ModelBone mb = new ModelBone()
                    {
                        Offset = Convert(scene.Meshes[i].Bones[x].MatrixA)
                    };
                    nodet.Bones.Add(mb);
                    model.Meshes[i].Bones.Add(mb);
                }
            }
            return(model);
        }
Пример #11
0
        /// <summary>
        /// loads a model from a file byte array.
        /// </summary>
        /// <param name="name">The name of the model.</param>
        /// <param name="data">The .obj file string.</param>
        /// <returns>A valid model.</returns>
        public Model FromBytes(string name, byte[] data)
        {
            Model3D scene = Handler.LoadModel(data);

            return(FromScene(scene, name, AnimEngine));
        }
Пример #12
0
        private Model3DGroup CreateGeometry(bool isFinal)
        {
            const double INSIDEPOINTRADIUS = .45d;

            ScaleTransform3D scaleTransform = new ScaleTransform3D(SCALE, SCALE, SCALE);

            Model3DGroup retVal = new Model3DGroup();

            // Insides
            if (!isFinal)
            {
                Model3D[] insideModels = CreateInsideVisuals(INSIDEPOINTRADIUS, this.MaterialBrushes, base.SelectionEmissives, scaleTransform);
                retVal.Children.AddRange(insideModels);
            }

            #region lights

            // Neat effect, but it makes my fan spin up, and won't slow back down.  Need to add an animation property to the options
            // class (and listen for when it toggles)

            //if (!isFinal)
            //{
            //    int numLights = 1 + this.Options.Random.Next(3);

            //    for (int cntr = 0; cntr < numLights; cntr++)
            //    {
            //        PointLight light = new PointLight();
            //        light.Color = Colors.Black;
            //        light.Range = SCALE * INSIDEPOINTRADIUS * 2d;
            //        light.LinearAttenuation = 1d;

            //        transformGroup = new Transform3DGroup();
            //        transformGroup.Children.Add(new TranslateTransform3D(Math3D.GetRandomVectorSpherical(this.Options.Random, INSIDEPOINTRADIUS)));
            //        transformGroup.Children.Add(scaleTransform);
            //        light.Transform = transformGroup;

            //        retVal.Children.Add(light);

            //        ColorAnimation animation = new ColorAnimation();
            //        animation.From = UtilityWPF.ColorFromHex("CC1266");
            //        animation.To = Colors.Black;
            //        animation.Duration = new Duration(TimeSpan.FromSeconds(1d + (this.Options.Random.NextDouble() * 5d)));
            //        animation.AutoReverse = true;
            //        animation.RepeatBehavior = RepeatBehavior.Forever;
            //        animation.AccelerationRatio = .5d;
            //        animation.DecelerationRatio = .5d;

            //        light.BeginAnimation(PointLight.ColorProperty, animation);
            //    }
            //}

            #endregion

            // Outer Shell
            Model3D geometry = CreateShellVisual(isFinal, this.MaterialBrushes, base.SelectionEmissives, scaleTransform);
            retVal.Children.Add(geometry);

            // Transform
            retVal.Transform = GetTransformForGeometry(isFinal);

            // Exit Function
            return(retVal);
        }
Пример #13
0
        private void LoadObj(string fileName)
        {
            if (_isLoading)
            {
                return;
            }

            bool isNewFile = (_fileName != fileName);

            _fileName   = fileName;
            _wpf3DModel = null;


            // Set ReadPolygonIndices in UI thread
            // When true ReaderObj will read PolygonIndices collection that can be used to show polygons instead of triangles
            _readerObj.ReadPolygonIndices = ReadPolygonIndicesCheckBox.IsChecked ?? false;

            // To read polygon indices from the read models,
            // iterating through GeometryModel3D objects (children of Model3DGroup) and
            // then converting its Geometry object into MeshGeometry3D.
            // The MeshGeometry3D defines the Positions, TriangleIndices, Normals and TextureCoordinates collections.
            //
            // On top of that the Ab3d.PowerToys and ReaderObj can also add the polygon indices collection.
            // It is set to MeshGeometry3D as a PolygonIndices dependency property (defined in Ab3d.Utilities.MeshUtils).
            // You can read the PolygonIndices directly with the following:
            //
            // var polygonIndices = meshGeometry3D.GetValue(Ab3d.Utilities.MeshUtils.PolygonIndicesProperty) as Int32Collection;
            //
            // You can also use the GetPolygonIndices, SetPolygonIndices and GetPolygonPositions extension methods on MeshGeometry3D,
            // or use GetPolygonPositions from MeshUtils.
            //
            // See also the following to get know how the polygon positions are organized:
            // https://www.ab4d.com/help/PowerToys/html/F_Ab3d_Utilities_MeshUtils_PolygonIndicesProperty.htm



            // UH: The following code is much much easier with async and await from .net 4.5
            // But here we want to use only .net 4.0

            // Read obj file and convert to wpf 3d objects in background thread
            var readObjFileTask = new Task(() =>
            {
                _lastException = null;

                try
                {
                    string texturesPath = Path.GetDirectoryName(_fileName);

                    // Read obj file from _fileName
                    // We read the object names into objectNames dictionary (Dictionary<string, Model3D>)
                    // This allows us to quickly get objects from their name.
                    // ReaderObj also set name to all objects and materials with using SetName extension method
                    // This way you can get object name or material name with GetName method.
                    // For example:
                    // _wpf3DModel.GetName();

                    var defaultMaterial = new DiffuseMaterial(Brushes.Silver);

                    _wpf3DModel = _readerObj.ReadModel3D(_fileName, texturesPath, defaultMaterial);

                    if (_wpf3DModel != null)
                    {
                        // We need to freeze the model because it was created on another thread.
                        // After the model is forzen, it cannot be changed any more.
                        // if you want to change the model, than Convert method must be called on UI thread
                        // or you must clone the read object in the UI thread
                        _wpf3DModel.Freeze();
                    }

                    // NOTE:
                    // If we wanted more control over reading obj files, we could read them in two steps
                    // 1) Read obj file into ObjFileData object
                    // 2) Convert read ObjFileData object into WPF Model3D
                    // The following code does that (uncomment it to see it in action):

                    //var objFileData = _readerObj.ReadFile(_fileName);
                    ////var objFileData = _readerObj.ReadStream(fileStream);

                    //var objMeshToWpfModel3DConverter = new ObjFileToWpfModel3DConverter();
                    //objMeshToWpfModel3DConverter.InvertYTextureCoordinate = false;
                    //objMeshToWpfModel3DConverter.TexturesDirectory = Path.GetDirectoryName(_fileName);

                    //// DefaultMaterial is a Material that is used when no other material is specified.
                    //// Actually with leaving DefaultMaterial as null, the same Silver material would be used (setting it here only to show the user what properties exist)
                    //objMeshToWpfModel3DConverter.DefaultMaterial = new DiffuseMaterial(Brushes.Silver);

                    //// ReuseMaterials specified if one material instance defined in obj file can be reused for all Model3D objects that use that material.
                    //// If false than a new material instance will be created for each usage
                    //// This is useful when user wants to change material on individual objects without applying the change to all other objects that use that material.
                    //// Default value is true.
                    //objMeshToWpfModel3DConverter.ReuseMaterials = true;

                    //_wpf3DModel = _objMeshToWpfModel3DConverter.Convert(objFileData);
                }
                catch (Exception ex)
                {
                    _lastException = ex;
                }
            });

            // After reading the obj file and converting it to WPF 3D objects we need to show the objects or errors - this needs to be done on UI thread
            var showObjectTask = readObjFileTask.ContinueWith(_ =>
            {
                try
                {
                    if (_lastException != null)
                    {
                        ResultTextBlock.Text = "ERROR reading obj file:\r\n" + _lastException.Message;
                    }
                    else if (_wpf3DModel != null)
                    {
                        string objectsDescriptions = Ab3d.Utilities.Dumper.GetObjectHierarchyString(_wpf3DModel);

                        if (_readerObj.Errors != null && _readerObj.Errors.Count > 0)
                        {
                            var sb = new StringBuilder();

                            sb.AppendLine("Obj file errors:");
                            foreach (var error in _readerObj.Errors)
                            {
                                sb.AppendLine(error);
                            }

                            ResultTextBlock.Text = objectsDescriptions + Environment.NewLine + Environment.NewLine + sb.ToString();
                        }
                        else
                        {
                            ResultTextBlock.Text = objectsDescriptions;
                        }

                        //ResultTextBlock.Text = Ab3d.Utilities.Dumper.GetMeshInitializationCode(model);
                        //ResultTextBlock.Text += "\r\n\n" + Ab3d.Utilities.Dumper.Dump(model);

                        ContentVisual.Content = _wpf3DModel;

                        // NOTE:
                        // We could show both solid model and wireframe in WireframeVisual3D (ContentWireframeVisual) with using WireframeWithOriginalSolidModel for WireframeType.
                        // But in this sample we show solid frame is separate ModelVisual3D and therefore we show only wireframe in WireframeVisual3D.
                        ContentWireframeVisual.BeginInit();
                        ContentWireframeVisual.ShowPolygonLines = ReadPolygonIndicesCheckBox.IsChecked ?? false;
                        ContentWireframeVisual.OriginalModel    = _wpf3DModel;
                        ContentWireframeVisual.EndInit();



                        // Calculate the center of the model and its size
                        // This will be used to position the camera

                        if (isNewFile) // If we just reloaded the previous file, we preserve the current camera TargetPosition and Distance
                        {
                            var bounds = _wpf3DModel.Bounds;

                            var modelCenter = new Point3D(bounds.X + bounds.SizeX / 2,
                                                          bounds.Y + bounds.SizeY / 2,
                                                          bounds.Z + bounds.SizeZ / 2);

                            var modelSize = Math.Sqrt(bounds.SizeX * bounds.SizeX +
                                                      bounds.SizeY * bounds.SizeY +
                                                      bounds.SizeZ * bounds.SizeZ);


                            Camera1.TargetPosition = modelCenter;
                            Camera1.Distance       = modelSize * 1.5;
                        }

                        // If the read model already define some lights, then do not show the Camera's light
                        if (ModelUtils.HasAnyLight(_wpf3DModel))
                        {
                            Camera1.ShowCameraLight = ShowCameraLightType.Never;
                        }
                        else
                        {
                            Camera1.ShowCameraLight = ShowCameraLightType.Always;
                        }
                    }

                    _isLoading = false;
                }
                finally
                {
                    Mouse.OverrideCursor = null;
                }
            },
                                                              TaskScheduler.FromCurrentSynchronizationContext()); // Run on UI thread


            _isLoading           = true;
            Mouse.OverrideCursor = Cursors.Wait;

            // Start tasks
            readObjFileTask.Start();
        }
Пример #14
0
 internal Model3DDrawElementsDelegate(Model3D model)
 {
     _model = model;
 }
Пример #15
0
        /// <summary>
        /// Translates the given <see cref="GeometryConfig"/> into a <see cref="Model3D"/>.
        /// </summary>
        /// <param name="geometry">The <see cref="GeometryConfig"/> storing the applicable data.</param>
        /// <param name="geometryIndex">A unique identifier generated by the caller of this method used to identify this geometry. If this ID is seen multiple times, the geometry won't be processed and instead the returned model will reference the existing data.</param>
        /// <param name="rootNode">If called by the <see cref="ArticulatedConfigHandler"/>, this is the root node of the associated <see cref="ArticulatedConfig"/>.</param>
        /// <returns></returns>
        public static Model3D GetGeometryInformation(GeometryConfig geometry, string geometryIndex, Node rootNode = null)
        {
            // stored
            // indexed stored
            // skinned indexed stored

            Model3D  model            = new Model3D();
            MeshData existingMeshData = MeshData.MeshDataBindings.GetOrDefault(geometryIndex);

            // model.Mesh = existingMeshData;

            if (existingMeshData == null)
            {
                // Go from the most complex to the least complex, since (presumably) simpler classes can nest.
                // Let's pull the basic arrays from the geometry data.
                MeshData meshData = new MeshData(geometryIndex);
                Debug.WriteLine("Created a new MeshData. Index: " + geometryIndex);

                float[]  vertices;
                float[]  uvs;
                float[]  normals;
                ushort[] indices;
                if (geometry is SkinnedIndexedStored skinnedIndexedStored)
                {
                    vertices = skinnedIndexedStored.getFloatArray(false, skinnedIndexedStored.vertexArray);
                    uvs      = skinnedIndexedStored.getFloatArray(false, skinnedIndexedStored.texCoordArrays);
                    normals  = skinnedIndexedStored.getFloatArray(false, skinnedIndexedStored.normalArray);
                    indices  = GetFromShortBuffer(skinnedIndexedStored.indices);

                    // Also need to handle skinning.
                    if (skinnedIndexedStored.mode != Mode.TRIANGLES)
                    {
                        XanLogger.WriteLine("WARNING: This Articulated model may not export properly! Its mode isn't TRIANGLES, and other behaviors (e.g. TRIANGLESTRIP) haven't been coded in yet! The method used for TRIANGLES will be applied anyway just to try something.", color: Color.DarkGoldenrod);
                    }
                    AttributeArrayConfig[] allArrays       = skinnedIndexedStored.vertexAttribArrays;
                    AttributeArrayConfig   boneIndicesAttr = GetArrayByName(allArrays, "boneIndices");
                    AttributeArrayConfig   boneWeightsAttr = GetArrayByName(allArrays, "boneWeights");

                    ushort[] boneIndicesS = skinnedIndexedStored.getFloatArray(false, boneIndicesAttr).ToUshortArray();
                    float[]  boneWeightsF = skinnedIndexedStored.getFloatArray(false, boneWeightsAttr);
                    // Now let's consider this literally: indices and weights for bones are vertex *attribute* arrays.
                    // So presumably this means that we iterate through the indices.
                    // The vertex at vertices[index] is part of bone boneIndices[index]. The index returned by boneIndices is the index of a name.
                    // A vertex can be in up to four groups at once, hence why these are in groups of quads.
                    // If the bone group is 0, it should be ignored.

                    // Apparently, this concept went way over my head in SK Animator Tools and it was a disaster. Part of why the code was so horrifying.

                    // Now for ease in indexing, I'm going to bump all of the elements in the bone name array forward by 1, then set index 0 to null.
                    string[] boneNames = new string[skinnedIndexedStored.bones.Length + 1];
                    boneNames[0] = null;
                    for (int idx = 0; idx < boneNames.Length - 1; idx++)
                    {
                        boneNames[idx + 1] = skinnedIndexedStored.bones[idx];
                    }

                    ushort[,] boneIndices = boneIndicesS.As2D(4);
                    float[,] boneWeights  = boneWeightsF.As2D(4);

                    meshData.BoneIndicesNative = boneIndicesS;
                    meshData.BoneWeightsNative = boneWeightsF;
                    meshData.BoneNames         = boneNames;
                    meshData.BoneIndices       = boneIndices;
                    meshData.BoneWeights       = boneWeights;

                    meshData.HasBoneData = true;

                    if (rootNode == null)
                    {
                        // The model supplied no root node. This can happen for implementations (e.g. StaticConfig) that has a GeometryConfig
                        // that is skinned.
                        // PRESUMABLY this means that it uses an external reference for its root node (e.g. the knight model has a common root)
                        // But in my case, I really can't read that right now.
                        meshData.UsesExternalRoot = true;
                    }
                    else
                    {
                        meshData.SetBones(rootNode);
                    }
                }
                else if (geometry is IndexedStored indexedStored)
                {
                    vertices             = indexedStored.getFloatArray(false, indexedStored.vertexArray);
                    uvs                  = indexedStored.getFloatArray(false, indexedStored.texCoordArrays);
                    normals              = indexedStored.getFloatArray(false, indexedStored.normalArray);
                    indices              = GetFromShortBuffer(indexedStored.indices);
                    meshData.HasBoneData = false;
                }
                else if (geometry is Stored stored)
                {
                    vertices = stored.getFloatArray(false, stored.vertexArray);
                    uvs      = stored.getFloatArray(false, stored.texCoordArrays);
                    normals  = stored.getFloatArray(false, stored.normalArray);
                    indices  = new ushort[vertices.Length];
                    for (ushort i = 0; i < indices.Length; i++)
                    {
                        indices[i] = i;
                    }
                    meshData.HasBoneData = false;
                }
                else
                {
                    throw new InvalidOperationException("The GeometryConfig type is unknown! Type: " + geometry.getClass().getName());
                }

                meshData.Vertices.SetFrom(Vector3.FromFloatArray(vertices));
                meshData.UVs.SetFrom(Vector2.FromFloatArray(uvs));
                meshData.Normals.SetFrom(Vector3.FromFloatArray(normals));
                meshData.Indices.SetFrom(indices);
                meshData.ConstructGroups();

                existingMeshData = meshData;
            }
            model.Mesh = existingMeshData;
            return(model);
        }
Пример #16
0
 /// <summary>
 /// Exports the specified model.
 /// </summary>
 /// <param name="model">
 /// The model.
 /// </param>
 public void Export(Model3D model)
 {
     this.ExportHeader();
     model.Traverse<GeometryModel3D>(this.ExportModel);
 }
 /// <summary>
 /// Traverses the Model3D tree. Run the specified action for each Model3D.
 /// </summary>
 /// <typeparam name="T">
 /// </typeparam>
 /// <param name="model">
 /// The model.
 /// </param>
 /// <param name="action">
 /// The action.
 /// </param>
 public static void TraverseModel<T>(Model3D model, Action<T, Transform3D> action) where T : Model3D
 {
     TraverseModel(model, Transform3D.Identity, action);
 }
        public PlanarShadowsCustomization()
        {
            InitializeComponent();

            _disposables = new DisposeList();

            MainDXViewportView.DXSceneInitialized += delegate(object sender, EventArgs args)
            {
                if (MainDXViewportView.DXScene != null)
                {
                    // Load texture file into ShaderResourceView (in our case we load dds file; but we could also load png file)
                    string textureFileName          = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources/GrassTexture.jpg");
                    var    loadedShaderResourceView = Ab3d.DirectX.TextureLoader.LoadShaderResourceView(MainDXViewportView.DXScene.DXDevice.Device, textureFileName);

                    _disposables.Add(loadedShaderResourceView);

                    // Define DXEngine's materials for shadow plane
                    _shadowPlaneMaterial = new StandardMaterial()
                    {
                        DiffuseColor    = Color3.White, // When DiffuseTextures are set, then DiffuseColor is used as a color filter (White means no filter)
                        DiffuseTextures = new ShaderResourceView[] { loadedShaderResourceView }
                    };

                    _shadowPlaneBackMaterial = new StandardMaterial()
                    {
                        DiffuseColor = Colors.DimGray.ToColor3()
                    };

                    _disposables.Add(_shadowPlaneMaterial);
                    _disposables.Add(_shadowPlaneBackMaterial);


                    // Define the PlanarShadowRenderingProvider
                    _planarShadowRenderingProvider = new PlanarShadowRenderingProvider()
                    {
                        // We need to provide information about the position of the plane in 3D space
                        ShadowPlaneCenterPosition  = new Vector3(0, 0, 0),
                        ShadowPlaneSize            = new Vector2(400, 400),
                        ShadowPlaneNormalVector    = new Vector3(0, 1, 0),
                        ShadowPlaneHeightDirection = new Vector3(0, 0, -1),

                        // In case ShadowPlaneMaterial and/or ShadowPlaneBackMaterial are defined
                        // the PlanarShadowRenderingProvider will also render the 3D plane.
                        ShadowPlaneMaterial     = _shadowPlaneMaterial,
                        ShadowPlaneBackMaterial = _shadowPlaneBackMaterial,

                        // Set shadow properties
                        ShadowColor        = Color3.Black,
                        ShadowTransparency = (float)ShadowTransparencySlider.Value / 100.0f, // default value is 0.65f

                        // Because shadow is rendered as standard 3D object, we need to offset it from the shadow plane
                        // to prevent z-fighting problems that occur when two 3D objects are rendered to the same 3D position.
                        // This value need to be very small so that it is not seen that the shadow is above the plane.
                        // Default value is 0.01f.
                        ShadowOffsetFromPlane = 0.01f,

                        // When using PlanarShadowRenderingProvider we do not need PlanarShadowMeshCreator from Ab3d.PowerToys
                        // to prepare a special MeshGeometry3D for us. Also PlanarShadowMeshCreator does not need to manually (on the CPU)
                        // cut the shadow to the plane bounds but this can be done with using hardware accelerated algorithm (using stencil buffer).
                        // But if we still want to use PlanarShadowMeshCreator we can set the following two properties to false
                        // (for example if we wanted to use PlanarShadowRenderingProvider just to provide proper transparent shadows).
                        ApplyShadowMatrix      = true,
                        CutShadowToPlaneBounds = true,

                        IsCheckingIsCastingShadow = false, // Initially do not check for IsCastingShadow values (this is also a default value). See comments in LoadModel for more info.

                        //CustomShadowLight = new Ab3d.DirectX.Lights.DirectionalLight(new Vector3(0, -1, 1))
                        //CustomShadowLight = new Ab3d.DirectX.Lights.PointLight(new Vector3(0, 500, 0), 300)
                    };

                    _disposables.Add(_planarShadowRenderingProvider);


                    MainDXViewportView.DXScene.InitializeShadowRendering(_planarShadowRenderingProvider);
                }


                _lightHorizontalAngle = 30;
                _lightVerticalAngle   = 27;
                _lightDistance        = 500;

                _ambientLight = new AmbientLight(System.Windows.Media.Color.FromRgb(40, 40, 40));

                _shadowPointLight       = new PointLight();
                _shadowDirectionalLight = new DirectionalLight();

                Camera1.ShowCameraLight = ShowCameraLightType.Never; // prevent adding camera's light

                SetShadowLight(isDirectionalLight: true);

                UpdateLights();

                _loadedModel3D = LoadModel3D();
                MainViewport.Children.Add(_loadedModel3D.CreateModelVisual3D());
            };



            this.PreviewKeyDown += OnPreviewKeyDown;

            // This will allow receiving keyboard events
            this.Focusable = true;
            this.Focus();

            this.Unloaded += delegate(object sender, RoutedEventArgs args)
            {
                _disposables.Dispose();
                MainDXViewportView.Dispose();
            };
        }
        public void ShowData(List <SphereData> originalData, Rect3D displayedDataBounds, Rect xyDataRange)
        {
            // Now use original data to create our data view objects

            // All data will be displayed in a 3D box defined below:
            //var displayedDataBounds = new Rect3D(AxesBox.CenterPosition.X - AxesBox.Size.X * 0.5,
            //                                     AxesBox.CenterPosition.Y - AxesBox.Size.Y * 0.5,
            //                                     AxesBox.CenterPosition.Z - AxesBox.Size.Z * 0.5,
            //                                     AxesBox.Size.X,
            //                                     AxesBox.Size.Y,
            //                                     AxesBox.Size.Z);

            _allSpheresData = new List <SphereDataView>(originalData.Count);

            foreach (var originalSphereData in originalData)
            {
                // Set color of the sphere based on its y position
                // We choose the color from the gradient defined in EnsureGradientColorsArray
                double relativeY = (originalSphereData.Location.Y - xyDataRange.Y) / xyDataRange.Height;

                int   colorArrayIndex = (int)(relativeY * (_gradientColorsArray.Length - 1));
                Color color           = _gradientColorsArray[colorArrayIndex];


                var sphereDataView = SphereDataView.Create(originalSphereData, displayedDataBounds, originalData.Count, xyDataRange, color);

                sphereDataView.IsSelectedChanged += delegate(object sender, EventArgs args)
                {
                    var changedPositionDataView = (SphereDataView)sender;
                    if (changedPositionDataView.IsSelected)
                    {
                        DataListBox.SelectedItems.Add(changedPositionDataView);
                    }
                    else
                    {
                        DataListBox.SelectedItems.Remove(changedPositionDataView);
                    }

                    UpdateSelectedSpheresData();
                };

                _allSpheresData.Add(sphereDataView);
            }

            // Bind positions data to ListBox
            DataListBox.ItemsSource = _allSpheresData;


            // Create curve through all positions
            // This is done by first creating all points that define the curve (10 points between each position that define the curve)
            List <Point3D> allPositions = new List <Point3D>();

            foreach (var positionData in _allSpheresData)
            {
                allPositions.Add(positionData.Position);
            }

            BezierCurve       bezierCurve = Ab3d.Utilities.BezierCurve.CreateFromCurvePositions(allPositions);
            Point3DCollection curvePoints = bezierCurve.CreateBezierCurve(positionsPerSegment: 10); // How many points between each defined position in the curve

            // Create 3D Polyline from curvePoints
            Model3D curveModel = Ab3d.Models.Line3DFactory.CreatePolyLine3D(curvePoints, thickness: 2, color: Colors.Blue, isClosed: false, startLineCap: LineCap.Flat, endLineCap: LineCap.Flat, parentViewport3D: MainViewport);

            CurveModelVisual.Content = curveModel;


            // Now create 3D sphere objects for each position
            SpheresModelVisual.Children.Clear();

            // Each sphere will also need MouseEnter, MouseLeave and MouseClick event handlers
            // We use EventManager3D for that
            var eventManager3D = new Ab3d.Utilities.EventManager3D(MainViewport);


            // Add 3D sphere for each position
            foreach (var positionData in _allSpheresData)
            {
                SpheresModelVisual.Children.Add(positionData.ModelVisual3D); // Sphere Visual3D is created in SphereDataView object

                // Add event handlers (sphere Visual3D will be the source of the events)
                var visualEventSource3D = new VisualEventSource3D(positionData.ModelVisual3D);

                visualEventSource3D.MouseEnter += delegate(object sender, Mouse3DEventArgs e)
                {
                    if (_isSelecting)
                    {
                        return;
                    }

                    // Use hand cursor
                    Mouse.OverrideCursor = Cursors.Hand;

                    // Find selected position data
                    var selectedPositionData = _allSpheresData.FirstOrDefault(p => p.ModelVisual3D == e.HitObject);

                    SelectData(selectedPositionData, e.CurrentMousePosition);
                };

                visualEventSource3D.MouseLeave += delegate(object sender, Mouse3DEventArgs e)
                {
                    if (_isSelecting)
                    {
                        return;
                    }

                    Mouse.OverrideCursor = null;

                    DataToolTipBorder.Visibility  = Visibility.Collapsed;
                    DataToolTipBorder.DataContext = null;

                    SelectedSphereLinesVisual.Children.Clear();
                };

                visualEventSource3D.MouseClick += delegate(object sender, MouseButton3DEventArgs e)
                {
                    // Select / deselect on mouse click
                    var clickedPositionData = _allSpheresData.FirstOrDefault(p => p.ModelVisual3D == e.HitObject);

                    if (clickedPositionData != null)
                    {
                        positionData.IsSelected = !clickedPositionData.IsSelected;
                    }
                };

                // Register the event source
                eventManager3D.RegisterEventSource3D(visualEventSource3D);
            }
        }
Пример #20
0
        private void CreateScene(Viewport3D parentViewport3D, double sphereRadius, double depthBias, TargetPositionCamera targetPositionCamera, bool showSphere)
        {
            parentViewport3D.Children.Clear();

            if (showSphere)
            {
                var sphereVisual3D = new Ab3d.Visuals.SphereVisual3D()
                {
                    CenterPosition          = new Point3D(0, 0, 0),
                    Radius                  = sphereRadius,
                    Segments                = 10,
                    Material                = new DiffuseMaterial(Brushes.SkyBlue),
                    UseCachedMeshGeometry3D = false // This will create a new MeshGeometry3D and will not use the shared MeshGeometry3D with radius = 1
                };

                parentViewport3D.Children.Add(sphereVisual3D);


                var sphereMesh = ((GeometryModel3D)sphereVisual3D.Content).Geometry as MeshGeometry3D;

                var sphereLinePositions = CollectWireframeLinePositions(sphereMesh);

                var multiLineVisual3D = new Ab3d.Visuals.MultiLineVisual3D()
                {
                    Positions     = sphereLinePositions,
                    LineThickness = 0.5,
                    LineColor     = Colors.Black,
                };

                // To specify line depth bias to the Ab3d.PowerToys line Visual3D objects,
                // we use SetDXAttribute extension method and use LineDepthBias as DXAttributeType
                // NOTE: This can be used only before the Visual3D is created by DXEngine.
                // If you want to change the line bias after the object has been rendered, use the SetDepthBias method (defined below)
                multiLineVisual3D.SetDXAttribute(DXAttributeType.LineDepthBias, depthBias);

                // It would be also possible to set the depth with changing the DepthBias on the WpfWireframeVisual3DNode.
                // This is done with using the SetDepthBias method
                //SetDepthBias(dxViewportView, wireframeVisual3D, depthBias);


                parentViewport3D.Children.Add(multiLineVisual3D);

                _shownLineVisual3D = multiLineVisual3D;
            }
            else
            {
                if (_sampleModel == null)
                {
                    var readerObj = new Ab3d.ReaderObj();
                    _sampleModel = readerObj.ReadModel3D(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Models\Teapot.obj"), null, new DiffuseMaterial(Brushes.SkyBlue));

                    _sampleModel.Freeze();
                }

                var readObjectRadius = Math.Sqrt(_sampleModel.Bounds.SizeX * _sampleModel.Bounds.SizeX + _sampleModel.Bounds.SizeZ + _sampleModel.Bounds.SizeZ) / 2;
                var scaleFactor      = sphereRadius / readObjectRadius;

                var finalModel = new Model3DGroup();
                finalModel.Children.Add(_sampleModel);
                finalModel.Transform = new ScaleTransform3D(scaleFactor, scaleFactor, scaleFactor);
                finalModel.Freeze();

                var wireframeVisual3D = new WireframeVisual3D()
                {
                    OriginalModel = finalModel,
                    WireframeType = WireframeVisual3D.WireframeTypes.WireframeWithOriginalSolidModel,
                    UseModelColor = false,
                    LineColor     = Colors.Black,
                    LineThickness = 0.5
                };

                // To specify line depth bias to the WireframeVisual3D,
                // we use SetDXAttribute extension method and use LineDepthBias as DXAttributeType
                wireframeVisual3D.SetDXAttribute(DXAttributeType.LineDepthBias, depthBias);

                // It would be also possible to set the depth with changing the DepthBias on the WpfWireframeVisual3DNode.
                // This is done with using the SetDepthBias method
                //SetDepthBias(dxViewportView, wireframeVisual3D, depthBias);


                parentViewport3D.Children.Add(wireframeVisual3D);

                _shownLineVisual3D = wireframeVisual3D;
            }

            _previousCameraDistance = sphereRadius * 4;
            targetPositionCamera.SetCurrentValue(BaseTargetPositionCamera.DistanceProperty, _previousCameraDistance);
            targetPositionCamera.SetCurrentValue(BaseCamera.OffsetProperty, new Vector3D(0, sphereRadius * 0.4, 0));
        }
Пример #21
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RectangleHitResult" /> class.
 /// </summary>
 /// <param name="model">The hit model.</param>
 public RectangleHitResult(Model3D model)
 {
     this.Model = model;
 }
Пример #22
0
        public static void parse(ref Model3D mdl, ref Level lvl, byte seg, uint off, byte?areaID)
        {
            if (seg == 0)
            {
                return;
            }
            ROM rom = ROM.Instance;

            byte[] data = rom.getSegment(seg, areaID);
            bool   end  = false;

            while (!end)
            {
                byte   cmdLen       = getCmdLength(data[off]);
                byte[] cmd          = rom.getSubArray_safe(data, off, cmdLen);
                string desc         = "Unknown command";
                bool   alreadyAdded = false;
                if (cmd[0] != 0x05 && nodeCurrent.isSwitch && nodeCurrent.switchPos != 1)
                {
                    if (nodeCurrent.switchFunc == 0x8029DB48)
                    {
                        //rom.printArray(cmd, cmdLen);
                        //Console.WriteLine(nodeCurrent.switchPos);
                    }
                    nodeCurrent.switchPos++;
                    off += cmdLen;
                    continue;
                }

                switch (cmd[0])
                {
                case 0x00:
                    desc = "Branch and Store (unused)";
                    end  = true;
                    break;

                case 0x01:
                    desc = "End geometry layout";
                    end  = true;
                    break;

                case 0x02:
                    desc = "Branch geometry layout to address 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    addGLSCommandToDump(ref mdl, cmd, seg, off, desc, areaID);
                    alreadyAdded = true;
                    CMD_02(ref mdl, ref lvl, cmd, areaID);
                    break;

                case 0x03:
                    desc = "Return from branch";
                    end  = true;
                    break;

                case 0x04:
                    desc = "Open New Node";
                    CMD_04();
                    break;

                case 0x05:
                    desc = "Close Node";
                    if (nodeCurrent != rootNode)
                    {
                        nodeCurrent = nodeCurrent.parent;
                    }
                    break;

                case 0x08:
                    desc = "Set screen rendering area (" +
                           "center X = " + (short)bytesToInt(cmd, 4, 2) +
                           ", center Y = " + (short)bytesToInt(cmd, 6, 2) +
                           ", Width = " + (short)(bytesToInt(cmd, 8, 2) * 2) +
                           ", Height = " + (short)(bytesToInt(cmd, 10, 2) * 2) + ")";
                    break;

                case 0x0A:
                    desc = "Set camera frustum (" +
                           "FOV = " + (short)bytesToInt(cmd, 2, 2) +
                           ", Near = " + (short)bytesToInt(cmd, 4, 2) +
                           ", Far = " + (short)bytesToInt(cmd, 6, 2) + ")";
                    break;

                case 0x0B:
                    desc = "Start geometry layout";
                    break;

                case 0x0C:
                    if (cmd[1] == 0x00)
                    {
                        desc = "Disable Z-Buffer";
                    }
                    else
                    {
                        desc = "Enable Z-Buffer";
                    }
                    break;

                case 0x0D:
                    desc = "Set render range from camera (min = " +
                           (short)bytesToInt(cmd, 4, 2) + ", max = " +
                           (short)bytesToInt(cmd, 6, 2) + ")";
                    break;

                case 0x0E:
                    desc = "Switch case with following display lists using ASM function 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    //rom.printArray(cmd, cmdLen);
                    CMD_0E(ref mdl, ref lvl, cmd);
                    break;

                case 0x10:
                    desc = "Translate and rotate";
                    //CMD_10(ref mdl, ref lvl, cmd);
                    break;

                case 0x11:
                    //rom.printArray(cmd, cmdLen);
                    CMD_11(ref mdl, ref lvl, cmd);
                    break;

                case 0x13:
                    desc = "Load display list 0x" + bytesToInt(cmd, 8, 4).ToString("X8") +
                           " into layer " + cmd[1] + " and offset position by (" +
                           (short)bytesToInt(cmd, 2, 2) +
                           "," + (short)bytesToInt(cmd, 2, 2) +
                           "," + (short)bytesToInt(cmd, 2, 2) +
                           ")";
                    //rom.printArray(cmd, cmdLen);
                    CMD_13(ref mdl, ref lvl, cmd, areaID);
                    break;

                case 0x14:
                    desc = "Billboard Model";
                    //CMD_10(ref mdl, ref lvl, cmd);
                    break;

                case 0x15:
                    desc = "Load display list 0x" + bytesToInt(cmd, 4, 4).ToString("X8") +
                           " into layer " + cmd[1];
                    CMD_15(ref mdl, ref lvl, cmd, areaID);
                    // rom.printArray(cmd, cmdLen);
                    break;

                case 0x16:
                    desc = "Start geometry layout with a shadow. (type = " + cmd[3] +
                           ", solidity = " + cmd[5] + ", scale = " +
                           bytesToInt(cmd, 6, 2) + ")";
                    //CMD_10(ref mdl, ref lvl, cmd);
                    break;

                case 0x17:
                    desc = "Setup display lists for level objects";
                    break;

                case 0x18:
                    desc = "Create display list(s) from the ASM function 0x" + bytesToInt(cmd, 4, 4).ToString("X8")
                           + " (a0 = " + bytesToInt(cmd, 2, 2) + ")";
                    CMD_18(ref mdl, ref lvl, cmd);
                    // rom.printArray(cmd, cmdLen);
                    break;

                case 0x19:
                    if (bytesToInt(cmd, 4, 4) == 0x00000000)
                    {
                        desc = "Draw solid color background. Color = (";
                        ushort color = (ushort)bytesToInt(cmd, 2, 2);
                        desc += (((color >> 11) & 0x1F) * 8) + ","
                                + (((color >> 6) & 0x1F) * 8) + ","
                                + (((color >> 1) & 0x1F) * 8) + ")";
                    }
                    else
                    {
                        desc = "Draw background image. bgID = " + bytesToInt(cmd, 2, 2) +
                               ", calls ASM function 0x" + bytesToInt(cmd, 4, 4).ToString("X8");
                    }
                    CMD_19(ref mdl, ref lvl, cmd, rom.decodeSegmentAddress(seg, off, areaID));
                    // rom.printArray(cmd, cmdLen);
                    break;

                case 0x1D:
                    desc = "Scale following node by " + ((bytesToInt(cmd, 4, 4) / 65536.0f) * 100.0f) + "%";
                    CMD_1D(ref mdl, cmd);
                    break;

                case 0x1A:
                case 0x1E:
                case 0x1F:
                    desc = "Do nothing";
                    break;

                case 0x20:
                    desc = "Start geometry layout with render area of " + bytesToInt(cmd, 2, 2);
                    break;
                }
                if (!alreadyAdded)
                {
                    addGLSCommandToDump(ref mdl, cmd, seg, off, desc, areaID);
                }
                off += cmdLen;
                if (nodeCurrent.isSwitch)
                {
                    nodeCurrent.switchPos++;
                }
            }
        }
Пример #23
0
        private Model3DGroup Initialize_Environment(string model1, string model2, string model3, string model4, string model5)
        {
            try
            {
                viewPort3d.RotateGesture = new MouseGesture(MouseAction.LeftClick);
                ModelImporter import = new ModelImporter();
                link1 = import.Load(model1);
                link2 = import.Load(model2);
                link3 = import.Load(model3);
                link4 = import.Load(model4);
                link5 = import.Load(model5);

                Transform3DGroup F1 = new Transform3DGroup();
                Transform3DGroup F2 = new Transform3DGroup();
                Transform3DGroup F3 = new Transform3DGroup();
                Transform3DGroup F4 = new Transform3DGroup();
                Transform3DGroup F5 = new Transform3DGroup();

                R = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 0, 1), joint1.Value), new Point3D(0, 0, 0));
                F1.Children.Add(R);

                T = new TranslateTransform3D(0, 0, 9.5);
                R = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 0, 1), joint2.Value), new Point3D(0, 0, 0));
                F2.Children.Add(F1);
                F2.Children.Add(T);
                F2.Children.Add(R);

                T = new TranslateTransform3D(15, 0, 0);
                R = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 0, 1), joint3.Value), new Point3D(0, 0, 0));
                F3.Children.Add(F2);
                F3.Children.Add(T);
                F3.Children.Add(R);


                T = new TranslateTransform3D(6.7, 0, 0);
                R = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 0, 1), joint4.Value), new Point3D(0, 0, 0));
                F4.Children.Add(F3);
                F4.Children.Add(T);
                F4.Children.Add(R);

                T = new TranslateTransform3D(5.35, 0, 0);
                R = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 0, 1), joint5.Value), new Point3D(0, 0, 0));
                F5.Children.Add(F4);
                F5.Children.Add(T);
                F5.Children.Add(R);

                link1.Transform = F1;
                link2.Transform = F2;
                link3.Transform = F3;
                link4.Transform = F4;
                link5.Transform = F5;

                RA.Children.Add(link1);
                RA.Children.Add(link2);
                RA.Children.Add(link3);
                RA.Children.Add(link4);
                RA.Children.Add(link5);
            }
            catch (Exception e)
            {
                MessageBox.Show("Exception Error:" + e.StackTrace);
            }
            return(RA);
        }
Пример #24
0
        public static void parse(ref Model3D mdl, ref Level lvl, byte seg, uint off)
        {
            if (seg == 0)
            {
                return;
            }
            ROM rom = ROM.Instance;

            byte[] data = rom.getSegment(seg);
            bool   end  = false;

            while (!end)
            {
                byte   cmdLen = getCmdLength(data[off]);
                byte[] cmd    = rom.getSubArray(data, off, cmdLen);
                //rom.printArray(cmd, cmdLen);
                if (cmd[0] != 0x05 && nodeCurrent.isSwitch && nodeCurrent.switchPos != 1)
                {
                    if (nodeCurrent.switchFunc == 0x8029DB48)
                    {
                        //rom.printArray(cmd, cmdLen);
                        //Console.WriteLine(nodeCurrent.switchPos);
                    }
                    nodeCurrent.switchPos++;
                    off += cmdLen;
                    continue;
                }

                switch (cmd[0])
                {
                case 0x00:
                case 0x01:
                    end = true;
                    break;

                case 0x02:
                    CMD_02(ref mdl, ref lvl, cmd);
                    break;

                case 0x03:
                    end = true;
                    break;

                case 0x04:
                    CMD_04();
                    break;

                case 0x05:
                    if (nodeCurrent != rootNode)
                    {
                        nodeCurrent = nodeCurrent.parent;
                    }
                    break;

                case 0x0E:
                    //rom.printArray(cmd, cmdLen);
                    CMD_0E(ref mdl, ref lvl, cmd);
                    break;

                case 0x10:
                    //CMD_10(ref mdl, ref lvl, cmd);
                    break;

                case 0x11:
                    //rom.printArray(cmd, cmdLen);
                    CMD_11(ref mdl, ref lvl, cmd);
                    break;

                case 0x13:
                    //rom.printArray(cmd, cmdLen);
                    CMD_13(ref mdl, ref lvl, cmd);
                    break;

                case 0x15:
                    CMD_15(ref mdl, ref lvl, cmd);
                    // rom.printArray(cmd, cmdLen);
                    break;

                case 0x1D:
                    CMD_1D(ref mdl, cmd);
                    break;
                }
                off += cmdLen;
                if (nodeCurrent.isSwitch)
                {
                    nodeCurrent.switchPos++;
                }
            }
        }
Пример #25
0
 public Model3DCommand(string type, Model3D parameters) : base(type, parameters)
 {
 }
Пример #26
0
 public void drawPicking()
 {
     for (int i = 0; i < Objects.Count; i++)
     {
         Object3D   obj      = Objects[i];
         Vector3    scale    = Vector3.One;
         Quaternion rotation = new Quaternion(obj.xRot, obj.yRot, obj.zRot, 1.0f);
         Vector3    position = new Vector3(obj.xPos, obj.yPos, obj.zPos);
         if (obj.ModelID != 0)
         {
             if (parent.ModelIDs.ContainsKey(obj.ModelID))
             {
                 Model3D model = parent.ModelIDs[obj.ModelID];
                 BoundingBox.draw_solid(scale, rotation, position,
                                        System.Drawing.Color.FromArgb(i % 256, i / 256, 1),
                                        model.UpperBoundary + boundOff, model.LowerBoundary - boundOff);
             }
         }
         else
         {
             BoundingBox.draw_solid(scale, rotation, position,
                                    System.Drawing.Color.FromArgb(i % 256, i / 256, 1),
                                    new Vector3(150.0f, 150.0f, 150.0f),
                                    new Vector3(-150.0f, -150.0f, -150.0f));
         }
     }
     for (int i = 0; i < MacroObjects.Count; i++)
     {
         Object3D   obj      = MacroObjects[i];
         Vector3    scale    = Vector3.One;
         Quaternion rotation = new Quaternion(obj.xRot, obj.yRot, obj.zRot, 1.0f);
         Vector3    position = new Vector3(obj.xPos, obj.yPos, obj.zPos);
         if (obj.ModelID != 0)
         {
             if (parent.ModelIDs.ContainsKey(obj.ModelID))
             {
                 Model3D model = parent.ModelIDs[obj.ModelID];
                 BoundingBox.draw_solid(scale, rotation, position,
                                        System.Drawing.Color.FromArgb(i % 256, i / 256, 2),
                                        model.UpperBoundary + boundOff, model.LowerBoundary - boundOff);
             }
         }
         else
         {
             BoundingBox.draw_solid(scale, rotation, position,
                                    System.Drawing.Color.FromArgb(i % 256, i / 256, 2),
                                    new Vector3(150.0f, 150.0f, 150.0f),
                                    new Vector3(-150.0f, -150.0f, -150.0f));
         }
     }
     for (int i = 0; i < SpecialObjects.Count; i++)
     {
         Object3D   obj      = SpecialObjects[i];
         Vector3    scale    = Vector3.One;
         Quaternion rotation = new Quaternion(obj.xRot, obj.yRot, obj.zRot, 1.0f);
         Vector3    position = new Vector3(obj.xPos, obj.yPos, obj.zPos);
         if (obj.ModelID != 0)
         {
             if (parent.ModelIDs.ContainsKey(obj.ModelID))
             {
                 Model3D model = parent.ModelIDs[obj.ModelID];
                 BoundingBox.draw_solid(scale, rotation, position,
                                        System.Drawing.Color.FromArgb(i % 256, i / 256, 3),
                                        model.UpperBoundary + boundOff, model.LowerBoundary - boundOff);
             }
         }
         else
         {
             BoundingBox.draw_solid(scale, rotation, position,
                                    System.Drawing.Color.FromArgb(i % 256, i / 256, 3),
                                    new Vector3(150.0f, 150.0f, 150.0f),
                                    new Vector3(-150.0f, -150.0f, -150.0f));
         }
     }
 }
Пример #27
0
 public UpdateModel3DCommand(Model3D parameters) : base("update", parameters)
 {
 }
        private void RecreateCurve()
        {
            // First update the positions
            PositionsVisual.Children.Clear();
            CurvesVisual.Children.Clear();

            // Add red crosses for each control point
            foreach (var onePosition in _controlPoints)
            {
                Ab3d.Visuals.WireCrossVisual3D cross = new Visuals.WireCrossVisual3D();
                cross.LineColor     = Colors.Red;
                cross.LineThickness = 1;
                cross.LinesLength   = 5;

                cross.Position = onePosition;

                PositionsVisual.Children.Add(cross);
            }


            RecreateControlPointNumbers();
            UpdatePositionCross();



            int positionsPerSegment = Int32.Parse(PointsCountTextBox.Text);


            // Create the curve
            // Because we already have the BezierCurve or BSpline class instance we can use them to create the curves.
            // First get the positions that will be used to create the PolyLine3D
            // Than we create the PolyLine3D
            // Note that we could also create the curves directly by the following methods:
            //curveModel = Ab3d.Models.Line3DFactory.CreateCurveThroughPoints3D(usedPointCollection, positionsPerSegment, 2, Colors.White, LineCap.Flat, LineCap.Flat, CurvesVisual);
            //curveModel = Ab3d.Models.Line3DFactory.CreateBezierCurve3D(usedPointCollection, positionsPerSegment, 2, Colors.White, LineCap.Flat, LineCap.Flat, CurvesVisual);
            //curveModel = Ab3d.Models.Line3DFactory.CreateBSpline3D(usedPointCollection, positionsPerSegment, 2, Colors.White, LineCap.Flat, LineCap.Flat, CurvesVisual);
            //curveModel = Ab3d.Models.Line3DFactory.CreateNURBSCurve3D(usedPointCollection, _weights, positionsPerSegment, 2, Colors.White, LineCap.Flat, LineCap.Flat, CurvesVisual);

            Point3DCollection finalPointsCollection;

            if (_selectedCurveType == CurveType.BezierCurve || _selectedCurveType == CurveType.CurveThroughPoints)
            {
                finalPointsCollection = _bezierCurve.CreateBezierCurve(positionsPerSegment);
            }
            else if (_selectedCurveType == CurveType.BSpline)
            {
                finalPointsCollection = _bspline.CreateBSpline(positionsPerSegment);
            }
            else
            {
                finalPointsCollection = _bspline.CreateNURBSCurve(positionsPerSegment);
            }

            Model3D curveModel = Ab3d.Models.Line3DFactory.CreatePolyLine3D(finalPointsCollection, 2, Colors.White, false, LineCap.Flat, LineCap.Flat, CurvesVisual);

            CurvesVisual.Content = curveModel;


            if (_selectedCurveType == CurveType.BezierCurve)
            {
                // Show bezier control points that represent tangent positions
                for (int i = 0; i < _bezierControlPoints.Count; i++)
                {
                    if ((i % 3) == 0) // Show only tanget positions - skip position on the curve - they were already shown
                    {
                        continue;
                    }

                    Ab3d.Visuals.WireCrossVisual3D cross = new Visuals.WireCrossVisual3D();

                    cross.LineColor     = Colors.Green;
                    cross.LineThickness = 1;
                    cross.LinesLength   = 5;
                    cross.Position      = _bezierControlPoints[i];
                    PositionsVisual.Children.Add(cross);
                }
            }
        }
Пример #29
0
 public Player(Model3D model, float width, float height, float depth, Vector3 translationVelocity, Vector3 angularVelocity)
     : base(model, width, height, depth, translationVelocity, angularVelocity)
 {
 }
Пример #30
0
        private void UpdateSlot(int index)
        {
            if (_slots.Count != pnlSlots.Children.Count)
            {
                throw new ApplicationException(string.Format("The list and panel are out of sync.  list={0}, panel={1}", _slots.Count.ToString(), pnlSlots.Children.Count.ToString()));
            }
            else if (_slots.Count < index)
            {
                throw new ArgumentException(string.Format("Invalid slot index: {0}, count={1}", index.ToString(), _slots.Count.ToString()));
            }

            Weapon weapon = null;

            if (_weapons != null && _weapons.Count > index)
            {
                weapon = _weapons[index];
            }

            SlotItem slot = _slots[index];

            slot.Text.Text = (index + 1).ToString();

            if (weapon == null)
            {
                #region Empty

                slot.Text.Fill   = _emptyTextFill;
                slot.Text.Stroke = _emptyTextStroke;
                ((BlurEffect)slot.Text.Effect).Radius = 8;

                if (slot.WeaponVisual != null)
                {
                    slot.Viewport.Children.Remove(slot.WeaponVisual);
                }

                slot.WeaponToken           = null;
                slot.WeaponRotateAnimation = null;
                slot.WeaponVisual          = null;

                #endregion
            }
            else
            {
                #region Filled

                // Darken the background text
                slot.Text.Fill   = _filledTextFill;
                slot.Text.Stroke = _filledTextStroke;
                ((BlurEffect)slot.Text.Effect).Radius = 3;

                // Remove visual if wrong weapon
                if (slot.WeaponToken != null && slot.WeaponToken.Value != weapon.Token)
                {
                    slot.Viewport.Children.Remove(slot.WeaponVisual);
                    slot.WeaponToken  = null;
                    slot.WeaponVisual = null;
                }

                // Add weapon visual
                if (slot.WeaponToken == null)
                {
                    Model3D model = UtilityCore.Clone(weapon.Model);
                    QuaternionRotation3D quatTransform = new QuaternionRotation3D(Math3D.GetRandomRotation());
                    model.Transform = new RotateTransform3D(quatTransform);

                    slot.WeaponRotateAnimation = AnimateRotation.Create_AnyOrientation(quatTransform, 3d);

                    slot.WeaponVisual = new ModelVisual3D()
                    {
                        Content = model
                    };

                    // Pull the camera back to a good distance
                    //NOTE: The positions are nomalized by the caller after this method has finished
                    slot.Camera.Position = (slot.Camera.Position.ToVector().ToUnit() * (weapon.Radius * 2.7d)).ToPoint();

                    slot.Viewport.Children.Add(slot.WeaponVisual);
                    slot.WeaponToken = weapon.Token;
                }

                #endregion
            }
        }
Пример #31
0
 public Model3DGamer(Model3DGroup models, IModelObject modelObject) : base(models, modelObject)
 {
     lastCurrentWeapon = TypesWeapon.Not;
     modelHands        = new Model3D(models, new Hand(modelObject as Gamer));
 }
Пример #32
0
        /// <summary>
        /// Finds the nearest point and its normal.
        /// </summary>
        /// <param name="viewport">
        /// The viewport.
        /// </param>
        /// <param name="position">
        /// The position.
        /// </param>
        /// <param name="point">
        /// The point.
        /// </param>
        /// <param name="normal">
        /// The normal.
        /// </param>
        /// <param name="visual">
        /// The visual.
        /// </param>
        /// <returns>
        /// The find nearest.
        /// </returns>
        public static bool FindNearest(this Viewport3DX viewport, Point position,
            out Point3D point, out Vector3D normal, out Model3D model)
        {
            point = new Point3D();
            normal = new Vector3D();
            model = null;

            var camera = viewport.Camera as ProjectionCamera;
            if (camera == null)
            {
                return false;
            }

            //var hits = FindHits(viewport, position);
            //if (hits.Count > 0)
            //{
            //    point = hits[0].PointHit;
            //    normal = hits[0].NormalAtHit;
            //    model = hits[0].ModelHit;
            //    return true;
            //}
            //else
            {
                // check for nearest points in the scene
                // TODO!!
                return false;
            }
        }
Пример #33
0
 public static MyTrans Transform(Model3D a)
 {
     return(new MyTrans(a.Transform));
 }