예제 #1
0
 static protected bool FindBend(Road.Section first, Road.Section second,
                                WayPoint.Node nodeC,
                                out WayPoint.Node node0,
                                out WayPoint.Node node1)
 {
     node0 = null;
     node1 = null;
     if (first.Edge.Node0 == nodeC)
     {
         node0 = first.Edge.Node1;
     }
     else if (first.Edge.Node1 == nodeC)
     {
         node0 = first.Edge.Node0;
     }
     if (second.Edge.Node0 == nodeC)
     {
         node1 = second.Edge.Node1;
     }
     else if (second.Edge.Node1 == nodeC)
     {
         node1 = second.Edge.Node0;
     }
     return((node0 != null) && (node1 != null));
 }
예제 #2
0
        /// <summary>
        /// Spread flora over intersection of road.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="first"></param>
        /// <param name="second"></param>
        /// <returns></returns>
        public override bool NewFan(
            Road.Intersection isect,
            Road.Section first,
            Road.Section second,
            List <Road.RenderObj> fans)
        {
            FBXModel model = EndModel;

            if (model != null)
            {
                RoadFBXRenderObj ro = new RoadFBXRenderObj();

                ro.Model    = model;
                ro.Animator = EndAnim;

                Matrix  localToWorld = Matrix.Identity;
                Vector3 position     = isect.Node.Position;
                position.Z = Terrain.GetTerrainHeightFlat(position) + isect.Node.Height;
                localToWorld.Translation = position;
                RandomizeAngle(ref localToWorld);
                ro.LocalToWorld = localToWorld;

                fans.Add(ro);
                return(true);
            }
            return(false);
        }
예제 #3
0
        public void Finish(Road.Section section)
        {
            AABB box = AABB.EmptyBox();

            bool stretchUp = section.Road.Generator.StretchUp;
            int  cnt       = Verts.Length;

            for (int i = 0; i < cnt; ++i)
            {
                if (stretchUp)
                {
                    float minHeight  = section.Road.Generator.MinHeight;
                    float maxHeight  = section.Road.Generator.MaxHeight;
                    float t          = (Verts[i].pos.Z - minHeight) / (maxHeight - minHeight);
                    float baseHeight = section.BaseHeight(Verts[i].pos);
                    float terrHeight = Terrain.GetTerrainHeightFlat(Verts[i].pos);
                    Verts[i].pos.Z = terrHeight + t * (Verts[i].pos.Z + baseHeight - terrHeight);
                }
                else
                {
                    if (Verts[i].pos.Z >= 0.0f)
                    {
                        Verts[i].pos.Z += section.BaseHeight(Verts[i].pos);
                    }
                    else
                    {
                        Verts[i].pos.Z = Terrain.GetTerrainHeightFlat(Verts[i].pos);
                    }
                }
                box.Union(Verts[i].pos);
            }
            sphere = box.MakeSphere();
        }
예제 #4
0
 /// <summary>
 /// Create new intersection fan.
 /// </summary>
 /// <param name="node"></param>
 /// <param name="first"></param>
 /// <param name="second"></param>
 /// <returns></returns>
 public override bool NewFan(
     Road.Intersection isect,
     Road.Section first,
     Road.Section second,
     List <Road.RenderObj> fans)
 {
     return(NewFan(isect, new Vector2(1.0f, 0.0f), MathHelper.TwoPi, fans));
 }
예제 #5
0
 /// <summary>
 /// Create a new post.
 /// </summary>
 /// <param name="node"></param>
 /// <param name="first"></param>
 /// <param name="second"></param>
 /// <returns></returns>
 public override bool NewFan(
     Road.Intersection isect,
     Road.Section first,
     Road.Section second,
     List <Road.RenderObj> fans)
 {
     return(posts.NewFan(isect, first, second, fans));
 }
        public void Finish(Road.Section section)
        {
            AABB box = AABB.EmptyBox();

            foreach (Road.RenderObj renderObj in renderObjs)
            {
                renderObj.Finish(section);
                box.Union(renderObj.Sphere);
            }
            sphere = box.MakeSphere();
        }
예제 #7
0
        /// <summary>
        /// Put down a tree at the intersection.
        /// </summary>
        public override bool NewFan(
            Road.Intersection isect,
            Road.Section first,
            Road.Section second,
            List <Road.RenderObj> fans)
        {
            FBXModel model = EndModel;

            if (model != null)
            {
                RoadMultiRenderObj multiRo = new RoadMultiRenderObj();

                Vector2 center = isect.Node.Position2d;

                float area = width * width * (float)Math.PI;

                int count = (int)Math.Ceiling(area * density);

                for (int i = 0; i < count; ++i)
                {
                    double rndAng = BokuGame.bokuGame.rnd.NextDouble() * Math.PI * 2.0;
                    float  rndOut = (float)(BokuGame.bokuGame.rnd.NextDouble() * 2.0 - 1.0);

                    float cos = (float)Math.Cos(rndAng);
                    float sin = (float)Math.Sin(rndAng);

                    Vector2 rndPos = center;
                    rndPos.X += cos * rndOut;
                    rndPos.Y += sin * rndOut;
                    float height = Terrain.GetTerrainHeightFlat(rndPos);

                    Matrix localToWorld = Matrix.CreateTranslation(rndPos.X, rndPos.Y, height);

                    RoadFBXRenderObj ro = new RoadFBXRenderObj();
                    ro.Model        = model;
                    ro.Animator     = EndAnim;
                    ro.LocalToWorld = localToWorld;

                    multiRo.RenderObjList.Add(ro);
                }

                fans.Add(multiRo);

                return(count > 0);
            }
            return(false);
        }
예제 #8
0
        /// <summary>
        /// Trim all geometry for two sections by the bisecting plane (if appropriate)
        /// </summary>
        /// <param name="plane"></param>
        public virtual bool Trim(Road.Section first, Road.Section second)
        {
            RoadStdRenderObj roFirst  = first.RenderObj as RoadStdRenderObj;
            RoadStdRenderObj roSecond = second.RenderObj as RoadStdRenderObj;

            if ((roFirst == null) || (roSecond == null))
            {
                return(false);
            }


            WayPoint.Node node0 = null;
            WayPoint.Node node1 = null;
            WayPoint.Node nodeC = null;
            if (!FindBend(first, second, out nodeC, out node0, out node1))
            {
                return(false);
            }

            Vector2 edge0 = Vector2.Normalize(node0.Position2d - nodeC.Position2d);
            Vector2 edge1 = Vector2.Normalize(node1.Position2d - nodeC.Position2d);
            float   dot   = Vector2.Dot(edge0, edge1);

            {
                float  cross = edge0.X * edge1.Y - edge0.Y * edge1.X;
                double rads  = Math.Atan2(cross, dot);
                if (rads > 0.0)
                {
                    Vector2 bisect = dot > -0.999f
                        ? Vector2.Normalize(edge0 + edge1)
                        : new Vector2(-edge0.Y, edge0.X);

                    Vector3 norm  = new Vector3(-bisect.Y, bisect.X, 0.0f);
                    float   dist  = Vector3.Dot(norm, nodeC.Position);
                    Vector4 plane = new Vector4(norm, dist);

                    TrimToPlane(-plane, roFirst);
                    TrimToPlane(plane, roSecond);

                    return(true);
                }
            }

            return(false);
        }
예제 #9
0
        /// <summary>
        /// Generate a fan to fill out an intersection.
        /// </summary>
        /// <param name="nodeC"></param>
        /// <param name="first"></param>
        /// <param name="second"></param>
        /// <returns></returns>
        public override bool NewFan(
            Road.Intersection isect,
            Road.Section first,
            Road.Section second,
            List <Road.RenderObj> fans)
        {
            if ((first == null) || (second == null))
            {
                return(NewFan(isect, new Vector2(1.0f, 0.0f), Math.PI * 2.0, fans));
            }

            WayPoint.Node nodeC = isect.Node;
            WayPoint.Node node0;
            WayPoint.Node node1;
            if (!FindBend(first, second, nodeC, out node0, out node1))
            {
                return(false);
            }

            Vector2 center      = nodeC.Position2d;
            Vector2 firstEdge   = Vector2.Normalize(node0.Position2d - center);
            Vector2 startRadial = new Vector2(-firstEdge.Y, firstEdge.X);

            double rads0 = first.EdgeAngle(nodeC) + Math.PI * 0.5;

            if (rads0 < 0.0)
            {
                rads0 += Math.PI * 2.0;
            }
            double rads1 = second.EdgeAngle(nodeC) - Math.PI * 0.5;

            if (rads1 < 0.0)
            {
                rads1 += Math.PI * 2.0;
            }
            double rads = rads1 - rads0;

            if (rads < 0.0)
            {
                rads += Math.PI * 2.0;
            }
            return(NewFan(isect, startRadial, rads, fans));
        }
예제 #10
0
        /// <summary>
        /// Spread flora over new section of road.
        /// </summary>
        /// <param name="section"></param>
        public override void NewSection(Road.Section section)
        {
            RoadMultiRenderObj multiRo = null;
            FBXModel           model   = Model;

            if (model != null)
            {
                multiRo = new RoadMultiRenderObj();

                Vector2 start = section.Edge.Node0.Position2d;
                Vector2 end   = section.Edge.Node1.Position2d;
                Vector2 axis  = end - start;
                Vector2 norm  = new Vector2(-axis.Y, axis.X);
                norm = Vector2.Normalize(norm) * width;

                float area = axis.Length() * width * 2.0f;

                int count = (int)Math.Ceiling(area * density);

                for (int i = 0; i < count; ++i)
                {
                    float rndTo  = (float)BokuGame.bokuGame.rnd.NextDouble();
                    float rndOut = (float)(BokuGame.bokuGame.rnd.NextDouble() * 2.0 - 1.0);

                    Vector2 rndPos = start + rndTo * axis + rndOut * norm;
                    float   height = Terrain.GetTerrainHeightFlat(rndPos);

                    height += section.Edge.Node0.Height + rndTo * (section.Edge.Node1.Height - section.Edge.Node0.Height);

                    Matrix localToWorld = Matrix.CreateTranslation(rndPos.X, rndPos.Y, height);

                    RandomizeAngle(ref localToWorld);

                    RoadFBXRenderObj ro = new RoadFBXRenderObj();
                    ro.Model        = model;
                    ro.LocalToWorld = localToWorld;
                    ro.Animator     = Anim;

                    multiRo.RenderObjList.Add(ro);
                }
            }
            section.RenderObj = multiRo;
        }
예제 #11
0
        /// <summary>
        /// Find the node shared by two sections and the unshared nodes
        /// </summary>
        /// <param name="first">First section</param>
        /// <param name="second">Second section</param>
        /// <param name="node0">Unshared node from first</param>
        /// <param name="node1">Unshared node from second</param>
        /// <param name="nodeC">Shared node</param>
        /// <returns>Return true if they do share a node</returns>
        static protected bool FindBend(Road.Section first, Road.Section second,
                                       out WayPoint.Node nodeC,
                                       out WayPoint.Node node0,
                                       out WayPoint.Node node1)
        {
            // Find the common and end nodes
            if (first.Edge.Node0 == second.Edge.Node0)
            {
                nodeC = first.Edge.Node0;
                node0 = first.Edge.Node1;
                node1 = second.Edge.Node1;
            }
            else if (first.Edge.Node0 == second.Edge.Node1)
            {
                nodeC = first.Edge.Node0;
                node0 = first.Edge.Node1;
                node1 = second.Edge.Node0;
            }
            else if (first.Edge.Node1 == second.Edge.Node0)
            {
                nodeC = first.Edge.Node1;
                node0 = first.Edge.Node0;
                node1 = second.Edge.Node1;
            }
            else if (first.Edge.Node1 == second.Edge.Node1)
            {
                nodeC = first.Edge.Node1;
                node0 = first.Edge.Node0;
                node1 = second.Edge.Node0;
            }
            else
            {
                node0 = null;
                node1 = null;
                nodeC = null;

                // Might assert, since these two edges don't share a node.
                // But not asserting lets this be used to check whether
                // two sections share a node.
                return(false);
            }
            return(true);
        }
예제 #12
0
        /// <summary>
        /// Generate a castle as an intersection.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="first"></param>
        /// <param name="second"></param>
        /// <returns></returns>
        public override bool NewFan(
            Road.Intersection isect,
            Road.Section first,
            Road.Section second,
            List <Road.RenderObj> fans)
        {
            bool didBase = base.NewFan(isect, first, second, fans);

            WayPoint.Node node = isect.Node;

            /*
             * centerheight
             * 4.4
             * height
             * 4.3, 2.0, 2.3, 2.3, -1.0
             * width
             * 0.05, 0.2, 0.2, 0.3, 0.3
             * */
            RoadFBXRenderObj ro    = null;
            FBXModel         model = ActorManager.GetActor("Castle").Model;

            if (model != null)
            {
                ro = new RoadFBXRenderObj();

                ro.Model = model;

                Matrix  localToWorld = Matrix.Identity;
                Vector3 position     = node.Position;
                localToWorld.Translation = position;
                ro.LocalToWorld          = localToWorld;

                fans.Add(ro);

                return(true);
            }
            return(didBase);
        }
예제 #13
0
        /// <summary>
        /// Generate a new section.
        /// </summary>
        /// <param name="section"></param>
        public override void NewSection(Road.Section section)
        {
            section.RenderObj = null;

            RoadVertex[] verts = GenVerts(section);

            Int16[] indices = GenIndices(section);

            if ((verts.Length > 0) && (indices.Length > 0))
            {
                RoadStdRenderObj ro = new RoadStdRenderObj();

                ro.Verts       = verts;
                ro.Indices     = indices;
                ro.DiffuseTex0 = diffTex0;
                ro.DiffuseTex1 = diffTex1;
                ro.NormalTex0  = normTex0;
                ro.NormalTex1  = normTex1;
                ro.UVXfm       = uvXfm;
                ro.Shininess   = Shininess;

                section.RenderObj = ro;
            }
        }
예제 #14
0
        /// <summary>
        /// Generate the vertex data for a (straight) section of road.
        /// </summary>
        /// <param name="section"></param>
        /// <returns></returns>
        protected RoadVertex[] GenVerts(Road.Section section)
        {
            Vector2 p0 = section.Edge.Node0.Position2d;
            Vector2 p1 = section.Edge.Node1.Position2d;

            Vector2 axis = p1 - p0;
            float   len  = axis.Length();

            axis /= len;

            Vector2 norm = new Vector2(-axis.Y, axis.X);

            float step = Road.Step;

            numSteps = Math.Max(1, (int)Math.Ceiling(len / step));
            step     = len / (float)numSteps;

            int vertsPerHalfStep = VertsPerStep / 2;

            int baseVertex = 0;

            RoadVertex[] verts = new RoadVertex[(numSteps + 1) * VertsPerStep];
            for (int iStep = 0; iStep <= numSteps; ++iStep)
            {
                Vector2 posCen = p0 + axis * step * iStep;

                Vector3 terrNormal = Vector3.UnitZ;
                // line it up with direction of travel by subtracting out component
                // along norm.
                //vtxNormal.X -= vtxNormal.X * norm.X;
                //vtxNormal.Y -= vtxNormal.Y * norm.Y;
                //vtxNormal.Normalize();

                // Negative side
                for (int iVert = vertsPerHalfStep - 1; iVert >= 0; --iVert)
                {
                    float width  = widthTable[iVert];
                    float height = heightTable[iVert];

                    Vector2 pos = new Vector2(
                        posCen.X - norm.X * width,
                        posCen.Y - norm.Y * width);

                    //float baseHeight = section.BaseHeight(pos);
                    //height += baseHeight;

                    verts[baseVertex].pos.X = pos.X;
                    verts[baseVertex].pos.Y = pos.Y;
                    verts[baseVertex].pos.Z = height;

                    verts[baseVertex].norm = VtxNormal(terrNormal, -norm, iVert);

                    verts[baseVertex].uv.X      = step * iStep;
                    verts[baseVertex].uv.Y      = distTable[iVert];
                    verts[baseVertex].texSelect = TexSelect(iVert);

                    ++baseVertex;
                }

                // Center
                float centerBaseHeight = 0.0f; // section.BaseHeight(posCen);
                float heightAtCenter   = centerHeight + centerBaseHeight;
                verts[baseVertex].pos.X     = posCen.X;
                verts[baseVertex].pos.Y     = posCen.Y;
                verts[baseVertex].pos.Z     = heightAtCenter;
                verts[baseVertex].norm      = terrNormal;
                verts[baseVertex].uv.X      = step * iStep;
                verts[baseVertex].uv.Y      = 0.0f;
                verts[baseVertex].texSelect = TexSelect(0);

                ++baseVertex;

                // Positive side
                for (int iVert = 0; iVert < vertsPerHalfStep; ++iVert)
                {
                    float width  = widthTable[iVert];
                    float height = heightTable[iVert];

                    Vector2 pos = new Vector2(
                        posCen.X + norm.X * width,
                        posCen.Y + norm.Y * width);

                    //float baseHeight = section.BaseHeight(pos);
                    //height += baseHeight;

                    verts[baseVertex].pos.X = pos.X;
                    verts[baseVertex].pos.Y = pos.Y;
                    verts[baseVertex].pos.Z = height;

                    verts[baseVertex].norm = VtxNormal(terrNormal, norm, iVert);

                    verts[baseVertex].uv.X      = step * iStep;
                    verts[baseVertex].uv.Y      = distTable[iVert];
                    verts[baseVertex].texSelect = TexSelect(iVert);

                    ++baseVertex;
                }
            }
            return(verts);
        }
예제 #15
0
 /// <summary>
 /// No trimming
 /// </summary>
 /// <param name="first"></param>
 /// <param name="second"></param>
 /// <returns></returns>
 public override bool Trim(Road.Section first, Road.Section second)
 {
     return(false);
 }
예제 #16
0
 /// <summary>
 /// Sections are rails.
 /// </summary>
 /// <param name="section"></param>
 public override void NewSection(Road.Section section)
 {
     rails.NewSection(section);
 }
예제 #17
0
        /// <summary>
        /// Generate connectivity for a straight section of road.
        /// </summary>
        /// <param name="section"></param>
        /// <returns></returns>
        protected Int16[] GenIndices(Road.Section section)
        {
            int vertRowBase  = 0;
            int nextRow      = VertsPerStep; // 3 per row
            int nextCol      = 1;            // the next one over
            int quadsPerStep = VertsPerStep - 1;
            int quadsPerSide = quadsPerStep / 2;
            int numTris      = numSteps * (quadsPerStep - numSkips * 2) * 2;

            Int16[] indices = new Int16[numTris * 3];
            int     idx     = 0;

            for (int iStep = 0; iStep < numSteps; ++iStep)
            {
                if ((iStep & 1) != 0)
                {
                    for (int iQuad = 0; iQuad < quadsPerStep; iQuad += 2)
                    {
                        int vertBase = vertRowBase + iQuad;

                        if (!SkipQuad(iQuad, quadsPerSide))
                        {
                            indices[idx++] = ((Int16)vertBase);
                            indices[idx++] = ((Int16)(vertBase + nextCol));
                            indices[idx++] = ((Int16)(vertBase + nextRow));

                            indices[idx++] = ((Int16)(vertBase + nextRow));
                            indices[idx++] = ((Int16)(vertBase + nextCol));
                            indices[idx++] = ((Int16)(vertBase + nextRow + nextCol));
                        }

                        ++vertBase;

                        if (!SkipQuad(iQuad + 1, quadsPerSide))
                        {
                            indices[idx++] = ((Int16)(vertBase + nextCol));
                            indices[idx++] = ((Int16)(vertBase + nextCol + nextRow));
                            indices[idx++] = ((Int16)(vertBase));

                            indices[idx++] = ((Int16)(vertBase));
                            indices[idx++] = ((Int16)(vertBase + nextCol + nextRow));
                            indices[idx++] = ((Int16)(vertBase + nextRow));
                        }
                    }
                }
                else
                {
                    for (int iQuad = 0; iQuad < quadsPerStep; iQuad += 2)
                    {
                        int vertBase = vertRowBase + iQuad;

                        if (!SkipQuad(iQuad, quadsPerSide))
                        {
                            indices[idx++] = ((Int16)(vertBase + nextCol));
                            indices[idx++] = ((Int16)(vertBase + nextCol + nextRow));
                            indices[idx++] = ((Int16)(vertBase));

                            indices[idx++] = ((Int16)(vertBase));
                            indices[idx++] = ((Int16)(vertBase + nextCol + nextRow));
                            indices[idx++] = ((Int16)(vertBase + nextRow));
                        }

                        ++vertBase;

                        if (!SkipQuad(iQuad + 1, quadsPerSide))
                        {
                            indices[idx++] = ((Int16)vertBase);
                            indices[idx++] = ((Int16)(vertBase + nextCol));
                            indices[idx++] = ((Int16)(vertBase + nextRow));

                            indices[idx++] = ((Int16)(vertBase + nextRow));
                            indices[idx++] = ((Int16)(vertBase + nextCol));
                            indices[idx++] = ((Int16)(vertBase + nextRow + nextCol));
                        }
                    }
                }

                vertRowBase += VertsPerStep;
            }
            return(indices);
        }
예제 #18
0
 /// <summary>
 /// Generate a straight section
 /// </summary>
 /// <param name="section">the section to hold the output</param>
 public abstract void NewSection(Road.Section section);
예제 #19
0
 /// <summary>
 /// Generate a new fan filling the sector defined by p0, p1, and pC as the center.
 /// Assumes |p0 - pC| == |p1 - pC| == radius == roadwidth/2, and that the fan goes from
 /// p0 to p1 counterclockwise.
 /// </summary>
 /// <param name="node">the shared node at the intersection</param>
 /// <param name="first">edge of start of the arc</param>
 /// <param name="second">edge of end of the arc</param>
 public abstract bool NewFan(
     Road.Intersection isect,
     Road.Section first,
     Road.Section second,
     List <Road.RenderObj> fans);
 public void Finish(Road.Section section)
 {
 }