コード例 #1
0
        /**
         * Gives a clone a new direction (splitting)
         *
         * @param trf The base transformation of the clone
         * @param s_angle The splitting angle
         * @param nseg The segment number, where the clone begins
         * @param nsplits The number of clones
         * @return The new direction for the clone
         */

        DX_Transformation split(DX_Transformation trf,
                                float s_angle, int nseg, int nsplits)
        {
            // applies a split angle to the stem - the Weber/Penn method
            int remaining_seg = segmentCount - nseg - 1;

            // the splitangle
            // FIXME: don't know if it should be nSplitAngle or nSplitAngle/2
            float declination = (float)(Math.Acos(trf.getZ3().Z) * 180 / Math.PI);
            float split_angle = Math.Max(0, (lpar.nSplitAngle
                                             + lpar.var(lpar.nSplitAngleV) - declination));

            // FIXME: first works better for level 0, second for further levels
            // transf = transf.rotxz(split_angle,s_angle)
            trf = trf.rotx(split_angle);

            // adapt split correction
            splitCorrection -= split_angle / remaining_seg;
            //t_corr = Transformation().rotx(-split_angle/remaining_seg)

            float split_diverge;

            if (s_angle > 0)
            { // original stem has s_angle==0
                if (par._0BaseSplits > 0 && stemlevel == 0 && nseg == 0)
                {
                    split_diverge = s_angle + lpar.var(lpar.nSplitAngleV);
                }
                else
                {
                    split_diverge = (float)(20 + 0.75 * (30 + Math.Abs(declination - 90))
                                            * Math.Pow((lpar.var(1) + 1) / 2.0, 2));
                    if (lpar.var(1) >= 0)
                    {
                        split_diverge = -split_diverge;
                    }
                }

                trf = trf.rotaxis(split_diverge, DX_Transformation.Z_AXIS);
            }
            else
            {
                split_diverge = 0;  // for debugging only
            }
            // adjust some parameters
            //split_cnt = split_cnt+1;

            // lower substem prospensity
            if (!pruneTest)
            {
                substemsPerSegment /= (float)(nsplits + 1);
                // FIXME: same reduction for leaves_per_segment?
            }
            return(trf);
        }
コード例 #2
0
        /**
         *	Leaf rotation toward light
         */
        private void setLeafOrientation(CS_Params par)
        {
            if (par.LeafBend == 0)
            {
                return;
            }

            // FIXME: make this function as fast as possible - a tree has a lot of leafs

            // rotation outside
            Vector3 pos = transf.getT();
            // the z-vector of transf is parallel to the
            // axis of the leaf, the y-vector is the normal
            // (of the upper side) of the leaf
            Vector3 norm = transf.getY3();

            float tpos  = (float)(Math.Atan2(pos.Y, pos.X) * 180 / Math.PI);
            float tbend = tpos - (float)(Math.Atan2(norm.Y, norm.X) * 180 / Math.PI);;
            // if (tbend>180) tbend = 360-tbend;

            float bend_angle = par.LeafBend * tbend;

            // transf = transf.rotz(bend_angle);
            // rotate about global z-axis
            transf = transf.rotaxis(bend_angle, DX_Transformation.Z_AXIS);

            // rotation up
            norm = transf.getY3();
            float fbend = (float)(Math.Atan2((float)Math.Sqrt(norm.X * norm.X + norm.Y * norm.Y), norm.Z) * 180 / Math.PI);

            bend_angle = par.LeafBend * fbend;

            transf = transf.rotx(bend_angle);

            //		this is from the paper, but is equivalent with
            //      local x-rotation (upper code line)
            //
            //		double orientation = Vector.atan2(norm.getY(),norm.getX());
            //		transf = transf
            //			.rotaxis(-orientation,Vector.Z_AXIS)
            //			.rotx(bend_angle)
            //			.rotaxis(orientation,Vector.Z_AXIS);
        }
コード例 #3
0
        /**
         * Calcs a new direction for the current segment
         *
         * @param trf The transformation of the previous segment
         * @param nsegm The number of the segment ( for testing, if it's the
         *              first stem segment
         * @return The new transformation of the current segment
         */

        DX_Transformation newDirection(DX_Transformation trf, int nsegm)
        {
            // next segments direction

            // The first segment shouldn't get another direction
            // down and rotation angle shouldn't be falsified
            if (nsegm == 0)
            {
                return(trf);
            }

            /*
             * if (Console.debug())
             *  TRF("Stem.new_direction() before curving",trf);
             */

            // get curving angle
            double delta;

            if (lpar.nCurveBack == 0)
            {
                delta = lpar.nCurve / lpar.nCurveRes;
            }
            else
            {
                if (nsegm < (lpar.nCurveRes + 1) / 2)
                {
                    delta = lpar.nCurve * 2 / lpar.nCurveRes;
                }
                else
                {
                    delta = lpar.nCurveBack * 2 / lpar.nCurveRes;
                }
            }
            delta += splitCorrection;

            /*
             * if (Console.debug())
             *  DBG("Stem.new_direction(): delta: "+delta);
             */

            trf = trf.rotx(delta);


            // With Weber/Penn the orientation of the x- and y-axis
            // shouldn't be disturbed (maybe, because proper curving relies on this)
            // so may be such random rotations shouldn't be used, instead nCurveV should
            // add random rotation to rotx, and rotate nCurveV about the tree's z-axis too?

            // add random rotation about z-axis
            if (lpar.nCurveV > 0)
            {
                //          if (nsegm==0 && stemlevel==0) { // first_trunk_segment
                //              // random rotation more moderate
                //              delta = (Math.abs(lpar.var(lpar.nCurveV)) -
                //                      Math.abs(lpar.var(lpar.nCurveV)))
                //						/ lpar.nCurveRes;
                //          }	else {
                // full random rotation
                delta = lpar.var(lpar.nCurveV) / lpar.nCurveRes;
                //          }
                // self.DBG("curvV (delta): %s\n" % str(delta))
                double rho = 180 + lpar.var(180);
                trf = trf.rotaxisz(delta, rho);
            }
            //TRF("Stem.new_direction() after curving",trf);

            // attraction up/down
            if (par.AttractionUp != 0 && stemlevel >= 2)
            {
                double declination = Math.Acos(trf.getZ3().Z);

                //          I don't see, why we need orientation here, may be this avoids
                //          attraction of branches with the x-Axis up and thus avoids
                //			twisting (see below), but why branches in one direction should
                //			be attracted, those with another direction not, this is unnaturally:
                //          double orient = Math.acos(trf.getY().getZ());
                //          double curve_up_orig = par.AttractionUp * declination * Math.cos(orient)/lpar.nCurveRes;

                // FIXME: devide by (lpar.nCurveRes-nsegm) if last segment
                // should actually be vertical
                double curve_up = par.AttractionUp *
                                  Math.Abs(declination * Math.Sin(declination)) / lpar.nCurveRes;

                Vector3 z = trf.getZ3();
                // FIXME: the mesh is twisted for high values of AttractionUp
                trf = trf.rotaxis(-curve_up * 180 / Math.PI, new Vector3(-z.Y, z.X, 0));
                // trf = trf.rotx(curve_up*180/Math.PI);
            }
            return(trf);
        }
コード例 #4
0
        /**
         * Creates the leaves for the current stem segment
         *
         * @param segment
         */

        void makeLeaves(CS_SegmentImpl segment)
        {
            // creates leaves for the current segment

            if (par.Leaves > 0)
            { // ### NORMAL MODE, leaves along the stem
                // how many leaves in this segment
                float leaves_eff = (int)(leavesPerSegment + par.leavesErrorValue + 0.5);

                // adapt error value
                par.leavesErrorValue -= (leaves_eff - leavesPerSegment);

                if (leaves_eff <= 0)
                {
                    return;
                }

                float offs;
                if (segment.index == 0)
                {
                    offs = parent.stemRadius(offset) / segmentLength;
                }
                else
                {
                    offs = 0;
                }

                // what distance between the leaves
                float dist = (1.0f - offs) / leaves_eff;

                for (int s = 0; s < leaves_eff; s++)
                {
                    // where on the segment add the leaf

                    // FIXME: may be use the same distribution method (BranchDist) as for substems?
                    float where = offs + dist / 2 + s * dist + lpar.var(dist / 2);

                    // offset from stembase
                    float loffs = (segment.index + where) * segmentLength;
                    // get a new direction for the leaf
                    DX_Transformation trf = substemDirection(segment.transf, loffs);
                    // translate it to its position on the stem
                    trf = trf.translate(segment.transf.getZ3() * (where * segmentLength));

                    // create new leaf
                    CS_LeafImpl leaf = new CS_LeafImpl(trf); // ,loffs);
                    leaf.make(par);
                    leaves.Add(leaf);
                }
            }

            // ##### FAN MOD, leaves placed in a fan at stem end
            else if (par.Leaves < 0 && segment.index == segmentCount - 1)
            {
                CS_LevelParams lpar_1 = par.getLevelParams(stemlevel + 1);
                int            cnt    = (int)(leavesPerBranch() + 0.5);

                DX_Transformation trf         = segment.transf.translate(segment.transf.getZ3() * (segmentLength));
                float             distangle   = lpar_1.nRotate / cnt;
                float             varangle    = lpar_1.nRotateV / cnt;
                float             downangle   = lpar_1.nDownAngle;
                float             vardown     = lpar_1.nDownAngleV;
                float             offsetangle = 0;
                // use different method for odd and even number
                if (cnt % 2 == 1)
                {
                    // create one leaf in the middle
                    CS_LeafImpl leaf = new CS_LeafImpl(trf); //,segmentCount*segmentLength);
                    leaf.make(par);
                    leaves.Add(leaf);
                    offsetangle = distangle;
                }
                else
                {
                    offsetangle = distangle / 2;
                }
                // create leaves left and right of the middle
                for (int s = 0; s < cnt / 2; s++)
                {
                    for (int rot = 1; rot >= -1; rot -= 2)
                    {
                        DX_Transformation transf1 = trf.roty(rot * (offsetangle + s * distangle
                                                                    + lpar_1.var(varangle)));
                        transf1 = transf1.rotx(downangle + lpar_1.var(vardown));
                        CS_LeafImpl leaf = new CS_LeafImpl(transf1); //,segmentCount*segmentLength);
                        leaf.make(par);
                        leaves.Add(leaf);
                    }
                }
            }
        }