public int Hash(CSGVertex p)
        {
            for (var i = 0; i < count; i++)
            {
                var item = buckets[i];

                var diffX  = p.P.x - item.P.x;
                var diffY  = p.P.y - item.P.y;
                var diffZ  = p.P.z - item.P.z;
                var sqrMag = diffX * diffX + diffY * diffY + diffZ * diffZ;

                if (sqrMag < bucketSize2)
                {
                    diffX  = p.N.x - item.N.x;
                    diffY  = p.N.y - item.N.y;
                    diffZ  = p.N.z - item.N.z;
                    sqrMag = diffX * diffX + diffY * diffY + diffZ * diffZ;

                    if (sqrMag < bucketSize2)
                    {
                        diffX  = p.UV.x - item.UV.x;
                        diffY  = p.UV.y - item.UV.y;
                        sqrMag = diffX * diffX + diffY * diffY;

                        if (sqrMag < bucketSize2)
                        {
                            return(i);
                        }
                    }
                }
            }

            buckets[count++] = p;
            return(count - 1);
        }
Beispiel #2
0
        public int Hash(CSGVertex p)
        {
            for (int i=0; i<count; i++)
            {
                var item = buckets[i];

                float diffX = p.P.x - item.P.x;
                float diffY = p.P.y - item.P.y;
                float diffZ = p.P.z - item.P.z;
                float sqrMag = diffX*diffX + diffY*diffY + diffZ*diffZ;

                if (sqrMag < bucketSize2)
                {
                    diffX = p.N.x - item.N.x;
                    diffY = p.N.y - item.N.y;
                    diffZ = p.N.z - item.N.z;
                    sqrMag = diffX * diffX + diffY * diffY + diffZ * diffZ;

                    if (sqrMag < bucketSize2)
                    {
                        diffX = p.UV.x - item.UV.x;
                        diffY = p.UV.y - item.UV.y;
                        sqrMag = diffX*diffX + diffY*diffY;

                        if (sqrMag < bucketSize2)
                        {
                            return i;
                        }
                    }
                }
            }

            buckets[count++] = p;
            return count-1;
        }
 // Create a new vertex between this vertex and `other` by linearly
 // interpolating all properties using a parameter of `t`. Subclasses should
 // override this to interpolate additional properties.
 public CSGVertex interpolate(CSGVertex other, float t)
 {
     return(new CSGVertex(
                this.pos.lerp(other.pos, t),
                this.normal.lerp(other.normal, t)
                ));
 }
Beispiel #4
0
    // Construct a solid cylinder. Optional parameters are `start`, `end`,
    // `radius`, and `slices`, which default to `[0, -1, 0]`, `[0, 1, 0]`, `1`, and
    // `16`. The `slices` parameter controls the tessellation.
    //
    // Example usage:
    //
    //     var cylinder = CSG.cylinder({
    //       start: [0, -1, 0],
    //       end: [0, 1, 0],
    //       radius: 1,
    //       slices: 16
    //     });
    static public CSG cylinder(CSGVector3 s, CSGVector3 e, float radius, int slices, CSGShared shared)
    {
        CSGVector3 ray   = e.minus(s);
        CSGVector3 axisZ = ray.unit();
        bool       isY   = (Math.Abs(axisZ.y) > 0.5f);

        CSGVector3 axisX = new CSGVector3(isY ? 1 : 0, !isY ? 1 : 0, 0).cross(axisZ).unit();
        CSGVector3 axisY = axisX.cross(axisZ).unit();

        CSGVertex start = new CSGVertex(s, axisZ.negated());
        CSGVertex end   = new CSGVertex(e, axisZ.unit());

        List <CSGPolygon> polygons = new List <CSGPolygon>();

        for (float i = 0; i < slices; i++)
        {
            float t0 = i / slices;
            float t1 = (i + 1) / slices;

            //cylinderPoint(s, ray, radius, axisX, axisY, axisZ,

            polygons.Add(
                new CSGPolygon(
                    new CSGVertex[] {
                start,
                cylinderPoint(s, ray, radius, axisX, axisY, axisZ, 0, t0, -1),
                cylinderPoint(s, ray, radius, axisX, axisY, axisZ, 0, t1, -1)
            }, shared));

            polygons.Add(
                new CSGPolygon(
                    new CSGVertex[] {
                cylinderPoint(s, ray, radius, axisX, axisY, axisZ, 0, t1, 0),
                cylinderPoint(s, ray, radius, axisX, axisY, axisZ, 0, t0, 0),
                cylinderPoint(s, ray, radius, axisX, axisY, axisZ, 1, t0, 0),
                cylinderPoint(s, ray, radius, axisX, axisY, axisZ, 1, t1, 0)
            }, shared));

            polygons.Add(
                new CSGPolygon(
                    new CSGVertex[] {
                end,
                cylinderPoint(s, ray, radius, axisX, axisY, axisZ, 1, t1, 1),
                cylinderPoint(s, ray, radius, axisX, axisY, axisZ, 1, t0, 1)
            }, shared));
        }

        return(CSG.fromPolygons(polygons));
    }
Beispiel #5
0
        protected List <DefaultVertex> ConvertCSGVertices(IList <CSGVertex> csgVertices)
        {
            List <DefaultVertex> result = new List <DefaultVertex>();

            for (int tri = 0; tri < csgVertices.Count / 3; ++tri)
            {
                CSGVertex c1 = csgVertices[tri * 3 + 0];
                CSGVertex c2 = csgVertices[tri * 3 + 1];
                CSGVertex c3 = csgVertices[tri * 3 + 2];
                Vector3   v1 = c1.Position;
                Vector2   w1 = c1.TexUV;
                Vector3   v2 = c2.Position;
                Vector2   w2 = c2.TexUV;
                Vector3   v3 = c3.Position;
                Vector2   w3 = c3.TexUV;
                float     x1 = v2.X - v1.X;
                float     x2 = v3.X - v1.X;
                float     y1 = v2.Y - v1.Y;
                float     y2 = v3.Y - v1.Y;
                float     z1 = v2.Z - v1.Z;
                float     z2 = v3.Z - v1.Z;

                float s1 = w2.X - w1.X;
                float s2 = w3.X - w1.X;
                float t1 = w2.Y - w1.Y;
                float t2 = w3.Y - w1.Y;

                float   r   = 1f / (s1 * t2 - s2 * t1);
                Vector3 tan = new Vector3(
                    (t2 * x1 - t1 * x2) * r,
                    (t2 * y1 - t1 * y2) * r,
                    (t2 * z1 - t1 * z2) * r
                    );

                result.Add(new DefaultVertex(c1.Position, c1.Normal, tan, c1.TexUV));
                result.Add(new DefaultVertex(c2.Position, c2.Normal, tan, c2.TexUV));
                result.Add(new DefaultVertex(c3.Position, c3.Normal, tan, c3.TexUV));
            }
            return(csgVertices.Select(csg => new DefaultVertex(csg.Position, csg.Normal, csg.TexUV)).ToList());
        }
    // Split `polygon` by this plane if needed, then put the polygon or polygon
    // fragments in the appropriate lists. Coplanar polygons go into either
    // `coplanarFront` or `coplanarBack` depending on their orientation with
    // respect to this plane. Polygons in front or in back of this plane go into
    // either `front` or `back`.
    public void splitPolygon(CSGPolygon polygon, List <CSGPolygon> coplanarFront, List <CSGPolygon> coplanarBack, List <CSGPolygon> front, List <CSGPolygon> back)
    {
        // Classify each point as well as the entire polygon into one of the above
        // four classes.
        int polygonType = 0;

        int[] types = new int[polygon.vertices.Count];

        for (int i = 0; i < polygon.vertices.Count; i++)
        {
            float t    = this.normal.dot(polygon.vertices[i].pos) - this.w;
            int   type = (t < -EPSILON) ? BACK : (t > EPSILON) ? FRONT : COPLANAR;
            polygonType |= type;
            types[i]     = type;
        }

        // Put the polygon in the correct list, splitting it when necessary.
        switch (polygonType)
        {
        case COPLANAR:
            (this.normal.dot(polygon.plane.normal) > 0 ? coplanarFront : coplanarBack).Add(polygon);
            break;

        case FRONT:
            front.Add(polygon);
            break;

        case BACK:
            back.Add(polygon);
            break;

        case SPANNING:
        {
            List <CSGVertex> f = new List <CSGVertex>();
            List <CSGVertex> b = new List <CSGVertex>();
            for (int i = 0; i < polygon.vertices.Count; i++)
            {
                int       j  = (i + 1) % polygon.vertices.Count;
                int       ti = types[i];
                int       tj = types[j];
                CSGVertex vi = polygon.vertices[i];
                CSGVertex vj = polygon.vertices[j];

                if (ti != BACK)
                {
                    f.Add(vi);
                }

                if (ti != FRONT)
                {
                    b.Add(ti != BACK ? vi.clone() : vi);
                }

                if ((ti | tj) == SPANNING)
                {
                    float     t = (this.w - this.normal.dot(vi.pos)) / this.normal.dot(vj.pos.minus(vi.pos));
                    CSGVertex v = vi.interpolate(vj, t);
                    f.Add(v);
                    b.Add(v.clone());
                }
            }
            if (f.Count >= 3)
            {
                front.Add(new CSGPolygon(f, polygon.shared));
            }

            if (b.Count >= 3)
            {
                back.Add(new CSGPolygon(b, polygon.shared));
            }
            break;
        }
        }
    }