Esempio n. 1
0
        // returns instance index or -1 if instance not found
        private int GetHitInstanceIndex(RayMeshGeometry3DHitTestResult rayHitResult)
        {
            var modelHit = rayHitResult.ModelHit;

            // When WPF GeometryModel3D objects are crated with InstancedMeshGeometryVisual3D,
            // each GeometryModel3D has a InstancedMeshGeometryVisual3D.InstanceIndexProperty set to an int value
            // that represent an index of the instance.
            int hitInstanceIndex = (int)modelHit.GetValue(InstancedMeshGeometryVisual3D.InstanceIndexProperty);

            if (hitInstanceIndex == -1) // If InstanceIndexProperty was not set, then we get a default value of -1.
            {
                // In this case we need to use the slower path
                // of finding the instance index from the bounds of the hit Model3D.

                // InstanceData.GetHitInstanceIndex method gets the instance index in the _instancedData array that has the bounds set to hitBounds
                // The last parameter (useOnlyMatrixTranslation) can be set to true when the InstanceData define only translation (OffsetX, OffsetY, OffsetZ) and no scale or rotation.
                // In this case a faster code path can be taken. When useOnlyMatrixTranslation is false (by default) a full matrix transformation is executed on each position.
                Rect3D hitBounds = rayHitResult.ModelHit.Bounds;
                hitInstanceIndex = InstanceData.GetHitInstanceIndex(hitBounds, _instanceMeshGeometry3D.Bounds, _instancedData, useOnlyMatrixTranslation: false);

                // If not found then hitInstanceIndex is -1
            }

            return(hitInstanceIndex);
        }
Esempio n. 2
0
        private InstancedMeshGeometryVisual3D AddInstancedTubePath(Point3DCollection spiralPositionCollection, Color4 tubeColor)
        {
            // Setup InstanceData
            var instanceData = new InstanceData[spiralPositionCollection.Count];

            // Convert to list of Vector3
            var dxCurvePositions = spiralPositionCollection.Select(p => p.ToVector3()).ToList();


            // NOTE:
            // When a tube path is created from a lot of positions,
            // then it is worth to transform the following loop into Parallel.For loop.

            var startPosition = dxCurvePositions[0];

            for (int i = 1; i < dxCurvePositions.Count; i++)
            {
                var endPosition = dxCurvePositions[i];

                var direction = endPosition - startPosition;
                var length    = direction.Length(); // length will be used for x scale

                var scale = new Vector3(length, 1, 1);

                //direction.Normalize(); // Because we already have length, we can quickly normalize with simply dividing by length
                direction /= length;

                instanceData[i].World        = Common.MatrixUtils.GetMatrixFromNormalizedDirection(direction, startPosition, scale);
                instanceData[i].DiffuseColor = Color4.White;

                startPosition = endPosition;
            }

            // Create tube mesh with normalized radius (=1) and from (0,0,0) to (1,0,0).
            // This mesh is then transformed to connect positions along the path
            var tubeLineMesh3D = new Ab3d.Meshes.TubeLineMesh3D(startPosition: new Point3D(0, 0, 0),
                                                                endPosition: new Point3D(1, 0, 0),
                                                                radius: 1,
                                                                segments: 8,
                                                                generateTextureCoordinates: false).Geometry;

            // Create InstancedMeshGeometryVisual3D
            var instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(tubeLineMesh3D);

            instancedMeshGeometryVisual3D.InstancesData = instanceData;

            // Set IsSolidColorMaterial to render tube instances with solid color without any shading based on lighting
            instancedMeshGeometryVisual3D.IsSolidColorMaterial = true;

            // Add instancedMeshGeometryVisual3D to the scene
            MainViewport.Children.Add(instancedMeshGeometryVisual3D);

            return(instancedMeshGeometryVisual3D);
        }
Esempio n. 3
0
        private InstanceData[] CreateInstancesData(Point3D center, Size3D size, int xCount, int yCount, int zCount)
        {
            var instancedData = new InstanceData[xCount * yCount * zCount];

            float xStep = (float)(size.X / xCount);
            float yStep = (float)(size.Y / yCount);
            float zStep = (float)(size.Z / zCount);

            int i = 0;

            for (int z = 0; z < zCount; z++)
            {
                float zPos = (float)(center.Z - (size.Z / 2.0) + (z * zStep));

                for (int y = 0; y < yCount; y++)
                {
                    float yPos = (float)(center.Y - (size.Y / 2.0) + (y * yStep));

                    for (int x = 0; x < xCount; x++)
                    {
                        float xPos = (float)(center.X - (size.X / 2.0) + (x * xStep));

                        instancedData[i].World = SharpDX.Matrix.Translation(xPos, yPos, zPos);

                        // If we would also need to scale the mesh, we could create the matrix with the following code:
                        //instancedData[i].World = new SharpDX.Matrix(xScale, 0, 0, 0,
                        //                                            0, yScale, 0, 0,
                        //                                            0, 0, zScale, 0,
                        //                                            xPos, yPos, zPos, 1);

                        //instancedData[i].DiffuseColor = new SharpDX.Color4(new SharpDX.Color3(0.3f + ((float)x / (float)xCount) * 0.7f,
                        //                                                                      0.3f + ((float)y / (float)yCount) * 0.7f,
                        //                                                                      0.3f + ((float)y / (float)yCount) * 0.7f));

                        instancedData[i].DiffuseColor = new SharpDX.Color4(new SharpDX.Color3(0.1f + ((float)y / (float)yCount) * 0.9f,
                                                                                              (float)Math.Abs(0.5 - ((float)x / (float)xCount)) * 2.0f,
                                                                                              0.1f + ((float)(yCount - y) / (float)yCount) * 0.9f));

                        // Use WPF's Orange color:
                        //instancedData[i].Color = Colors.Orange.ToColor4();

                        i++;
                    }
                }
            }

            return(instancedData);
        }
Esempio n. 4
0
        private void CreateInstancedTubePath()
        {
            // Create curve through those points
            var controlPoints = new Point3D[]
            {
                new Point3D(-200, 50, 150),
                new Point3D(0, 50, 20),
                new Point3D(150, 50, 0),
                new Point3D(150, 50, 200),
                new Point3D(250, 50, 200)
            };

            // To create curve through specified points we must first convert the points into a bezierCurve (curve that has tangents defined for each point).
            // The curve is created with 10 points per segments - 10 points between two control points.
            var bezierCurve    = Ab3d.Utilities.BezierCurve.CreateFromCurvePositions(controlPoints);
            var curvePositions = bezierCurve.CreateBezierCurve(positionsPerSegment: 10);


            // Convert Point3D to Vector3
            var dxCurvePositions = curvePositions.Select(p => p.ToVector3()).ToList();

            // Setup InstanceData
            var instanceData = new InstanceData[curvePositions.Count];


            // NOTE:
            // When a tube path is created from a lot of positions,
            // then it is worth to transform the following loop into Parallel.For loop.

            var startPosition = dxCurvePositions[0];

            for (int i = 1; i < dxCurvePositions.Count; i++)
            {
                var endPosition = dxCurvePositions[i];

                var direction = endPosition - startPosition;
                var length    = direction.Length(); // length will be used for x scale

                var scale = new Vector3(length, 1, 1);

                //direction.Normalize(); // Because we already have length, we can quickly normalize with simply dividing by length
                direction /= length;

                instanceData[i].World        = Common.MatrixUtils.GetMatrixFromNormalizedDirection(direction, startPosition, scale);
                instanceData[i].DiffuseColor = Color4.White;

                startPosition = endPosition;
            }

            // Create tube mesh with normalized radius (=1) and from (0,0,0) to (1,0,0).
            // This mesh is then transformed to connect positions along the path
            var tubeLineMesh3D = new Ab3d.Meshes.TubeLineMesh3D(startPosition: new Point3D(0, 0, 0),
                                                                endPosition: new Point3D(1, 0, 0),
                                                                radius: 1,
                                                                segments: 8,
                                                                generateTextureCoordinates: false).Geometry;

            // Create InstancedMeshGeometryVisual3D
            var instancedMeshGeometryVisual3D = new InstancedMeshGeometryVisual3D(tubeLineMesh3D);

            instancedMeshGeometryVisual3D.InstancesData = instanceData;

            // Set IsSolidColorMaterial to render tube instances with solid color without any shading based on lighting
            instancedMeshGeometryVisual3D.IsSolidColorMaterial = true;

            // Add instancedMeshGeometryVisual3D to the scene
            MainViewport.Children.Add(instancedMeshGeometryVisual3D);
        }