private void MakeObjects(out MeshGeometry3D cameraMesh,
                                 out MeshGeometry3D boxMesh, out MeshGeometry3D edgeMesh,
                                 out Point3D cameraCenter)
        {
            // Make a "camera."
            cameraMesh = new MeshGeometry3D();
            cameraMesh.AddBox(new Point3D(-0.6, -0.5, -0.2),
                              D3.XVector(1.2), D3.YVector(1), D3.ZVector(0.4));
            Point3D[] points = G3.MakePolygonPoints(20, new Point3D(0, 0, -0.7),
                                                    D3.XVector(0.3), D3.YVector(0.3));
            cameraMesh.AddCylinder(points, D3.ZVector(0.7), true);
            points = G3.MakePolygonPoints(20, new Point3D(0, 0, -0.8),
                                          D3.XVector(0.4), D3.YVector(0.4));
            cameraMesh.AddCylinder(points, D3.ZVector(0.2), true);
            cameraMesh.AddBox(new Point3D(0.3, 0.5, -0.1),
                              D3.XVector(0.2), D3.YVector(0.2), D3.ZVector(0.2));
            MainGroup.Children.Add(cameraMesh.MakeModel(Brushes.LightBlue));

            // Transform the camera and vector.
            Transform3DGroup  trans = new Transform3DGroup();
            RotateTransform3D r1    = D3.Rotate(D3.XVector(), D3.Origin, -45);

            trans.Children.Add(r1);
            RotateTransform3D r2 = D3.Rotate(D3.YVector(), D3.Origin, -45);

            trans.Children.Add(r2);

            // See where we need to translate to make the camera point at the origin.
            Point3D lookAtPoint = new Point3D(0, 0, -3.5);

            lookAtPoint = trans.Transform(lookAtPoint);

            TranslateTransform3D t1 = new TranslateTransform3D(
                -lookAtPoint.X, -lookAtPoint.Y, -lookAtPoint.Z);

            trans.Children.Add(t1);
            cameraMesh.ApplyTransformation(trans);

            cameraCenter = trans.Transform(D3.Origin);

            // Make a target box.
            boxMesh = new MeshGeometry3D();
            boxMesh.AddBox(new Point3D(-0.75, -0.75, -0.75),
                           D3.XVector(1.5), D3.YVector(1.5), D3.ZVector(1.5));
            MainGroup.Children.Add(boxMesh.MakeModel(Brushes.LightGreen));

            // Make the box's edges.
            edgeMesh = new MeshGeometry3D();
            HashSet <Edge> edges = new HashSet <Edge>();

            edgeMesh.AddBox(new Point3D(-0.75, -0.75, -0.75),
                            D3.XVector(1.5), D3.YVector(1.5), D3.ZVector(1.5), edges: edges);
            MainGroup.Children.Add(edgeMesh.MakeModel(Brushes.Black));
        }
Exemplo n.º 2
0
        // Define the model.
        private void DefineModel(Model3DGroup group)
        {
            // Axes.
            MeshExtensions.AddAxes(group);

            MeshGeometry3D mesh1 = new MeshGeometry3D();
            MeshGeometry3D mesh2 = new MeshGeometry3D();
            MeshGeometry3D mesh3 = new MeshGeometry3D();
            MeshGeometry3D mesh4 = new MeshGeometry3D();

            double  x0     = -5;
            Point3D center = new Point3D(x0, 0, 4.5);

            // Box.
            mesh1.AddBox(center + new Vector3D(-0.5, 0, -1),
                         D3.XVector(1), D3.YVector(3), D3.ZVector(2));
            center.X += 2;

            // Box wrapped.
            mesh2.AddBoxWrapped(center + new Vector3D(-0.5, 0, -1),
                                D3.XVector(1), D3.YVector(3), D3.ZVector(2));
            center.X += 2;

            // Cone.
            Point3D[] circle = G3.MakePolygonPoints(20, center, D3.XVector(1), D3.ZVector(-1));
            mesh1.AddCone(center, circle, D3.YVector(4));
            center.X += 2;

            // Cone frustum.
            circle = G3.MakePolygonPoints(20, center, D3.XVector(1), D3.ZVector(-1));
            mesh1.AddConeFrustum(center, circle, D3.YVector(4), 3);
            center.X += 2;

            // Cone frustum w/cutting plane.
            circle = G3.MakePolygonPoints(20, center, D3.XVector(1), D3.ZVector(-1));
            mesh1.AddConeFrustum(center, circle, D3.YVector(4),
                                 center + new Vector3D(0, 2, 0), new Vector3D(0, 1, 1));
            center.X += 2;

            // Start a new row.
            center.X  = x0;
            center.Z -= 3;

            // Cube.
            MeshGeometry3D cubeMesh = new MeshGeometry3D();

            cubeMesh.AddCube();
            cubeMesh.ApplyTransformation(new ScaleTransform3D(1, 1.5, 0.5));
            cubeMesh.ApplyTransformation(
                new TranslateTransform3D(center.X, center.Y + 1.5, 0));
            mesh3.Merge(cubeMesh);
            center.X += 2;

            // Cylinder.
            Point3D[] polygon = G3.MakePolygonPoints(7, center, D3.XVector(1), D3.ZVector(-1));
            mesh1.AddCylinder(polygon, new Vector3D(0, 2, -1));
            center.X += 2;

            // Cylinder.
            circle = G3.MakePolygonPoints(20, center, D3.XVector(1), D3.ZVector(-1));
            mesh1.AddCylinder(circle, new Vector3D(0, 2, -1), true);
            center.X += 2;

            // Cylinder w/cutting planes.
            polygon = G3.MakePolygonPoints(7, center, D3.XVector(1), D3.ZVector(-1));
            mesh1.AddCylinder(polygon, new Vector3D(0, 1, 0),
                              center + new Vector3D(0, 2, 0), new Vector3D(0, 2, 1),
                              center + new Vector3D(0, -2, 0), new Vector3D(0, 2, -1));
            center.X += 2;

            // Cylinder w/cutting planes.
            polygon = G3.MakePolygonPoints(7, center, D3.XVector(1), D3.ZVector(-1));
            mesh1.AddCylinder(polygon, new Vector3D(0, 1, 0),
                              center + new Vector3D(0, 2, 0), new Vector3D(0, 2, 1),
                              center + new Vector3D(0, -2, 0), new Vector3D(0, 2, -1), true);
            center.X += 2;

            // Start a new row.
            center.X  = x0;
            center.Z -= 3;

            // Dodecahedron.
            MeshGeometry3D dodMesh = new MeshGeometry3D();

            dodMesh.AddDodecahedron();
            double dodScale = 1 / G3.DodecahedronCircumradius();

            dodMesh.ApplyTransformation(new ScaleTransform3D(dodScale, dodScale, dodScale));
            dodMesh.ApplyTransformation(
                new TranslateTransform3D(center.X, center.Y + 0.5, center.Z));
            mesh3.Merge(dodMesh);
            center.X += 2;

            // Frustum.
            polygon = G3.MakePolygonPoints(5, center, D3.XVector(1), D3.ZVector(-1));
            mesh1.AddFrustum(center, polygon, D3.YVector(4), 2);
            center.X += 2;

            // Icosahedron.
            MeshGeometry3D icoMesh = new MeshGeometry3D();

            icoMesh.AddIcosahedron();
            double icoScale = 1 / G3.IcosahedronCircumradius();

            icoMesh.ApplyTransformation(new ScaleTransform3D(icoScale, icoScale, icoScale));
            icoMesh.ApplyTransformation(
                new TranslateTransform3D(center.X, center.Y + 0.5, center.Z));
            mesh3.Merge(icoMesh);
            center.X += 2;

            // Octahedron.
            MeshGeometry3D octMesh = new MeshGeometry3D();

            octMesh.AddOctahedron();
            double octScale = 1 / G3.OctahedronCircumradius();

            octMesh.ApplyTransformation(new ScaleTransform3D(octScale, octScale, octScale));
            octMesh.ApplyTransformation(
                new TranslateTransform3D(center.X, center.Y + 0.5, center.Z));
            mesh3.Merge(octMesh);
            center.X += 2;

            // Pyramid.
            polygon = G3.MakePolygonPoints(6, center, D3.XVector(1), D3.ZVector(-1));
            mesh1.AddPyramid(center, polygon, D3.YVector(3));
            center.X += 2;

            // Start a new row.
            center.X  = x0;
            center.Z -= 3;

            // Sphere.
            mesh1.AddSphere(center + new Vector3D(0, 1, 0), 1, 20, 10);
            center.X += 2;

            // Tetrahedron.
            MeshGeometry3D tetMesh = new MeshGeometry3D();

            tetMesh.AddTetrahedron();
            double tetScale = 1 / G3.TetrahedronCircumradius();

            tetMesh.ApplyTransformation(new ScaleTransform3D(tetScale, tetScale, tetScale));
            tetMesh.ApplyTransformation(
                new TranslateTransform3D(center.X, center.Y + 0.5, center.Z));
            mesh3.Merge(tetMesh);
            center.X += 2;

            // Textured sphere.
            mesh4.Positions.Add(new Point3D());
            mesh4.TextureCoordinates.Add(new Point(1.01, 1.01));
            mesh4.AddTexturedSphere(center + new Vector3D(0, 1, 0), 1, 20, 10);
            center.X += 2;

            // Textured torus.
            mesh4.AddTexturedTorus(center + new Vector3D(0, 1, 0), 0.6, 0.4, 30, 15);
            center.X += 2;

            // Torus.
            mesh1.AddTorus(center + new Vector3D(0, 1, 0), 0.6, 0.4, 30, 15);
            center.X += 2;

            // Start a new row.
            center.X  = x0;
            center.Z -= 3;

            group.Children.Add(mesh1.MakeModel(Brushes.LightGreen));
            group.Children.Add(mesh2.MakeModel("wrapper.png"));
            group.Children.Add(mesh3.MakeModel(Brushes.LightBlue));
            group.Children.Add(mesh4.MakeModel("world.jpg"));
        }
        // Define the model.
        private void DefineModel()
        {
            // Axes.
            //MainGroup.Children.Add(MeshExtensions.XAxisModel(4, 0.1));
            //MainGroup.Children.Add(MeshExtensions.YAxisModel(4, 0.1));
            //MainGroup.Children.Add(MeshExtensions.ZAxisModel(4, 0.1));
            //MainGroup.Children.Add(MeshExtensions.OriginModel(0.12));

            // Make the ground.
            MeshGeometry3D groundMesh = new MeshGeometry3D();
            const double   dx         = 4;
            const double   dy         = 1;
            const double   dz         = dx;
            const double   groundY    = -2;
            Point3D        corner     = new Point3D(-dx / 2, groundY - dy, -dz / 2);

            Point[] topCoords =
            {
                new Point(0,   0),
                new Point(0,  dz),
                new Point(dx, dz),
                new Point(dx,  0),
            };
            Point[] sideCoords =
            {
                new Point(0,   0),
                new Point(0,  dz),
                new Point(dy, dz),
                new Point(dy,  0),
            };
            groundMesh.AddBox(corner, D3.XVector(dx), D3.YVector(dy), D3.ZVector(dz),
                              sideCoords, sideCoords, sideCoords, sideCoords, topCoords, topCoords);
            MainGroup.Children.Add(groundMesh.MakeModel("metal.jpg"));

            // This group represents the whole robot.
            RobotGroup = new Model3DGroup();
            MainGroup.Children.Add(RobotGroup);

            // Base.
            const double   baseWidth  = 0.4;
            const double   baseLength = 2.5;
            MeshGeometry3D baseMesh   = new MeshGeometry3D();

            baseMesh.AddBox(new Point3D(-baseWidth / 2, 0, -baseWidth / 2),
                            D3.XVector(baseWidth), D3.YVector(baseLength), D3.ZVector(baseWidth));
            GeometryModel3D baseModel = baseMesh.MakeModel(Brushes.Pink);

            const int    numCyl       = 20;
            const double bJointWidth  = 0.5;
            const double bJointRadius = 0.5;

            Point3D[] bPgon = G3.MakePolygonPoints(numCyl, new Point3D(0, 0, 0),
                                                   D3.XVector(bJointRadius), D3.ZVector(-bJointRadius));
            baseMesh.AddCylinder(bPgon, D3.YVector(bJointWidth), true);

            BaseGroup = JoinBones(RobotGroup, new TranslateTransform3D(0, groundY, 0));
            BaseGroup.Children.Add(baseModel);

            // Shoulder.
            const double   shoulderWidth  = 0.4;
            const double   shoulderLength = 2;
            MeshGeometry3D shoulderMesh   = new MeshGeometry3D();

            shoulderMesh.AddBox(new Point3D(-shoulderWidth / 2, 0, -shoulderWidth / 2),
                                D3.XVector(shoulderWidth), D3.YVector(shoulderLength), D3.ZVector(shoulderWidth));

            const double sJointWidth  = 0.5;
            const double sJointRadius = 0.4;

            Point3D[] sPgon = G3.MakePolygonPoints(numCyl, new Point3D(0, 0, -sJointWidth / 2),
                                                   D3.XVector(sJointRadius), D3.YVector(sJointRadius));
            shoulderMesh.AddCylinder(sPgon, D3.ZVector(sJointWidth), true);
            GeometryModel3D shoulderModel = shoulderMesh.MakeModel(Brushes.LightGreen);

            ShoulderGroup = JoinBones(BaseGroup, new TranslateTransform3D(0, baseLength, 0));
            ShoulderGroup.Children.Add(shoulderModel);

            // Elbow.
            const double   elbowWidth  = 0.4;
            const double   elbowLength = 1.5;
            MeshGeometry3D elbowMesh   = new MeshGeometry3D();

            elbowMesh.AddBox(new Point3D(-elbowWidth / 2, 0, -elbowWidth / 2),
                             D3.XVector(elbowWidth), D3.YVector(elbowLength), D3.ZVector(elbowWidth));

            const double eJointWidth  = 0.5;
            const double eJointRadius = 0.4;

            Point3D[] ePgon = G3.MakePolygonPoints(numCyl, new Point3D(0, 0, -eJointWidth / 2),
                                                   D3.XVector(eJointRadius), D3.YVector(eJointRadius));
            elbowMesh.AddCylinder(ePgon, D3.ZVector(eJointWidth), true);
            GeometryModel3D elbowModel = elbowMesh.MakeModel(Brushes.LightBlue);

            ElbowGroup = JoinBones(ShoulderGroup, new TranslateTransform3D(0, shoulderLength, 0));
            ElbowGroup.Children.Add(elbowModel);

            // Wrist.
            const double   wDx       = 1.5;
            const double   wDy       = 0.2;
            const double   wDz       = 0.4;
            MeshGeometry3D wristMesh = new MeshGeometry3D();

            wristMesh.AddBox(new Point3D(-wDx / 2, 0, -wDz / 2),
                             D3.XVector(wDx), D3.YVector(wDy), D3.ZVector(wDz));

            const double wJointRadius = 0.3;

            Point3D[] wPgon = G3.MakePolygonPoints(numCyl, new Point3D(0, -wDy / 2, 0),
                                                   D3.XVector(wJointRadius), D3.ZVector(-wJointRadius));
            wristMesh.AddCylinder(wPgon, D3.YVector(wDy), true);
            GeometryModel3D wristModel = wristMesh.MakeModel(Brushes.Red);

            WristGroup = JoinBones(ElbowGroup, new TranslateTransform3D(0, elbowLength, 0));
            WristGroup.Children.Add(wristModel);

            // Finger 1.
            const double   fDx         = 0.1;
            const double   fDy         = 0.5;
            const double   fDz         = 0.2;
            MeshGeometry3D finger1Mesh = new MeshGeometry3D();

            finger1Mesh.AddBox(new Point3D(-fDx / 2, 0, -fDz / 2),
                               D3.XVector(fDx), D3.YVector(fDy), D3.ZVector(fDz));
            GeometryModel3D finger1Model = finger1Mesh.MakeModel(Brushes.Green);

            Finger1Group = JoinBones(WristGroup, new TranslateTransform3D(-fDx / 2, wDy, 0));
            Finger1Group.Children.Add(finger1Model);

            // Finger 2.
            MeshGeometry3D finger2Mesh = new MeshGeometry3D();

            finger2Mesh.AddBox(new Point3D(-fDx / 2, 0, -fDz / 2),
                               D3.XVector(fDx), D3.YVector(fDy), D3.ZVector(fDz));
            GeometryModel3D finger2Model = finger2Mesh.MakeModel(Brushes.Green);

            Finger2Group = JoinBones(WristGroup, new TranslateTransform3D(fDx / 2, wDy, 0));
            Finger2Group.Children.Add(finger2Model);
        }
Exemplo n.º 4
0
        /// Define the model.
        void DefineModelRobot()
        {
            Width  = 450;
            Height = 700;

            // Axes.
            MeshExtensions.AddXAxis(_group, 15, 0.1); // red = x
            MeshExtensions.AddYAxis(_group, 12, 0.1); // green = y
            MeshExtensions.AddZAxis(_group, 15, 0.1); // blue = z
            MeshExtensions.AddOrigin(_group, 0.5);    // black

            // Make the ground.
            const double groundY = -5;

            MakeGround(groundY);

            // Various robot dimensions.
            const double headR     = 1.5;            // Head radius.
            const double neckLen   = headR;          // Neck length.
            const double backLen   = 3 * headR;      // Back length.
            const double shouW     = 3 * headR;      // Shoulder width.
            const double uaLen     = 2 * headR;      // Upper arm length.
            const double laLen     = 2 * headR;      // Lower arm length
            const double hipsW     = 2 * headR;      // Hip width.
            const double ulLen     = 2 * headR;      // Upper leg length.
            const double llLen     = 2 * headR;      // Lower leg length.
            const double boneR     = 0.3;            // Bone radius.
            const double jointR    = 0.4;            // Joint radius.
            const double height    = 2 * headR + neckLen + backLen + ulLen + llLen;
            const double headY     = height - headR; // Distance from center of head to ground.
            Brush        boneBrush = Brushes.PowderBlue;

            // This group represents the whole robot.
            _groupRobot = new Model3DGroup();
            _group.Children.Add(_groupRobot);
            _groupRobot.Transform = new TranslateTransform3D(0, headY + groundY, 0);

            // Head.
            // Skull.
            MeshGeometry3D skullMesh = new MeshGeometry3D();

            skullMesh.AddSphere(D3.Origin, headR, 20, 10, true);
            GeometryModel3D skullModel = skullMesh.MakeModel(boneBrush);

            // Nose.
            MeshGeometry3D noseMesh   = new MeshGeometry3D();
            Point3D        noseCenter = new Point3D(0, 0, headR);

            Point3D[] nosePoints = G3.MakePolygonPoints(10, noseCenter, D3.XVector(headR * 0.2), D3.YVector(headR * 0.2));
            Vector3D  noseAxis   = new Vector3D(0, 0, headR);

            noseMesh.AddConeFrustum(noseCenter, nosePoints, noseAxis, headR * 0.5);
            GeometryModel3D noseModel = noseMesh.MakeModel(Brushes.Orange);

            // Eyes and smile.
            MeshGeometry3D eyeMesh   = new MeshGeometry3D();
            Point3D        eyeCenter = SphericalToCartesian(headR, -Math.PI * 0.2, Math.PI * 0.4);

            eyeMesh.AddSphere(eyeCenter, headR * 0.2, 10, 5, false);
            eyeCenter = SphericalToCartesian(headR, Math.PI * 0.2, Math.PI * 0.4);
            eyeMesh.AddSphere(eyeCenter, headR * 0.2, 10, 5, false);
            eyeCenter = SphericalToCartesian(headR, Math.PI * 0, Math.PI * 0.7);
            eyeMesh.AddSphere(eyeCenter, headR * 0.1, 10, 5, false);
            eyeCenter = SphericalToCartesian(headR, Math.PI * 0.1, Math.PI * 0.67);
            eyeMesh.AddSphere(eyeCenter, headR * 0.1, 10, 5, false);
            eyeCenter = SphericalToCartesian(headR, -Math.PI * 0.1, Math.PI * 0.67);
            eyeMesh.AddSphere(eyeCenter, headR * 0.1, 10, 5, false);
            eyeCenter = SphericalToCartesian(headR, Math.PI * 0.15, Math.PI * 0.6);
            eyeMesh.AddSphere(eyeCenter, headR * 0.1, 10, 5, false);
            eyeCenter = SphericalToCartesian(headR, -Math.PI * 0.15, Math.PI * 0.6);
            eyeMesh.AddSphere(eyeCenter, headR * 0.1, 10, 5, false);
            GeometryModel3D eyeModel = eyeMesh.MakeModel(Brushes.Black);

            // Hat.
            MeshGeometry3D hatMesh   = new MeshGeometry3D();
            Point3D        hatCenter = new Point3D(0, headR * 0.75, 0);

            hatMesh.AddSphere(hatCenter, headR * 0.75, 20, 10, true);
            const double hatR = headR * 1.2;

            Point3D[] hatPgon = G3.MakePolygonPoints(20, hatCenter, D3.XVector(hatR), D3.ZVector(hatR));
            hatMesh.AddCylinder(hatPgon, D3.YVector(-0.2), true);

            GeometryModel3D hatModel = hatMesh.MakeModel(Brushes.SaddleBrown);

            // Head groups.
            _groupHead = JoinBones(_groupRobot, null);
            _groupHead.Children.Add(skullModel);
            _groupHead.Children.Add(noseModel);
            _groupHead.Children.Add(eyeModel);
            _groupHead.Children.Add(hatModel);

            // Neck.
            MeshGeometry3D neckMesh = new MeshGeometry3D();

            Point3D[] neckPgon = G3.MakePolygonPoints(10, D3.Origin, D3.XVector(boneR), D3.ZVector(boneR));
            neckMesh.AddCylinder(neckPgon, D3.YVector(-neckLen), true);
            GeometryModel3D neckModel = neckMesh.MakeModel(boneBrush);

            _groupNeck = JoinBones(_groupHead, new TranslateTransform3D(0, -headR, 0));
            _groupNeck.Children.Add(neckModel);

            // Shoulders.
            MeshGeometry3D shoulderMesh = new MeshGeometry3D();

            Point3D[] shouldersPgon = G3.MakePolygonPoints(10, new Point3D(-shouW / 2, 0, 0), D3.ZVector(boneR), D3.YVector(-boneR));
            shoulderMesh.AddCylinder(shouldersPgon, D3.XVector(shouW), true);
            GeometryModel3D shoulderModel = shoulderMesh.MakeModel(boneBrush);

            _groupShoulder = JoinBones(_groupNeck, new TranslateTransform3D(0, -neckLen, 0));
            _groupShoulder.Children.Add(shoulderModel);

            // Left upper arm.
            MeshGeometry3D luArmMesh = new MeshGeometry3D();

            luArmMesh.AddCylinder(neckPgon, D3.YVector(-uaLen), true);
            luArmMesh.AddSphere(D3.Origin, jointR, 10, 5, true);
            GeometryModel3D luArmModel = luArmMesh.MakeModel(boneBrush);

            _groupLeftUpperArm = JoinBones(_groupShoulder, new TranslateTransform3D(shouW / 2, 0, 0));
            _groupLeftUpperArm.Children.Add(luArmModel);

            // Right upper arm.
            MeshGeometry3D ruArmMesh = new MeshGeometry3D();

            ruArmMesh.AddCylinder(neckPgon, D3.YVector(-uaLen), true);
            ruArmMesh.AddSphere(D3.Origin, jointR, 10, 5, true);
            GeometryModel3D ruArmModel = ruArmMesh.MakeModel(boneBrush);

            _groupRightUpperArm = JoinBones(_groupShoulder, new TranslateTransform3D(-shouW / 2, 0, 0));
            _groupRightUpperArm.Children.Add(ruArmModel);

            // Left lower arm.
            MeshGeometry3D llArmMesh = new MeshGeometry3D();

            llArmMesh.AddCylinder(neckPgon, D3.YVector(-laLen), true);
            llArmMesh.AddSphere(D3.Origin, jointR, 10, 5, true);
            GeometryModel3D llArmModel = llArmMesh.MakeModel(boneBrush);

            _groupLeftLowerArm = JoinBones(_groupLeftUpperArm, new TranslateTransform3D(0, -uaLen, 0));
            _groupLeftLowerArm.Children.Add(llArmModel);

            // Right lower arm.
            MeshGeometry3D rlArmMesh = new MeshGeometry3D();

            rlArmMesh.AddCylinder(neckPgon, D3.YVector(-laLen), true);
            rlArmMesh.AddSphere(D3.Origin, jointR, 10, 5, true);
            GeometryModel3D rlArmModel = rlArmMesh.MakeModel(boneBrush);

            _groupRightLowerArm = JoinBones(_groupRightUpperArm, new TranslateTransform3D(0, -uaLen, 0));
            _groupRightLowerArm.Children.Add(rlArmModel);

            // Back and hips.
            MeshGeometry3D backMesh = new MeshGeometry3D();

            backMesh.AddCylinder(neckPgon, D3.YVector(-backLen), true);
            GeometryModel3D backModel = backMesh.MakeModel(boneBrush);

            MeshGeometry3D hipsMesh = new MeshGeometry3D();

            Point3D[] hipsPgon = G3.MakePolygonPoints(10, new Point3D(-hipsW / 2, -backLen, 0), D3.ZVector(boneR), D3.YVector(-boneR));
            hipsMesh.AddCylinder(hipsPgon, D3.XVector(hipsW), true);
            GeometryModel3D hipsModel = hipsMesh.MakeModel(boneBrush);

            _groupBack = JoinBones(_groupNeck, new TranslateTransform3D(0, -neckLen, 0));
            _groupBack.Children.Add(backModel);
            _groupBack.Children.Add(hipsModel);

            // Left upper leg.
            MeshGeometry3D luLegMesh = new MeshGeometry3D();

            luLegMesh.AddCylinder(neckPgon, D3.YVector(-ulLen), true);
            luLegMesh.AddSphere(D3.Origin, jointR, 10, 5, true);
            GeometryModel3D luLegModel = luLegMesh.MakeModel(boneBrush);

            _groupLeftUpperLeg = JoinBones(_groupBack, new TranslateTransform3D(-hipsW / 2, -backLen, 0));
            _groupLeftUpperLeg.Children.Add(luLegModel);

            // Right upper leg.
            MeshGeometry3D ruLegMesh = new MeshGeometry3D();

            ruLegMesh.AddCylinder(neckPgon, D3.YVector(-ulLen), true);
            ruLegMesh.AddSphere(D3.Origin, jointR, 10, 5, true);
            GeometryModel3D ruLegModel = ruLegMesh.MakeModel(boneBrush);

            _groupRightUpperLeg = JoinBones(_groupBack, new TranslateTransform3D(hipsW / 2, -backLen, 0));
            _groupRightUpperLeg.Children.Add(ruLegModel);

            // Left lower leg.
            MeshGeometry3D llLegMesh = new MeshGeometry3D();

            llLegMesh.AddCylinder(neckPgon, D3.YVector(-llLen), true);
            llLegMesh.AddSphere(D3.Origin, jointR, 10, 5, true);
            GeometryModel3D llLegModel = llLegMesh.MakeModel(boneBrush);

            _groupLeftLowerLeg = JoinBones(_groupLeftUpperLeg, new TranslateTransform3D(0, -ulLen, 0));
            _groupLeftLowerLeg.Children.Add(llLegModel);

            // Right lower leg.
            MeshGeometry3D rlLegMesh = new MeshGeometry3D();

            rlLegMesh.AddCylinder(neckPgon, D3.YVector(-llLen), true);
            rlLegMesh.AddSphere(D3.Origin, jointR, 10, 5, true);
            GeometryModel3D rlLegModel = rlLegMesh.MakeModel(boneBrush);

            _groupRightLowerLeg = JoinBones(_groupRightUpperLeg, new TranslateTransform3D(0, -ulLen, 0));
            _groupRightLowerLeg.Children.Add(rlLegModel);
        }
        // Define the model.
        private void DefineModel(Model3DGroup group)
        {
            // Define a polygon in the XZ plane.
            Point3D center = new Point3D(0, -1.5, 2);

            Point3D[] polygon = G3.MakePolygonPoints(20, center,
                                                     new Vector3D(0.5, 0, 0), new Vector3D(0, 0, -0.5));

            // Transform to move the polygon.
            TranslateTransform3D xTranslate = new TranslateTransform3D(-2, 0, 0);

            // Make a transform to move the polygon in the -Z direction.
            TranslateTransform3D xzTranslate = new TranslateTransform3D(2, 0, -2);

            // Make a smooth skewed cylinder.
            MeshGeometry3D mesh1 = new MeshGeometry3D();

            mesh1.AddCylinder(polygon, new Vector3D(0, 2, -1), true);
            group.Children.Add(mesh1.MakeModel(Brushes.Pink));

            // Make a skewed cylinder.
            MeshGeometry3D mesh2 = new MeshGeometry3D();

            xTranslate.Transform(polygon);
            mesh2.AddCylinder(polygon, new Vector3D(0, 3, -1));
            group.Children.Add(mesh2.MakeModel(Brushes.Pink));

            // Make a smooth right cylinder.
            MeshGeometry3D mesh3 = new MeshGeometry3D();

            xzTranslate.Transform(polygon);
            mesh3.AddCylinder(polygon, new Vector3D(0, 2, 0), true);
            group.Children.Add(mesh3.MakeModel(Brushes.LightGreen));

            // Make a right cylinder.
            MeshGeometry3D mesh4 = new MeshGeometry3D();

            xTranslate.Transform(polygon);
            mesh4.AddCylinder(polygon, new Vector3D(0, 3, 0));
            group.Children.Add(mesh4.MakeModel(Brushes.LightGreen));

            // Make a cylinder defined by cutting planes.
            MeshGeometry3D mesh5 = new MeshGeometry3D();

            xzTranslate.Transform(polygon);
            mesh5.AddCylinder(polygon, new Vector3D(0, 3, 0),
                              center + new Vector3D(0, 1, 0), new Vector3D(0, 2, 1),
                              center + new Vector3D(0, -0.5, 0), new Vector3D(1, -1, 0),
                              true);
            group.Children.Add(mesh5.MakeModel(Brushes.LightBlue));

            // Make a smooth cylinder defined by cutting planes.
            MeshGeometry3D mesh6 = new MeshGeometry3D();

            xTranslate.Transform(polygon);
            mesh6.AddCylinder(polygon, new Vector3D(0, 3, 0),
                              center + new Vector3D(0, 2, 0), new Vector3D(0, 2, 1),
                              center + new Vector3D(0, -0.5, 0), new Vector3D(1, -1, 0));
            group.Children.Add(mesh6.MakeModel(Brushes.LightBlue));

            // Show the axes.
            MeshExtensions.AddAxes(group);
        }
        // Draw a branch in the indicated direction.
        private void DrawBranch(MeshGeometry3D mesh,
                                int depth, double length, double radius, double angle,
                                double lengthFactor, double radiusFactor, int numBranches,
                                Point3D startPoint, Vector3D axis, int numSides)
        {
            // Set the branch's length.
            axis = axis.Scale(length);

            // Get two vectors perpendicular to the axis.
            Vector3D v1;

            if (Vector3D.AngleBetween(axis, D3.ZVector()) > 0.1)
            {
                v1 = Vector3D.CrossProduct(axis, D3.ZVector());
            }
            else
            {
                v1 = Vector3D.CrossProduct(axis, D3.XVector());
            }
            Vector3D v2 = Vector3D.CrossProduct(axis, v1);

            v1 = v1.Scale(radius);
            v2 = v2.Scale(radius);

            // Make the cone's base.
            Point3D[] pgon = G3.MakePolygonPoints(numSides, startPoint, v1, v2);

            // Make the branch.
            mesh.AddCylinder(pgon, axis, true);

            // Draw child branches.
            if (depth <= 0)
            {
                return;
            }

            // Move to the end of this segment.
            depth--;
            startPoint += axis;
            length     *= lengthFactor;
            if (length < 0.01)
            {
                length = 0.01;
            }
            radius *= radiusFactor;
            if (radius < 0.001)
            {
                radius = 0.001;
            }

            // Find child vectors.
            List <Vector3D> children = axis.MakeFlowerVectors(
                D3.YVector(), D3.ZVector(), angle, numBranches);

            // Draw the child branches.
            foreach (Vector3D child in children)
            {
                DrawBranch(mesh, depth, length,
                           radius, angle, lengthFactor, radiusFactor, numBranches,
                           startPoint, child, numSides);
            }
        }