public static RoadVertex operator*(RoadVertex v, float f)
            {
                RoadVertex ret = v;

                ret.pos  *= f;
                ret.norm *= f;
                ret.uv   *= f;
                Vector4 texSel = ret.texSelect.ToVector4();

                texSel       *= f;
                ret.texSelect = new Color(texSel);

                return(ret);
            }
            public static RoadVertex operator+(RoadVertex v0, RoadVertex v1)
            {
                RoadVertex ret = v0;

                ret.pos  += v1.pos;
                ret.norm += v1.norm;
                ret.uv   += v1.uv;
                Vector4 v0TexSel = v0.texSelect.ToVector4();
                Vector4 v1TexSel = v1.texSelect.ToVector4();

                v0TexSel     += v1TexSel;
                ret.texSelect = new Color(v0TexSel);

                return(ret);
            }
        /// <summary>
        /// Generate (if necessary) an interpolated vertex, returning the index
        /// for the vertex based on this barycentric coordinate
        /// </summary>
        /// <param name="vtxData"></param>
        /// <param name="bary"></param>
        /// <param name="idx0"></param>
        /// <param name="idx1"></param>
        /// <param name="idx2"></param>
        /// <returns></returns>
        static protected Int16 AddVertex(List <RoadVertex> vtxData,
                                         Vector3 bary,
                                         Int16 idx0,
                                         Int16 idx1,
                                         Int16 idx2)
        {
            if ((bary.X == 1.0f) &&
                (bary.Y == 0.0f) &&
                (bary.Z == 0.0f))
            {
                // original first vert
                return(idx0);
            }
            else if ((bary.X == 0.0f) &&
                     (bary.Y == 1.0f) &&
                     (bary.Z == 0.0f))
            {
                // original second vert
                return(idx1);
            }
            else if ((bary.X == 0.0f) &&
                     (bary.Y == 0.0f) &&
                     (bary.Z == 1.0f))
            {
                // original third vert
                return(idx2);
            }
            RoadVertex vtx0 = vtxData[idx0];
            RoadVertex vtx1 = vtxData[idx1];
            RoadVertex vtx2 = vtxData[idx2];

            RoadVertex newVtx = vtx0 * bary.X
                                + vtx1 * bary.Y
                                + vtx2 * bary.Z;

            vtxData.Add(newVtx);
            return((Int16)(vtxData.Count - 1));
        }
        /// <summary>
        /// Generate a list of indices for the input geometry trimmed to the exterior
        /// of the planes in the list.
        /// This is a convex trim, for a concave trim, rather than trimming the output
        /// of one plane, you would trim the rejects of the previous trim.
        /// Convex trim:
        ///     slice geometry at plane[0] boundary
        ///     discard geometry on negative side of plane[0]
        ///     slice positive side geometry at plane[1] boundary
        ///     discard geometry on negative side of plane[1]
        ///     [repeat for rest of planes]
        /// Concave trim:
        ///     slice geometry at plane[0] boundary
        ///     accept geometry on positive side of plane[0]
        ///     slice negative side geometry at plane[1] boundary
        ///     accept positive side geometry of plane[1]
        ///     slice negative side geometry at plane[2] boundary
        ///     accept positive side geometry of plane[2]
        ///     [repeat for rest of planes]
        /// </summary>
        /// <param name="planes"></param>
        /// <param name="idxIn"></param>
        /// <param name="idxOut"></param>
        /// <param name="vtxData"></param>
        /// <returns></returns>
        static public bool TrimIndexedTriList(List <Vector4> planes,
                                              List <Int16> idxIn,
                                              List <Int16> idxOut,
                                              List <RoadVertex> vtxData)
        {
            GraphicsDevice device = BokuGame.bokuGame.GraphicsDevice;

            UInt32 numIndicesIn = (UInt32)idxIn.Count;
            UInt32 numTrisIn    = numIndicesIn / 3; // Hardcoding for IndexElemetnSize.SixteenBits / Int16

            Debug.Assert(numTrisIn * 3 == numIndicesIn);
            idxOut.Clear();

            UInt32 numVertsIn = (UInt32)vtxData.Count;

            List <Vector3> baryIn  = new List <Vector3>(3);
            List <Vector3> baryOut = new List <Vector3>(3);

            bool anyTrimmed = false;

            // for each plane
            foreach (Vector4 plane in planes)
            {
                // for each triangle
                for (int iTri = 0; iTri < numTrisIn; iTri++)
                {
                    Int16 idx0 = idxIn[iTri * 3 + 0];
                    Int16 idx1 = idxIn[iTri * 3 + 1];
                    Int16 idx2 = idxIn[iTri * 3 + 2];

                    RoadVertex vtx0 = vtxData[idx0];
                    RoadVertex vtx1 = vtxData[idx1];
                    RoadVertex vtx2 = vtxData[idx2];

                    baryIn.Clear();
                    baryIn.Add(new Vector3(1.0f, 0.0f, 0.0f));
                    baryIn.Add(new Vector3(0.0f, 1.0f, 0.0f));
                    baryIn.Add(new Vector3(0.0f, 0.0f, 1.0f));

                    baryOut.Clear();

                    // Run the triangle through the trimmer
                    bool trimmed = Trim(vtx0.pos, vtx1.pos, vtx2.pos, baryIn, baryOut, plane);
                    // if the triangle wasn't trimmed
                    anyTrimmed = anyTrimmed || trimmed;
                    if (!trimmed)
                    {
                        // Copy the indices as is into the output list
                        idxOut.Add(idx0);
                        idxOut.Add(idx1);
                        idxOut.Add(idx2);
                    }
                    else if (baryOut.Count > 2)
                    {
                        // We've been trimmed, but we still have non-zero count of
                        // vertices, which means we contain new vertices.

                        // We could get clever here and tell which vertices are new
                        // and which have been generated, or we can be lazy and just
                        // assume all are new.

                        // In either case, we append any new vertices to the end of
                        // the vertex list, and add the new indices to the output list


                        Int16 idxPivot = AddVertex(vtxData, baryOut[0], idx0, idx1, idx2);

                        Int16 idxLast = AddVertex(vtxData, baryOut[1], idx0, idx1, idx2);

                        Int16 idxNext = AddVertex(vtxData, baryOut[2], idx0, idx1, idx2);

                        idxOut.Add(idxPivot);
                        idxOut.Add(idxLast);
                        idxOut.Add(idxNext);

                        for (int iBary = 3; iBary < baryOut.Count; ++iBary)
                        {
                            idxLast = idxNext;
                            idxNext = AddVertex(vtxData, baryOut[iBary], idx0, idx1, idx2);

                            idxOut.Add(idxPivot);
                            idxOut.Add(idxLast);
                            idxOut.Add(idxNext);
                        }

                        anyTrimmed = true;
                    }
                    // else the whole triangle was culled
                }
            }
            return(anyTrimmed);
        }
Esempio n. 5
0
        protected virtual bool NewFan(
            Road.Intersection isect,
            Vector2 startRadial,
            double rads,
            List <Road.RenderObj> fans)
        {
            Road   road       = isect.Road;
            int    numRadials = (int)Math.Ceiling(rads / road.RadStep);
            double radStep    = rads / numRadials;

            Vector2 center = isect.Node.Position2d;

            int vertsPerRadial = VertsPerStep / 2;
            int numVerts       = (numRadials + 1) * vertsPerRadial + 1;

            RoadVertex[] verts = new RoadVertex[numVerts];

            Vector3 terrNormal = Vector3.UnitZ;

            AABB box = AABB.EmptyBox();

            int iVert = 0;

            for (int iRadial = 0; iRadial <= numRadials; ++iRadial)
            {
                double ang = radStep * iRadial;
                float  cos = (float)Math.Cos(ang);
                float  sin = (float)Math.Sin(ang);

                Vector2 radial = new Vector2(startRadial.X * cos - startRadial.Y * sin,
                                             startRadial.X * sin + startRadial.Y * cos);

                for (int iOut = 0; iOut < vertsPerRadial; ++iOut)
                {
                    float width  = widthTable[iOut];
                    float height = heightTable[iOut];

                    float arc = (float)(ang * width);

                    RoadVertex vtx = new RoadVertex();
                    Vector2    pos = center + width * radial;

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

                    vtx.pos.X = pos.X;
                    vtx.pos.Y = pos.Y;
                    vtx.pos.Z = height;

                    box.Union(vtx.pos);

                    vtx.norm = VtxNormal(terrNormal, radial, iOut);

                    vtx.uv.X      = arc;
                    vtx.uv.Y      = distTable[iOut];
                    vtx.texSelect = TexSelect(iOut);

                    verts[iVert++] = vtx;
                }
            }

            float centerBaseHeight = 0.0f; //  isect.BaseHeight(center);
            float heightAtCenter   = centerHeight + centerBaseHeight;

            RoadVertex last = new RoadVertex();

            last.pos.X = center.X;
            last.pos.Y = center.Y;
            last.pos.Z = heightAtCenter;

            box.Union(last.pos);

            last.norm = terrNormal;

            last.uv.X      = 0.0f;
            last.uv.Y      = 0.0f;
            last.texSelect = TexSelect(0);

            int centerIdx = iVert++;

            verts[centerIdx] = last;

            Debug.Assert(iVert == numVerts);

            // First step per radial is a single tri,
            // then the rest of the steps are quads
            int quadsPerRadial = vertsPerRadial - 1;

            int numTris = 0;

            if (!skipTable[0])
            {
                numTris += numRadials;

                numTris += numRadials * (quadsPerRadial - numSkips) * 2;
            }
            else
            {
                numTris += numRadials * (quadsPerRadial - (numSkips - 1)) * 2;
            }
            Int16[] indices = new Int16[numTris * 3];

            int nextRad = vertsPerRadial;
            int nextOut = 1;
            int baseVtx = 0;
            int idx     = 0;

            for (int iRadial = 0; iRadial < numRadials; ++iRadial)
            {
                if (!skipTable[0])
                {
                    indices[idx++] = (Int16)(baseVtx);
                    indices[idx++] = (Int16)(centerIdx);
                    indices[idx++] = (Int16)(baseVtx + nextRad);
                }

                for (int iOut = 0; iOut < quadsPerRadial; iOut++)
                {
                    if (!skipTable[iOut + 1])
                    {
                        indices[idx++] = (Int16)(baseVtx + iOut + nextRad);
                        indices[idx++] = (Int16)(baseVtx + iOut + nextRad + nextOut);
                        indices[idx++] = (Int16)(baseVtx + iOut);

                        indices[idx++] = (Int16)(baseVtx + iOut);
                        indices[idx++] = (Int16)(baseVtx + iOut + nextRad + nextOut);
                        indices[idx++] = (Int16)(baseVtx + iOut + nextOut);
                    }
                }
                baseVtx += nextRad;
            }
            Debug.Assert(idx == numTris * 3);

            RoadStdRenderObj ro = null;

            if ((verts.Length > 0) && (indices.Length > 0))
            {
                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;
                ro.Sphere      = box.MakeSphere();

                fans.Add(ro);

                return(true);
            }
            return(false);
        }
Esempio n. 6
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);
        }