Esempio n. 1
0
        private void AppendBranch(Matrix transform, int parentId, float lengthScale, float radiusScale, int level)
        {
            if (level <= 0)
            {
                return; // Do nothing, this branch is invisible.
            }
            Branch branch = branches[parentId];

            // Add this branch
            float length = lengthScale * GetFloatFromValueRange(branch.length, seed++);

            float radius = GetFloatFromValueRange(branch.radius, seed++);

            float radiusEndScale = radiusScale * GetFloatFromValueRange(branch.radiusEnd, seed++);

            float radiusEnd = radius * radiusEndScale;

            radius = radiusScale * radius;

            if (level == 1)
            {
                radiusEnd = 0.0f;
            }

            int radialSegments = (level * (this.radialSegments - 3)) / levels + 3;

            if (level > cutoffLevel)
            {
                MeshUtil.BuildCylinder(
                    treeVertices,
                    treeIndices,
                    ref boundingBox,

                    length,
                    radius,
                    radiusEnd,
                    radialSegments,

                    transform,
                    0.0f,
                    1.0f);
            }

            // Add children
            if (level > 1)
            {
                for (int childN = 0; childN < branch.children.Count; childN++)
                {
                    BranchChild child = branch.children[childN];

                    int childBranchId = GetBranchIndexFromId(child.idRef);

                    if (childBranchId == -1)
                    {
                        continue;
                    }

                    Branch childBranch = branches[childBranchId];

                    if (!IsValueInRange(child.levelRange, level))
                    {
                        continue;
                    }

                    int childLevel = level + GetIntFromValueRange(child.relativeLevel, seed++);   // RelativeLevel is usually negative, -1 in particular.

                    int numChildren = GetIntFromValueRange(child.count, seed++);

                    float positionRange = child.position.max - child.position.min;

                    positionRange /= (float)numChildren;

                    float orientation = GetRandomFloat(seed++, 0, 360.0f);

                    for (int i = 0; i < numChildren; i++)
                    {
                        float childLengthScale = lengthScale * GetFloatFromValueRange(child.lengthScale, seed++);

                        orientation += GetFloatFromValueRange(child.orientation, seed++);

                        // Clamp value between 0 and 360.
                        if (orientation < 0.0f)
                        {
                            orientation += 360.0f;
                        }
                        else
                        if (orientation > 360.0f)
                        {
                            orientation -= 360.0f;
                        }

                        float childOrientation = orientation;

                        float gravity = GetFloatFromValueRange(child.gravityInfluence, seed++);

                        float childPitch = GetFloatFromValueRange(child.pitch, seed++);

                        float childPosition = GetFloatFromValueRange(child.position, seed++);

                        float position;

                        if (child.position.isFixedValue)
                        {
                            position = child.position.min;
                        }
                        else
                        {
                            position = (child.position.min + positionRange * i + positionRange * GetRandomFloat(seed++, 0f, 1f));
                        }

                        float childRadiusScale = (radiusScale * (1.0f - position) + radiusEndScale * position) * GetFloatFromValueRange(child.radiusScale, seed++);

                        // Build transformation matrix
                        Matrix mat =
                            Matrix.CreateRotationX(MathHelper.ToRadians(childPitch))
                            * Matrix.CreateRotationY(MathHelper.ToRadians(childOrientation));

                        // Set the Y translation
                        mat.M42 = length * position;

                        // Transform by the branch transformation
                        mat = mat * transform;

                        if (gravity != 0.0f)
                        {
                            // Do some extra work

                            // Get a vector pointing downwards (towards gravity's pull)
                            Vector3 vDown = -Vector3.UnitY;

                            // Get a vector pointing in the branch's direction, by rotating the Y unit vector.
                            Vector3 vBranch = mat.Up;

                            Vector3 vSide;

                            if (Math.Abs(vBranch.Y) >= 0.9f)
                            {
                                // The X unit vector should suffice as side vector if rotated by the matrix.
                                vSide = mat.Right; //Vector3.TransformNormal(Vector3.UnitX, mat);
                            }
                            else
                            {
                                // Use the cross product to find a suitable sideways vector
                                vSide = Vector3.Cross(vBranch, vDown);
                                vSide.Normalize();
                            }

                            vDown = Vector3.Cross(vSide, vBranch);
                            vDown.Normalize();

                            mat.Right    = vSide;
                            mat.Backward = vDown;

                            float dot = -vBranch.Y;

                            if (gravity < 0.0f)
                            {
                                dot = -dot;
                            }

                            float angle = (float)Math.Acos(dot);

                            angle *= gravity;

                            // Bend the branch around the X-axis.
                            Matrix mat2 = Matrix.CreateRotationX(angle);

                            mat = mat2 * mat;
                        }

                        // Add the branch
                        AppendBranch(mat, childBranchId, childLengthScale, childRadiusScale, childLevel);
                    }
                }
            }

            // Add leaves
            if (addLeaves)
            {
                for (int leafN = 0; leafN < branch.leaves.Count; leafN++)
                {
                    Leaf leaf = branch.leaves[leafN];

                    if (!IsValueInRange(leaf.levelRange, level))
                    {
                        continue;
                    }

                    int count = GetIntFromValueRange(leaf.count, leafSeed++);

                    for (int i = 0; i < count; i++)
                    {
                        float width    = GetFloatFromValueRange(leaf.width, leafSeed++);
                        float height   = GetFloatFromValueRange(leaf.height, leafSeed++);
                        float scale    = GetFloatFromValueRange(leaf.scale, leafSeed++);
                        float position = GetFloatFromValueRange(leaf.position, leafSeed++);
                        float roll     = GetFloatFromValueRange(leaf.roll, leafSeed++);
                        float anchor   = GetFloatFromValueRange(leaf.anchor, leafSeed++);

                        Matrix mat = Matrix.Identity;

                        mat.M42 = length * position;

                        mat = mat * transform;

                        Vector3 leafPos = mat.Translation;

                        Color color = new Color(
                            (byte)GetIntFromValueRange(leaf.red, leafSeed++),
                            (byte)GetIntFromValueRange(leaf.green, leafSeed++),
                            (byte)GetIntFromValueRange(leaf.blue, leafSeed++),
                            (byte)GetIntFromValueRange(leaf.alpha, leafSeed++));

                        //Console.WriteLine("Color = " + color.R + ", " + color.G + ", " + color.B + ", " + color.A);

                        if (leaf.hasAxis)
                        {
                            cloud.AxisEnabled = true;
                            cloud.Axis        = leaf.axis;
                            leafPos          += leaf.axis * height * scale * anchor / 2.0f;
                        }

                        cloud.AddParticle(leafPos, color, roll, new Vector2(width, height));
                    }
                }
            }
        }
Esempio n. 2
0
        private bool LoadXmlBranchChild(XmlNode node, List <BranchChild> children)
        {
            BranchChild child = BranchChild.Create();

            child.idRef = GetIntAttribute(node, "ref", -1);

            // Must have a valid branch reference id
            if (child.idRef < 0)
            {
                return(false);
            }

            // Get the relative level short-hand from the attribute (if available)
            AssignValueRange(node, "level", ref child.relativeLevel);

            // Let all subelements apply to the new branch type
            for (int i = 0; i < node.ChildNodes.Count; i++)
            {
                XmlNode childnode = node.ChildNodes[i];
                switch (childnode.Name)
                {
                case "relativeLevel":
                    AssignValueRange(childnode, ref child.relativeLevel);
                    break;

                case "levelRange":
                    AssignValueRange(childnode, ref child.levelRange);
                    break;

                case "position":
                    AssignValueRange(childnode, ref child.position);
                    break;

                case "lengthScale":
                    AssignValueRange(childnode, ref child.lengthScale);
                    break;

                case "radiusScale":
                    AssignValueRange(childnode, ref child.radiusScale);
                    break;

                case "orientation":
                    AssignValueRange(childnode, ref child.orientation);
                    break;

                case "pitch":
                    AssignValueRange(childnode, ref child.pitch);
                    break;

                case "gravity":
                    AssignValueRange(childnode, ref child.gravityInfluence);
                    break;

                case "count":
                    AssignValueRange(childnode, ref child.count);
                    break;
                }
            }

            // Add the branchchild to the array
            children.Add(child);

            return(true);
        }