Пример #1
0
 public void copyFaceNormalToVertexNormals()
 {
     for (int f = 0, fl = this.faces.Count; f < fl; f++)
     {
         Face3 face = this.faces[f];
         face.SetFaceNormalToVertexNormals();
     }
 }
Пример #2
0
    // Use this for initialization
    void Start()
    {
        THREE.Geometry geometry;

        AddRenderObject(new THREE.SphereGeometry(75, 20, 10), material, new Vector3(-400, 0, 200));

        AddRenderObject(new THREE.IcosahedronGeometry(75, 1), material, new Vector3(-200, 0, 200));

        AddRenderObject(new THREE.OctahedronGeometry(75, 2), material, new Vector3(0, 0, 200));

        AddRenderObject(new THREE.TetrahedronGeometry(75, 0), material, new Vector3(200, 0, 200));

        AddRenderObject(new THREE.PlaneGeometry(100, 100, 4, 4), material, new Vector3(-400, 0, 0));

        geometry = AddRenderObject(new THREE.BoxGeometry(100, 100, 100, 4, 4, 4), material, new Vector3(-200, 0, 0));

        AddRenderObject(new THREE.CircleGeometry(50, 20, 0, Mathf.PI * 2), material, new Vector3(0, 0, 0));

        AddRenderObject(new THREE.RingGeometry(10, 50, 20, 5, 0, Mathf.PI * 2), material, new Vector3(200, 0, 0));

        AddRenderObject(new THREE.CylinderGeometry(25, 75, 100, 40, 5, false), material, new Vector3(400, 0, 0));

        //
        List <Vector3> points = new List <Vector3>();

        for (var i = 0; i < 50; i++)
        {
            points.Add(new Vector3(Mathf.Sin(i * 0.2f) * Mathf.Sin(i * 0.1f) * 15 + 50, 0, (i - 5) * 2));
        }
        AddRenderObject(new THREE.LatheGeometry(points, 20), material, new Vector3(-400, 0, -200));

        AddRenderObject(new THREE.TorusGeometry(50, 20, 20, 20), material, new Vector3(-200, 0, -200));

        AddRenderObject(new THREE.TorusKnotGeometry(50, 10, 50, 20), material, new Vector3(0, 0, -200));


        THREE.Line     lineMesh = new THREE.Line(new THREE.Geometry(), wireMaterial);
        THREE.Geometry geo      = geometry;
        for (int i = 0; i < geo.faces.Count; i++)
        {
            THREE.Face3 _face = geo.faces[i];
            List <int>  tri   = _face.GetTriangles();

            for (int n = 0; n < tri.Count; n++)
            {
                Vector3           normal = _face.vertexNormals[n];
                THREE.ArrowHelper arrow  = new THREE.ArrowHelper(normal, geo.vertices[tri[n]], 10, Color.green);
                lineMesh.Add(arrow);
            }
        }

        AddRenderLineObject(lineMesh.geo, wireMaterial, new Vector3(-200, 0, 0));
    }
        // Use this for initialization
        public TorusGeometry(float radius = 10, float tube = 4, int radialSegments = 8, int tubularSegments = 6, float arc = Mathf.PI * 2)
        {
            Vector3        center  = new Vector3();
            List <Vector2> uvs     = new List <Vector2> ();
            List <Vector3> normals = new List <Vector3> ();

            for (int j = 0; j <= radialSegments; j++)
            {
                for (int i = 0; i <= tubularSegments; i++)
                {
                    float u = (float)i / tubularSegments * arc;
                    float v = (float)j / radialSegments * Mathf.PI * 2;

                    center.x = radius * Mathf.Cos(u);
                    center.y = radius * Mathf.Sin(u);

                    var vertex = new Vector3();
                    vertex.x = (radius + tube * Mathf.Cos(v)) * Mathf.Cos(u);
                    vertex.y = (radius + tube * Mathf.Cos(v)) * Mathf.Sin(u);
                    vertex.z = tube * Mathf.Sin(v);

                    this.vertices.Add(vertex);

                    uvs.Add(new Vector2((float)i / tubularSegments, (float)j / radialSegments));

                    normals.Add((vertex - center).normalized);
                }
            }


            for (int j = 1; j <= radialSegments; j++)
            {
                for (int i = 1; i <= tubularSegments; i++)
                {
                    int a = (tubularSegments + 1) * j + i - 1;
                    int b = (tubularSegments + 1) * (j - 1) + i - 1;
                    int c = (tubularSegments + 1) * (j - 1) + i;
                    int d = (tubularSegments + 1) * j + i;

                    var face = new Face3(a, b, d, new Vector3[] { clone(normals[a]), clone(normals[b]), clone(normals[d]) });
                    this.faces.Add(face);
                    this.faceVertexUvs.Add(new List <Vector2>(new Vector2[] { uvs[a], uvs[b], uvs[d] }));

                    face = new Face3(b, c, d, new Vector3[] { clone(normals[b]), clone(normals[c]), clone(normals[d]) });
                    this.faces.Add(face);
                    this.faceVertexUvs.Add(new List <Vector2>(new Vector2[] { uvs[b], uvs[c], uvs[d] }));
                }
            }

            this.computeFaceNormals();
            //this.computeVertexNormals();
        }
Пример #4
0
        void f3(int a, int b, int c, Shape shape, bool isBottom, int shapesOffset, WorldUVGenerator uvgen, Option options)
        {
            a += shapesOffset;
            b += shapesOffset;
            c += shapesOffset;

            // normal, color, material
            Face3 face;

            if (faceIndex >= faces.Count)
            {
                face = new Face3(a, b, c);
                this.faces.Add(face);
            }
            else
            {
                face   = faces[faceIndex];
                face.a = a;
                face.b = b;
                face.c = c;
            }
            faceIndex++;

            TubeGeometry.FrenetFrames splineTube = options.frames;
            Vector3 normal;

            if (splineTube != null)
            {
                int stepIndex = isBottom ? 0 : splineTube.tangents.Count - 1;
                normal = splineTube.tangents[stepIndex] * (isBottom ? -1 : 1);
            }
            else
            {
                normal = (isBottom ? -1 : 1) * Vector3.forward;
            }
            face.vertexNormals = new Vector3[] { normal, normal, normal };

            List <Vector2> uvs = isBottom ? uvgen.generateBottomUV(this, shape, a, b, c) : uvgen.generateTopUV(this, shape, a, b, c);

            face.uvs = uvs.ToArray();

            // TODO: faceVertexUvs の変更で問題点ないか確認
//			if(faceIndex-1 >= faceVertexUvs.Count){
//				this.faceVertexUvs.Add( new List<Vector2>( uvs ));
//			}else{
//				this.faceVertexUvs[faceIndex - 1] = new List<Vector2>( uvs );
//			}
//			//this.faceVertexUvs.Add( new List<Vector2>( new Vector2[]{ Vector2.one, Vector2.one, Vector2.one } )); // Debug
        }
        public CircleGeometry(float radius_, int segments_, float thetaStart_, float thetaLength_)
        {
            List <Vector2> uvs = new List <Vector2> ();

            float radius = radius_;

//		float thetaStart = thetaStart_ != undefined ? thetaStart_ : 0;
//		float thetaLength = thetaLength_ != undefined ? thetaLength_ : Mathf.PI * 2;
//		int segments = segments_ != undefined ? Mathf.max( 3, segments_ ) : 8;
            float thetaStart  = thetaStart_;
            float thetaLength = thetaLength_;
            int   segments    = segments_;

            Vector3 center   = new Vector3();
            Vector2 centerUV = new Vector2(0.5f, 0.5f);

            this.vertices.Add(center);
            uvs.Add(centerUV);

            for (int i = 0; i <= segments; i++)
            {
                Vector3 vertex  = new Vector3();
                float   segment = thetaStart + ((float)i / segments) * thetaLength;

                vertex.x = radius * Mathf.Cos(segment);
                vertex.y = radius * Mathf.Sin(segment);

                this.vertices.Add(vertex);
                uvs.Add(new Vector2((vertex.x / radius + 1) / 2, (vertex.y / radius + 1) / 2));
            }

            Vector3 n = new Vector3(0, 0, 1);

            for (int i = 1; i <= segments; i++)
            {
                int v1 = i;
                int v2 = i + 1;
                int v3 = 0;

                Face3 face = new Face3(v1, v2, v3, new Vector3[] { n, n, n });
                face.uvs = new Vector2[] {
                    uvs [i],
                    uvs [i + 1],
                    centerUV
                };
                this.faces.Add(face);
            }
        }
Пример #6
0
        // Approximate a curved face with recursively sub-divided triangles.

        void make(THREEVector3 v1, THREEVector3 v2, THREEVector3 v3)
        {
            Face3 face = new Face3(v1.index, v2.index, v3.index, new Vector3[] { v1.vec, v2.vec, v3.vec });

            // centroid.copy( v1 ).add( v2 ).add( v3 ).divideScalar( 3 );
            //THREEVector3 centroid = new THREEVector3();
            //centroid.vec = Vector3.zero;
            centroid.vec = (v1.vec + v2.vec + v3.vec) / 3.0f;
            float azi = azimuth(centroid);

            face.uvs = new Vector2[] {
                correctUV(v1.uv, v1, azi),
                correctUV(v2.uv, v2, azi),
                correctUV(v3.uv, v3, azi)
            };
            this.faces.Add(face);
        }
Пример #7
0
        List <Vector3> GetSameIdNormalsById(int v_id, float smoothAngle)
        {
            List <Vector3> sameIdNormals = new List <Vector3>();

            for (int i = 0; i < faces.Count; i++)
            {
                Face3     face    = faces [i];
                int[]     indexes = face.GetVertexIndexList();
                Vector3[] normals = face.GetVertexNormals();
                for (int n = 0; n < indexes.Length; n++)
                {
                    int check_id = indexes [n];                     // v_id: 頂点のid

                    if (check_id == v_id)
                    {
//						Vector3 sameNormal = faces[i].vertexNormals[n];
                        Vector3 sameNormal = normals[n];
                        sameIdNormals.Add(sameNormal);
                    }
                }
            }

            //
            List <Vector3> smoothNormals = new List <Vector3>();
            float          checkAngle    = smoothAngle;

            for (int n = 0; n < sameIdNormals.Count; n++)
            {
                Vector3 currentNormal = sameIdNormals[n];
                Vector3 smoothVec     = currentNormal;
                for (int i = 0; i < sameIdNormals.Count; i++)
                {
                    Vector3 checkNormal = sameIdNormals[i];
                    float   angle       = Vector3.Angle(checkNormal, currentNormal);
                    if (angle < checkAngle)
                    {
                        smoothVec += checkNormal;
                    }
                }
                smoothVec.Normalize();
                smoothNormals.Add(smoothVec);
            }
            return(smoothNormals);
        }
Пример #8
0
        // faceから面のnormal計算
        public void computeFaceNormals()
        {
            Vector3 cb = new Vector3(), ab = new Vector3();

            for (int f = 0, fl = this.faces.Count; f < fl; f++)
            {
                Face3 face = this.faces[f];

                Vector3 vA = this.vertices[face.a];
                Vector3 vB = this.vertices[face.b];
                Vector3 vC = this.vertices[face.c];

                cb = vC - vB;
                ab = vA - vB;
                cb = Vector3.Cross(cb, ab);

                cb.Normalize();

                face.normal = cb;
            }
        }
Пример #9
0
        public UnityEngine.Mesh CreateAndGetMesh_Simple()
        {
            UnityEngine.Mesh mesh = new UnityEngine.Mesh();

            List <int> t_triangle = new List <int> ();

            for (int i = 0; i < faces.Count; i++)
            {
                Face3 face = faces [i];
                t_triangle.AddRange(face.GetTriangles());
            }

            // uv
            List <Vector2> t_uv = new List <Vector2> (new Vector2[vertices.Count]);

            for (int i = 0; i < faces.Count; i++)
            {
                List <int> indexes = faces [i].GetVertexIndexList();
                for (int n = 0; n < indexes.Count; n++)
                {
                    int     v_id = indexes [n];             // v_id: 頂点のid
                    Vector2 uv   = faceVertexUvs [i] [n];   //  i 番目のfaceのn番目のuv
                    uv.x        = 1.0f - uv.x;              // flip x
                    t_uv [v_id] = uv;
                }
            }

            mesh.vertices  = vertices.ToArray();
            mesh.triangles = t_triangle.ToArray();
            mesh.uv        = t_uv.ToArray();

            mesh.RecalculateBounds();
            //mesh.UploadMeshData(true);

            return(mesh);
        }
Пример #10
0
 public static Vector3 randomPointInFace(Face3 face, Geometry geometry, JsBoolean useCachedAreas) { return null; }
        /*
         * public float width;
         * public float height;
         *
         * int widthSegments;
         * int heightSegments;
         */
        public PlaneGeometry(float width, float height, int widthSegments, int heightSegments)
        {
            /*
             * this.width = width;
             * this.height = height;
             *
             * this.widthSegments = widthSegments;
             * this.heightSegments = heightSegments;
             */

            int   ix, iz;
            float width_half  = width / 2;
            float height_half = height / 2;

            int gridX = widthSegments;
            int gridZ = heightSegments;

            int gridX1 = gridX + 1;
            int gridZ1 = gridZ + 1;

            float segment_width  = width / gridX;
            float segment_height = height / gridZ;


            Vector3 normal = new Vector3(0, 0, 1);

            //float uvFactorX = 1.0f/widthSegments;
            //float uvFactorY = 1.0f/heightSegments;

            for (iz = 0; iz < gridZ1; iz++)
            {
                for (ix = 0; ix < gridX1; ix++)
                {
                    var x = ix * segment_width - width_half;
                    var y = iz * segment_height - height_half;

                    this.vertices.Add(new Vector3(x, -y, 0));
                    //this.uvs.Add( new Vector2(ix*uvFactorX, 1.0f - iz*uvFactorY));
                }
            }

            for (iz = 0; iz < gridZ; iz++)
            {
                for (ix = 0; ix < gridX; ix++)
                {
                    int a = ix + gridX1 * iz;
                    int b = ix + gridX1 * (iz + 1);
                    int c = (ix + 1) + gridX1 * (iz + 1);
                    int d = (ix + 1) + gridX1 * iz;

                    Vector2 uva = new Vector2((float)ix / gridX, 1 - (float)iz / gridZ);
                    Vector2 uvb = new Vector2((float)ix / gridX, 1 - (float)(iz + 1) / gridZ);
                    Vector2 uvc = new Vector2((float)(ix + 1) / gridX, 1 - (float)(iz + 1) / gridZ);
                    Vector2 uvd = new Vector2((float)(ix + 1) / gridX, 1 - (float)iz / gridZ);

                    Face3 face0 = new Face3(a, b, d, new Vector3[] { normal, normal, normal });
                    //face.normal.copy( normal );
                    //face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
                    //face.materialIndex = materialIndex;

                    face0.uvs = new Vector2[] { uva, uvb, uvd };
                    this.faces.Add(face0);

                    Face3 face1 = new Face3(b, c, d, new Vector3[] { normal, normal, normal });
                    //face.normal.copy( normal );
                    //face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
                    //face.materialIndex = materialIndex;

                    face1.uvs = new Vector2[] { uvb, uvc, uvd };
                    this.faces.Add(face1);
                }
            }

            //this.computeCentroids();
            //
        }
Пример #12
0
    // Use this for initialization
    protected override void Init()
    {
        base.Init();

        THREE.MeshThreeJs drawNormalMesh;

        THREE.MeshThreeJs threeMesh;
        threeMesh          = new THREE.MeshThreeJs(new THREE.SphereGeometry(75, 20, 10), material);
        threeMesh.position = new Vector3(-400, 0, 200);
        scene.Add(threeMesh);

        threeMesh          = new THREE.MeshThreeJs(new THREE.IcosahedronGeometry(75, 1), material);
        threeMesh.position = new Vector3(-200, 0, 200);
        scene.Add(threeMesh);

        threeMesh          = new THREE.MeshThreeJs(new THREE.OctahedronGeometry(75, 2), material);
        threeMesh.position = new Vector3(0, 0, 200);
        scene.Add(threeMesh);

        threeMesh          = new THREE.MeshThreeJs(new THREE.TetrahedronGeometry(75, 0), material);
        threeMesh.position = new Vector3(200, 0, 200);
        scene.Add(threeMesh);

        threeMesh          = new THREE.MeshThreeJs(new THREE.PlaneGeometry(100, 100, 4, 4), material);
        threeMesh.position = new Vector3(-400, 0, 0);
        scene.Add(threeMesh);

        threeMesh          = new THREE.MeshThreeJs(new THREE.BoxGeometry(100, 100, 100, 4, 4, 4), material);
        threeMesh.position = new Vector3(-200, 0, 0);
        scene.Add(threeMesh);

        drawNormalMesh = threeMesh;         // Draw Normal Mesh

        threeMesh          = new THREE.MeshThreeJs(new THREE.CircleGeometry(50, 20, 0, Mathf.PI * 2), material);
        threeMesh.position = new Vector3(0, 0, 0);
        scene.Add(threeMesh);

        threeMesh          = new THREE.MeshThreeJs(new THREE.RingGeometry(10, 50, 20, 5, 0, Mathf.PI * 2), material);
        threeMesh.position = new Vector3(200, 0, 0);
        scene.Add(threeMesh);

        threeMesh          = new THREE.MeshThreeJs(new THREE.CylinderGeometry(25, 75, 100, 40, 5, false), material);
        threeMesh.position = new Vector3(400, 0, 0);
        scene.Add(threeMesh);


        //
        List <Vector3> points = new List <Vector3>();

        for (var i = 0; i < 50; i++)
        {
            points.Add(new Vector3(Mathf.Sin(i * 0.2f) * Mathf.Sin(i * 0.1f) * 15 + 50, 0, (i - 5) * 2));
        }

        threeMesh          = new THREE.MeshThreeJs(new THREE.LatheGeometry(points, 20), material);
        threeMesh.position = new Vector3(-400, 0, -200);
        scene.Add(threeMesh);

        threeMesh          = new THREE.MeshThreeJs(new THREE.TorusGeometry(50, 20, 20, 20), material);
        threeMesh.position = new Vector3(-200, 0, -200);
        scene.Add(threeMesh);

        threeMesh          = new THREE.MeshThreeJs(new THREE.TorusKnotGeometry(50, 10, 50, 20), material);
        threeMesh.position = new Vector3(0, 0, -200);
        scene.Add(threeMesh);

        /*
         * threeMesh = new THREE.AxisHelper( 50 );
         * threeMesh.position.set( 200, 0, -200 );
         * scene.Add( threeMesh );
         *
         * threeMesh = new THREE.ArrowHelper( new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 0 ), 50 );
         * threeMesh.position.set( 400, 0, -200 );
         * scene.Add( threeMesh );
         */

        THREE.Line lineMesh = new THREE.Line(new THREE.Geometry(), wireMaterial);
        lineMesh.position = drawNormalMesh.position;

        THREE.Geometry geo = drawNormalMesh.geo;
        for (int i = 0; i < geo.faces.Count; i++)
        {
            THREE.Face3 _face = geo.faces[i];
            int[]       tri   = _face.GetTriangles();

            for (int n = 0; n < tri.Length; n++)
            {
                Vector3           normal = _face.vertexNormals[n];
                THREE.ArrowHelper arrow  = new THREE.ArrowHelper(normal, geo.vertices[tri[n]], 10, Color.green);
                lineMesh.Add(arrow);
            }
        }

        scene.Add(lineMesh);
    }
Пример #13
0
        void buildPlane(string u, string v, int udir, int vdir, float width, float height, float depth, int materialIndex)
        {
            string w = "z";
            int    ix, iy;
            int    gridX       = this.widthSegments;
            int    gridY       = this.heightSegments;
            float  width_half  = width / 2.0f;
            float  height_half = height / 2.0f;
            int    offset      = this.vertices.Count;


            if ((u == "x" && v == "y") || (u == "y" && v == "x"))
            {
                w = "z";
            }
            else if ((u == "x" && v == "z") || (u == "z" && v == "x"))
            {
                w     = "y";
                gridY = depthSegments;
            }
            else if ((u == "z" && v == "y") || (u == "y" && v == "z"))
            {
                w     = "x";
                gridX = depthSegments;
            }


            int _u = IndexFromStr(u);
            int _v = IndexFromStr(v);
            int _w = IndexFromStr(w);

            int     gridX1         = gridX + 1;
            int     gridY1         = gridY + 1;
            float   segment_width  = width / gridX;
            float   segment_height = height / gridY;
            Vector3 normal         = new Vector3();

            normal [_w] = depth > 0 ? 1 : -1;

            //float uvFactorX = 1.0f/widthSegments;
            //float uvFactorY = 1.0f/heightSegments;

            for (iy = 0; iy < gridY1; iy++)
            {
                for (ix = 0; ix < gridX1; ix++)
                {
                    Vector3 vector = new Vector3();
                    vector [_u] = (ix * segment_width - width_half) * udir;
                    vector [_v] = (iy * segment_height - height_half) * vdir;
                    vector [_w] = depth;

                    this.vertices.Add(vector);
                }
            }

            for (iy = 0; iy < gridY; iy++)
            {
                for (ix = 0; ix < gridX; ix++)
                {
                    int a = ix + gridX1 * iy;
                    int b = ix + gridX1 * (iy + 1);
                    int c = (ix + 1) + gridX1 * (iy + 1);
                    int d = (ix + 1) + gridX1 * iy;

                    Vector2 uva = new Vector2((float)ix / gridX, 1 - (float)iy / gridY);
                    Vector2 uvb = new Vector2((float)ix / gridX, 1 - (float)(iy + 1) / gridY);
                    Vector2 uvc = new Vector2((float)(ix + 1) / gridX, 1 - (float)(iy + 1) / gridY);
                    Vector2 uvd = new Vector2((float)(ix + 1) / gridX, 1 - (float)iy / gridY);

                    Face3 face = new Face3(a + offset, b + offset, d + offset);
                    face.vertexNormals = new Vector3[] { normal, normal, normal };
                    face.uvs           = new Vector2[] { uva, uvb, uvd };
                    this.faces.Add(face);

                    face = new Face3(b + offset, c + offset, d + offset);
                    face.vertexNormals = new Vector3[] { normal, normal, normal };
                    face.uvs           = new Vector2[] { uvb, uvc, uvd };
                    this.faces.Add(face);
                }
            }
        }
Пример #14
0
 public PolyhedronGeometry(Vector3[] vertices, Face3[] faces, JsNumber radius, JsNumber detail) { }
Пример #15
0
        public TubeGeometry(Curve path, int segments = 64, float radius = 1, int radialSegments = 8, bool closed = false)
        {
            //this.path = path;

            List <List <int> > grid = new List <List <int> > ();

            //Vector3 tangent;
            Vector3 normal;
            Vector3 binormal;

            int numpoints = segments + 1;

            //float x, y, z;
            //float tx, ty, tz;
            float u, v;

            float   cx, cy;
            Vector3 pos, pos2 = new Vector3();
            int     ip, jp;
            int     a, b, c, d;
            Vector2 uva, uvb, uvc, uvd;


            var frames = new THREE.TubeGeometry.FrenetFrames(path, segments, closed);

//			tangents = frames.tangents;
//			normals = frames.normals;
//			binormals = frames.binormals;

            // proxy internals
            this.tangents  = frames.tangents;
            this.normals   = frames.normals;
            this.binormals = frames.binormals;

//		function vert( x, y, z ) {
//
//			return scope.vertices.push( new THREE.Vector3( x, y, z ) ) - 1;
//
//		}

            // consruct the grid

            for (int i = 0; i < numpoints; i++)
            {
                //grid[ i ] = [];
                grid.Add(new List <int> ());

                u = (float)i / (numpoints - 1);

                pos = path.getPointAt(u);

                //tangent = tangents [i];
                normal   = normals [i];
                binormal = binormals [i];

                for (int j = 0; j < radialSegments; j++)
                {
                    v = (float)j / radialSegments * 2.0f * Mathf.PI;

                    cx = -radius *Mathf.Cos(v);                       // TODO: Hack: Negating it so it faces outside.

                    cy = radius * Mathf.Sin(v);

                    //pos2.copy( pos );
                    pos2    = (pos);
                    pos2.x += cx * normal.x + cy * binormal.x;
                    pos2.y += cx * normal.y + cy * binormal.y;
                    pos2.z += cx * normal.z + cy * binormal.z;

                    //grid[ i ][ j ] = vert( pos2.x, pos2.y, pos2.z );
                    grid [i].Add(vert(pos2.x, pos2.y, pos2.z));
                }
            }

            // construct the mesh

            for (int i = 0; i < segments; i++)
            {
                for (int j = 0; j < radialSegments; j++)
                {
                    ip = (closed) ? (i + 1) % segments : i + 1;
                    jp = (j + 1) % radialSegments;

                    a = grid[i][j];                                     // *** NOT NECESSARILY PLANAR ! ***
                    b = grid[ip][j];
                    c = grid[ip][jp];
                    d = grid[i][jp];

                    uva = new Vector2((float)i / segments, (float)j / radialSegments);
                    uvb = new Vector2((float)(i + 1) / segments, (float)j / radialSegments);
                    uvc = new Vector2((float)(i + 1) / segments, (float)(j + 1) / radialSegments);
                    uvd = new Vector2((float)i / segments, (float)(j + 1) / radialSegments);

                    Face3 face0 = new Face3(a, b, d);
                    face0.uvs = new Vector2[] { uva, uvb, uvd };
                    this.faces.Add(face0);

                    Face3 face1 = new Face3(b, c, d);
                    face1.uvs = new Vector2[] { uvb, uvc, uvd };
                    this.faces.Add(face1);
                }
            }

            //this.computeFaceNormals();
            //this.computeVertexNormals();
        }
        public LatheGeometry(List <Vector3> points, int segments = 20, float phiStart = 0, float phiLength = Mathf.PI * 2)
        {
            float inversePointLength = 1.0f / (points.Count - 1);
            float inverseSegments    = 1.0f / segments;

            for (int i = 0, il = segments; i <= il; i++)
            {
                float phi = phiStart + i * inverseSegments * phiLength;

                float c = Mathf.Cos(phi),
                      s = Mathf.Sin(phi);

                for (int j = 0, jl = points.Count; j < jl; j++)
                {
                    var pt = points [j];

                    Vector3 vertex = new Vector3();

                    vertex.x = c * pt.x - s * pt.y;
                    vertex.y = s * pt.x + c * pt.y;
                    vertex.z = pt.z;

                    this.vertices.Add(vertex);
                }
            }

            int np = points.Count;

            for (int i = 0, il = segments; i < il; i++)
            {
                for (int j = 0, jl = points.Count - 1; j < jl; j++)
                {
                    int _base = j + np * i;
                    int a     = _base;
                    int b     = _base + np;
                    int c     = _base + 1 + np;
                    int d     = _base + 1;

                    float u0 = i * inverseSegments;
                    float v0 = j * inversePointLength;
                    float u1 = u0 + inverseSegments;
                    float v1 = v0 + inversePointLength;

                    Face3 face0 = new Face3(a, b, d);
                    face0.uvs = new Vector2[] {
                        new Vector2(u0, v0),
                        new Vector2(u1, v0),
                        new Vector2(u0, v1)
                    };
                    this.faces.Add(face0);

                    Face3 face1 = new Face3(b, c, d);
                    face1.uvs = new Vector2[] {
                        new Vector2(u1, v0),
                        new Vector2(u1, v1),
                        new Vector2(u0, v1)
                    };
                    this.faces.Add(face1);
                }
            }

            this.mergeVertices();
            this.computeFaceNormals();
            this.computeVertexNormals();
        }
Пример #17
0
        void f4(int a, int b, int c, int d, Shape shape, List <Vector3> wallContour, int stepIndex, int stepsLength, int contourIndex1, int contourIndex2, int shapesOffset, WorldUVGenerator uvgen, Option options, bool reverse, Quaternion tQ0, Quaternion tQ1)
        {
            a += shapesOffset;
            b += shapesOffset;
            c += shapesOffset;
            d += shapesOffset;

            List <Vector2> uvs = uvgen.generateSideWallUV(this, shape, wallContour, a, b, c, d,
                                                          stepIndex, stepsLength, contourIndex1, contourIndex2);

            Face3 face0;

            if (faceIndex >= faces.Count)
            {
                face0 = new Face3(a, b, d);
                this.faces.Add(face0);
            }
            else
            {
                face0   = faces[faceIndex];
                face0.a = a;
                face0.b = b;
                face0.c = d;
            }

            face0.uvs = new Vector2[] { uvs[0], uvs[1], uvs[3] };
            faceIndex++;

            Face3 face1;

            if (faceIndex >= faces.Count)
            {
                face1 = new Face3(b, c, d);
                this.faces.Add(face1);
            }
            else
            {
                face1   = faces[faceIndex];
                face1.a = b;
                face1.b = c;
                face1.c = d;
            }

            face1.uvs = new Vector2[] { uvs[1], uvs[2], uvs[3] };
            faceIndex++;

            //
            Vector3 normal0;
            Vector3 normal1;

            TubeGeometry.FrenetFrames splineTube = options.frames;
            if (shape.normals != null)
            {
                if (splineTube != null)
                {
                    Vector3 n0 = shape.normals[contourIndex1];
                    if (reverse)
                    {
                        n0.y *= -1;
                    }
                    normal0 = tQ0 * n0;
                    normal0.Normalize();

                    Vector3 n1 = shape.normals[contourIndex1];
                    if (reverse)
                    {
                        n1.y *= -1;
                    }
                    normal1 = tQ1 * n1;
                    normal1.Normalize();
                }
                else
                {
                    Vector3 norm = shape.normals[contourIndex1];
                    if (reverse)
                    {
                        norm.y *= -1;
                    }
                    normal0 = norm;
                    normal1 = norm;
                }

//				face0.vertexNormals = new Vector3[]{normal0, normal0, normal1 };
//				face1.vertexNormals = new Vector3[]{normal0, normal1, normal1 };

                face0.vertexNormals[0] = normal0;
                face0.vertexNormals[1] = normal0;
                face0.vertexNormals[2] = normal1;

                face1.vertexNormals[0] = normal0;
                face1.vertexNormals[1] = normal1;
                face1.vertexNormals[2] = normal1;
            }
            //

            // TODO: faceVertexUvs の変更で問題点ないか確認
//			List<Vector2> uvs0;
//			if(faceIndex - 2 >= this.faceVertexUvs.Count){
//				uvs0 = new List<Vector2>( new Vector2[]{ uvs[ 0 ], uvs[ 1 ], uvs[ 3 ] } );
//				this.faceVertexUvs.Add(uvs0);
//			}else{
//				this.faceVertexUvs[faceIndex - 2] = new List<Vector2>( new Vector2[]{ uvs[ 0 ], uvs[ 1 ], uvs[ 3 ] } );
//			}


//			List<Vector2> uvs1;
//			if(faceIndex - 1 >= this.faceVertexUvs.Count){
//				uvs1 = new List<Vector2>( new Vector2[]{ uvs[ 1 ], uvs[ 2 ], uvs[ 3 ] } );
//				this.faceVertexUvs.Add(uvs1);
//			}else{
//				this.faceVertexUvs[faceIndex - 1] = new List<Vector2>( new Vector2[]{ uvs[ 1 ], uvs[ 2 ], uvs[ 3 ] } );
//			}

//			this.faceVertexUvs.Add( new List<Vector2>( new Vector2[]{ Vector2.one, Vector2.one, Vector2.one, Vector2.one } )); // Debug
//			this.faceVertexUvs.Add( new List<Vector2>( new Vector2[]{ Vector2.one, Vector2.one, Vector2.one, Vector2.one } )); // Debug
        }
Пример #18
0
        void processEdge(int a, int b, List <Vector3> vertices, Dictionary <string, Edge> map, Face3 face, MetaVertex[] metaVertices)
        {
            int vertexIndexA = Mathf.Min(a, b);
            int vertexIndexB = Mathf.Max(a, b);

            string key = vertexIndexA + "_" + vertexIndexB;

            Edge edge;

            //if ( key in map ) {
            if (map.ContainsKey(key))
            {
                edge = map[key];
            }
            else
            {
                Vector3 vertexA = vertices[vertexIndexA];
                Vector3 vertexB = vertices[vertexIndexB];

                edge         = new Edge();
                edge.a       = vertexA;
                edge.b       = vertexB;
                edge.newEdge = -1;
                edge.faces   = new List <Face3>();

                edge.key = key;

                map[key] = edge;
            }

            edge.faces.Add(face);

            metaVertices[a].edges.Add(edge);
            metaVertices[b].edges.Add(edge);
        }
Пример #19
0
        //
        public int mergeVertices()
        {
            //var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
            Dictionary <string, int> verticesMap = new Dictionary <string, int> ();
            List <Vector3>           unique      = new List <Vector3> ();
            List <int> changes = new List <int> ();

            float precisionPoints = 4;             // number of decimal points, eg. 4 for epsilon of 0.0001
            float precision       = Mathf.Pow(10, precisionPoints);

            for (int i = 0, il = this.vertices.Count; i < il; i++)
            {
                Vector3 v   = this.vertices [i];
                string  key = Mathf.Round(v.x * precision).ToString() + '_' + Mathf.Round(v.y * precision).ToString() + '_' + Mathf.Round(v.z * precision).ToString();

                int changeId;
                //if ( verticesMap[ key ] == null ) {
                if (!verticesMap.ContainsKey(key))
                {
                    verticesMap [key] = i;
                    unique.Add(this.vertices [i]);
                    //changes[ i ] = unique.Count - 1;
                    changeId = unique.Count - 1;
                }
                else
                {
                    //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
                    //changes[ i ] = changes[ verticesMap[ key ] ];
                    changeId = changes [verticesMap [key]];
                }
                changes.Add(changeId);
            }


            // if faces are completely degenerate after merging vertices, we
            // have to remove them from the geometry.
            List <int> faceIndicesToRemove = new List <int> ();

            for (int i = 0, il = this.faces.Count; i < il; i++)
            {
                Face3 face = this.faces [i];

                face.a = changes [face.a];
                face.b = changes [face.b];
                face.c = changes [face.c];

                List <int> indices = new List <int> (new int[] { face.a, face.b, face.c });

                //int dupIndex = -1;

                // if any duplicate vertices are found in a Face3
                // we have to remove the face as nothing can be saved
                for (int n = 0; n < 3; n++)
                {
                    if (indices [n] == indices [(n + 1) % 3])
                    {
                        //dupIndex = n;
                        faceIndicesToRemove.Add(i);
                        break;
                    }
                }
            }

            for (int i = faceIndicesToRemove.Count - 1; i >= 0; i--)
            {
                int idx = faceIndicesToRemove [i];
                this.faces.RemoveAt(idx);

                for (int j = this.faceVertexUvs.Count - 1; j >= 0; j--)
                {
                    this.faceVertexUvs [j].RemoveAt(idx);
                }
            }

            // Use unique set of vertices

            int diff = this.vertices.Count - unique.Count;

            Debug.Log(diff);
            this.vertices = unique;

            return(diff);
        }
Пример #20
0
 public static Vector3 randomPointInFace(Face3 face, Geometry geometry, JsBoolean useCachedAreas)
 {
     return(null);
 }
        // Analytically subdivide a face to the required detail level.

        void subdivide(Face3 face, int detail)
        {
            float cols = Mathf.Pow(2.0f, (float)detail);
            //float cells = Mathf.Pow (4.0f, (float)detail);
            THREEVector3 a = prepare(this.t_vertices [face.a]);
            THREEVector3 b = prepare(this.t_vertices [face.b]);
            THREEVector3 c = prepare(this.t_vertices [face.c]);

            List <List <THREEVector3> > v = new List <List <THREEVector3> > ();

            // Construct all of the vertices for this subdivision.

            for (int i = 0; i <= cols; i++)
            {
                //v[ i ] = new List<THREEVector3>();
                List <THREEVector3> vList = new List <THREEVector3> ();
                v.Add(vList);
                //v.Add (new List<THREEVector3>() );

                THREEVector3 aj   = prepare(a.clone().lerp(c, (float)i / cols));
                THREEVector3 bj   = prepare(b.clone().lerp(c, (float)i / cols));
                int          rows = (int)(cols - i);

                for (int j = 0; j <= rows; j++)
                {
                    THREEVector3 vv;
                    if (j == 0 && i == cols)
                    {
                        //v[ i ][ j ] = aj;
                        vv = aj;
                    }
                    else
                    {
                        //v[ i ][ j ] = prepare( aj.clone().lerp( bj, j / rows ) );
                        vv = prepare(aj.clone().lerp(bj, (float)j / rows));
                    }
                    vList.Add(vv);
                }
            }

            // Construct all of the faces.

            for (int i = 0; i < cols; i++)
            {
                for (int j = 0; j < 2 * (cols - i) - 1; j++)
                {
                    int k = Mathf.FloorToInt((float)j / 2.0f);

                    if (j % 2 == 0)
                    {
                        make(
                            v [i] [k + 1],
                            v [i + 1] [k],
                            v [i] [k]
                            );
                    }
                    else
                    {
                        make(
                            v [i] [k + 1],
                            v [i + 1] [k + 1],
                            v [i + 1] [k]
                            );
                    }
                }
            }
        }
        /**
         * Adds a shape to THREE.ShapeGeometry, based on THREE.ExtrudeGeometry.
         */
        void addShape(Shape shape, Option options)
        {
            int curveSegments = options.curveSegments;

            //Material material = options.material;
            //var uvgen = options.UVGenerator === undefined ? THREE.ExtrudeGeometry.WorldUVGenerator : options.UVGenerator;
            ExtrudeGeometry.WorldUVGenerator uvgen = options.UVGenerator;
            if (uvgen == null)
            {
                uvgen = new ExtrudeGeometry.WorldUVGenerator();
            }

            //BoundingBox shapebb = this.shapebb;
            //

            int i, l;

            int shapesOffset = this.vertices.Count;
            ShapeAndHoleObject shapePoints = shape.extractPoints(curveSegments);

            List <Vector3>         vertices = shapePoints.shapeVertices;
            List <List <Vector3> > holes    = shapePoints.holes;

            bool reverse = !Shape.Utils.isClockWise(vertices);

            if (reverse)
            {
                //vertices = vertices.reverse();
                vertices.Reverse();

                // Maybe we should also check if holes are in the opposite direction, just to be safe...

                for (i = 0, l = holes.Count; i < l; i++)
                {
                    List <Vector3> hole = holes[i];

                    if (Shape.Utils.isClockWise(hole))
                    {
                        //holes[ i ] = hole.reverse();
                        hole.Reverse();
                        holes[i] = hole;
                    }
                }

                reverse = false;
            }

            List <List <int> > faces = Shape.Utils.triangulateShape(vertices, holes);

            // Vertices
            //var contour = vertices;

            for (i = 0, l = holes.Count; i < l; i++)
            {
                List <Vector3> hole = holes[i];
                //vertices = vertices.concat( hole );
                vertices.AddRange(hole);
            }

            Vector3    vert;
            int        vlen = vertices.Count;
            List <int> face;
            int        flen = faces.Count;

            //var cont;
            //int clen = contour.Count;

            for (i = 0; i < vlen; i++)
            {
                vert = vertices[i];

                this.vertices.Add(new Vector3(vert.x, vert.y, 0));
            }

            for (i = 0; i < flen; i++)
            {
                face = faces[i];

                int a = face[0] + shapesOffset;
                int b = face[1] + shapesOffset;
                int c = face[2] + shapesOffset;

                Face3 f = new Face3(a, b, c);
                f.uvs = uvgen.generateBottomUV(this, shape, a, b, c).ToArray();
                this.faces.Add(f);

                //this.faceVertexUvs.Add( new List<Vector2>( new Vector2[]{ new Vector2(0.0f, 0.0f), new Vector2(0.0f, 0.0f), new Vector2(0.0f, 0.0f) })); // debug
            }
        }
Пример #23
0
        public CylinderGeometry(float radiusTop = 5, float radiusBottom = 5, float height = 10, int radialSegments = 8, int heightSegments = 1, bool openEnded = false)
        {
            float heightHalf = height / 2.0f;

            int x, y;
            List <List <int> >     vertices = new List <List <int> > ();
            List <List <Vector2> > uvs      = new List <List <Vector2> > ();

            for (y = 0; y <= heightSegments; y++)
            {
                List <int>     verticesRow = new List <int> ();
                List <Vector2> uvsRow      = new List <Vector2> ();

                float v      = (float)y / heightSegments;
                float radius = v * (radiusBottom - radiusTop) + radiusTop;

                for (x = 0; x <= radialSegments; x++)
                {
                    float u = (float)x / radialSegments;

                    Vector3 vertex = new Vector3();
                    vertex.x = radius * Mathf.Sin(u * Mathf.PI * 2);
                    vertex.y = -v * height + heightHalf;
                    vertex.z = radius * Mathf.Cos(u * Mathf.PI * 2);

                    this.vertices.Add(vertex);

                    verticesRow.Add(this.vertices.Count - 1);
                    uvsRow.Add(new Vector2(u, 1 - v));
                }

                vertices.Add(verticesRow);
                uvs.Add(uvsRow);
            }

            float   tanTheta = (radiusBottom - radiusTop) / height;
            Vector3 na, nb;

            for (x = 0; x < radialSegments; x++)
            {
                if (radiusTop != 0)
                {
                    na = (this.vertices [vertices [0] [x]]);
                    nb = (this.vertices [vertices [0] [x + 1]]);
                }
                else
                {
                    na = (this.vertices [vertices [1] [x]]);
                    nb = (this.vertices [vertices [1] [x + 1]]);
                }

                na.y = (Mathf.Sqrt(na.x * na.x + na.z * na.z) * tanTheta);
                nb.y = (Mathf.Sqrt(nb.x * nb.x + nb.z * nb.z) * tanTheta);
                na.Normalize();
                nb.Normalize();

                for (y = 0; y < heightSegments; y++)
                {
                    int v1 = vertices [y] [x];
                    int v2 = vertices [y + 1] [x];
                    int v3 = vertices [y + 1] [x + 1];
                    int v4 = vertices [y] [x + 1];

                    Vector3 n1 = (na);
                    Vector3 n2 = (na);
                    Vector3 n3 = (nb);
                    Vector3 n4 = (nb);

                    Vector2 uv1 = (uvs [y] [x]);
                    Vector2 uv2 = (uvs [y + 1] [x]);
                    Vector2 uv3 = (uvs [y + 1] [x + 1]);
                    Vector2 uv4 = (uvs [y] [x + 1]);

                    Face3 face0 = new Face3(v1, v2, v4, new Vector3[] { n1, n2, n4 });
                    face0.uvs = new Vector2[] { uv1, uv2, uv4 };
                    this.faces.Add(face0);

                    Face3 face1 = new Face3(v2, v3, v4, new Vector3[] { (n2), n3, (n4) });
                    face1.uvs = new Vector2[] {
                        (uv2),
                        uv3,
                        (uv4)
                    };
                    this.faces.Add(face1);
                }
            }

            // top cap

            if (openEnded == false && radiusTop > 0)
            {
                this.vertices.Add(new Vector3(0, heightHalf, 0));

                for (x = 0; x < radialSegments; x++)
                {
                    int v1 = vertices [0] [x];
                    int v2 = vertices [0] [x + 1];
                    int v3 = this.vertices.Count - 1;

                    Vector3 n1 = new Vector3(0, 1, 0);
                    Vector3 n2 = new Vector3(0, 1, 0);
                    Vector3 n3 = new Vector3(0, 1, 0);

                    Vector2 uv1 = (uvs [0] [x]);
                    Vector2 uv2 = (uvs [0] [x + 1]);
                    Vector2 uv3 = new Vector2(uv2.x, 0);

                    Face3 face = new Face3(v1, v2, v3, new Vector3[] { n1, n2, n3 });
                    face.uvs = new Vector2[] { uv1, uv2, uv3 };
                    this.faces.Add(face);
                }
            }

            // bottom cap

            if (openEnded == false && radiusBottom > 0)
            {
                this.vertices.Add(new Vector3(0, -heightHalf, 0));

                for (x = 0; x < radialSegments; x++)
                {
                    int v1 = vertices [y] [x + 1];
                    int v2 = vertices [y] [x];
                    int v3 = this.vertices.Count - 1;

                    Vector3 n1 = new Vector3(0, -1, 0);
                    Vector3 n2 = new Vector3(0, -1, 0);
                    Vector3 n3 = new Vector3(0, -1, 0);

                    Vector2 uv1 = (uvs [y] [x + 1]);
                    Vector2 uv2 = (uvs [y] [x]);
                    //Vector2 uv3 = new Vector2( uv2.u, 1 );
                    Vector2 uv3 = new Vector2(uv2.x, 1);

                    Face3 face = new Face3(v1, v2, v3, new Vector3[] { n1, n2, n3 });
                    face.uvs = new Vector2[] { uv1, uv2, uv3 };
                    this.faces.Add(face);
                }
            }

            //this.mergeVertices ();

            //this.computeVertexNormals();
            this.computeFaceNormals();
        }
        public TorusKnotGeometry(float radius = 10, float tube = 4, int radialSegments = 64, int tubularSegments = 8, float p = 2, float q = 3, float heightScale = 1)
        {
            List <List <int> > grid = new List <List <int> > (radialSegments);

            Vector3 tang  = new Vector3();
            Vector3 n     = new Vector3();
            Vector3 bitan = new Vector3();

            for (int i = 0; i < radialSegments; ++i)
            {
                grid.Add(new List <int> (tubularSegments));
                float   u  = (float)i / radialSegments * 2 * p * Mathf.PI;
                Vector3 p1 = getPos(u, q, p, radius, heightScale);
                Vector3 p2 = getPos(u + 0.01f, q, p, radius, heightScale);
                //tang.subVectors( p2, p1 );
                //n.addVectors( p2, p1 );
                tang = p2 - p1;
                n    = p2 + p1;

                //bitan.crossVectors( tang, n );
                //n.crossVectors( bitan, tang );

                bitan = Vector3.Cross(tang, n);
                n     = Vector3.Cross(bitan, tang);

                bitan.Normalize();
                n.Normalize();

                for (int j = 0; j < tubularSegments; ++j)
                {
                    float v  = (float)j / tubularSegments * 2 * Mathf.PI;
                    float cx = -tube *Mathf.Cos(v);                        // TODO: Hack: Negating it so it faces outside.

                    float cy = tube * Mathf.Sin(v);

                    Vector3 pos = new Vector3();
                    pos.x = p1.x + cx * n.x + cy * bitan.x;
                    pos.y = p1.y + cx * n.y + cy * bitan.y;
                    pos.z = p1.z + cx * n.z + cy * bitan.z;

                    this.vertices.Add(pos);
                    //grid[ i ][ j ] = this.vertices.Count - 1;
                    grid [i].Add(this.vertices.Count - 1);
                }
            }

            for (int i = 0; i < radialSegments; ++i)
            {
                for (int j = 0; j < tubularSegments; ++j)
                {
                    int ip = (i + 1) % radialSegments;
                    int jp = (j + 1) % tubularSegments;

                    int a = grid [i] [j];
                    int b = grid [ip] [j];
                    int c = grid [ip] [jp];
                    int d = grid [i] [jp];

                    Vector2 uva = new Vector2((float)i / radialSegments, (float)j / tubularSegments);
                    Vector2 uvb = new Vector2((float)(i + 1) / radialSegments, (float)j / tubularSegments);
                    Vector2 uvc = new Vector2((float)(i + 1) / radialSegments, (float)(j + 1) / tubularSegments);
                    Vector2 uvd = new Vector2((float)i / radialSegments, (float)(j + 1) / tubularSegments);

                    Face3 face0 = new Face3(a, b, d);
                    face0.uvs = new Vector2[] { uva, uvb, uvd };
                    this.faces.Add(face0);

                    Face3 face1 = new Face3(b, c, d);
                    face1.uvs = new Vector2[] { (uvb), uvc, (uvd) };
                    this.faces.Add(face1);
                }
            }

            this.computeFaceNormals();
            this.computeVertexNormals();
        }
        // Use this for initialization
        public ParametricGeometry(Func <float, float, Vector3> func, int slices, int stacks)
        {
            List <Vector3> verts = this.vertices;
            List <Face3>   faces = this.faces;
//			List<List<Vector2>> uvs = this.faceVertexUvs;

            //int i, j;
            Vector3 p;
            float   u, v;

            //int stackCount = stacks + 1;
            int sliceCount = slices + 1;

            for (int i = 0; i <= stacks; i++)
            {
                v = (float)i / stacks;

                for (int j = 0; j <= slices; j++)
                {
                    u = (float)j / slices;

                    p = func(u, v);
                    verts.Add(p);
                }
            }

            int     a, b, c, d;
            Vector2 uva, uvb, uvc, uvd;

            for (int i = 0; i < stacks; i++)
            {
                for (int j = 0; j < slices; j++)
                {
                    a = i * sliceCount + j;
                    b = i * sliceCount + j + 1;
                    c = (i + 1) * sliceCount + j + 1;
                    d = (i + 1) * sliceCount + j;

                    uva = new Vector2((float)j / slices, (float)i / stacks);
                    uvb = new Vector2((float)(j + 1) / slices, (float)i / stacks);
                    uvc = new Vector2((float)(j + 1) / slices, (float)(i + 1) / stacks);
                    uvd = new Vector2((float)j / slices, (float)(i + 1) / stacks);

                    Face3 face0 = new Face3(a, b, d);
                    face0.uvs = new Vector2[] { uva, uvb, uvd };
                    faces.Add(face0);

                    Face3 face1 = new Face3(b, c, d);
                    face1.uvs = new Vector2[] { (uvb), uvc, (uvd) };
                    faces.Add(face1);
                }
            }

            // console.log(this);

            // magic bullet
            // var diff = this.mergeVertices();
            // console.log('removed ', diff, ' vertices by merging');

            this.computeFaceNormals();
            this.computeVertexNormals();
        }
        //float phiStart;
        //float phiLength;
        //float thetaStart;
        //float thetaLength;

        public SphereGeometry(float radius = 50, int widthSegments = 8, int heightSegments = 6, float phiStart = 0, float phiLength = Mathf.PI * 2, float thetaStart = 0, float thetaLength = Mathf.PI)
        {
            this.radius = radius;

            this.widthSegments  = widthSegments = Mathf.Max(3, Mathf.FloorToInt(widthSegments));
            this.heightSegments = heightSegments = Mathf.Max(2, Mathf.FloorToInt(heightSegments));

            //this.phiStart = phiStart;
            //this.phiLength = phiLength;

            //this.thetaStart = thetaStart;
            //this.thetaLength = thetaLength;

            int x, y;
            List <List <int> >     verticesIndex = new List <List <int> > ();
            List <List <Vector2> > uvs           = new List <List <Vector2> > ();

            for (y = 0; y <= heightSegments; y++)
            {
                List <int>     verticesRow = new List <int> ();
                List <Vector2> uvsRow      = new List <Vector2> ();

                for (x = 0; x <= widthSegments; x++)
                {
                    float u = (float)x / widthSegments;
                    float v = (float)y / heightSegments;

                    Vector3 vertex = new Vector3();
                    vertex.x = -radius *Mathf.Cos(phiStart + u *phiLength) * Mathf.Sin(thetaStart + v * thetaLength);

                    vertex.y = radius * Mathf.Cos(thetaStart + v * thetaLength);
                    vertex.z = radius * Mathf.Sin(phiStart + u * phiLength) * Mathf.Sin(thetaStart + v * thetaLength);

                    this.vertices.Add(vertex);

                    //Vector2 uv = new Vector2( u, 1 - v );
                    //this.uvs.Add( uv );

                    verticesRow.Add(this.vertices.Count - 1);
                    uvsRow.Add(new Vector2(u, 1 - v));
                }

                verticesIndex.Add(verticesRow);
                uvs.Add(uvsRow);
            }

            for (y = 0; y < this.heightSegments; y++)
            {
                for (x = 0; x < this.widthSegments; x++)
                {
                    int v1 = verticesIndex [y] [x + 1];
                    int v2 = verticesIndex [y] [x];
                    int v3 = verticesIndex [y + 1] [x];
                    int v4 = verticesIndex [y + 1] [x + 1];

                    Vector3 n1 = this.vertices[v1].normalized;
                    Vector3 n2 = this.vertices[v2].normalized;
                    Vector3 n3 = this.vertices[v3].normalized;
                    Vector3 n4 = this.vertices[v4].normalized;

//					var uv1 = uvs[ y ][ x + 1 ].clone();
//					var uv2 = uvs[ y ][ x ].clone();
//					var uv3 = uvs[ y + 1 ][ x ].clone();
//					var uv4 = uvs[ y + 1 ][ x + 1 ].clone();

                    Vector2 uv1 = uvs [y] [x + 1];
                    Vector2 uv2 = uvs [y] [x];
                    Vector2 uv3 = uvs [y + 1] [x];
                    Vector2 uv4 = uvs [y + 1] [x + 1];

                    if (Mathf.Abs(this.vertices [v1].y) == this.radius)
                    {
                        Face3 face = new Face3(v1, v3, v4, new Vector3[] { n1, n3, n4 });
                        face.uvs = new Vector2[] { uv1, uv3, uv4 };
                        this.faces.Add(face);
                    }
                    else if (Mathf.Abs(this.vertices [v3].y) == this.radius)
                    {
                        Face3 face = new Face3(v1, v2, v3, new Vector3[] { n1, n2, n3 });
                        face.uvs = new Vector2[] { uv1, uv2, uv3 };
                        this.faces.Add(face);
                    }
                    else
                    {
                        Face3 face0 = new Face3(v1, v2, v4, new Vector3[] { n1, n2, n4 });
                        face0.uvs = new Vector2[] { uv1, uv2, uv4 };
                        this.faces.Add(face0);

                        Face3 face1 = new Face3(v2, v3, v4, new Vector3[] { n2, n3, n4 });
                        face1.uvs = new Vector2[] { uv2, uv3, uv4 };
                        this.faces.Add(face1);
                    }
                }
            }
            //this.computeFaceNormals();
            //this.mergeVertices();
        }
        public RingGeometry(float innerRadius = 0, float outerRadius = 50, int thetaSegments = 8, int phiSegments = 8, float thetaStart = 0, float thetaLength = Mathf.PI * 2)
        {
            List <Vector2> uvs        = new List <Vector2> ();
            float          radius     = innerRadius;
            float          radiusStep = ((outerRadius - innerRadius) / (float)phiSegments);

            for (int i = 0; i <= phiSegments; i++)                // concentric circles inside ring

            {
                for (int o = 0; o <= thetaSegments; o++)                    // number of segments per circle

                {
                    Vector3 vertex  = new Vector3();
                    float   segment = thetaStart + (float)o / thetaSegments * thetaLength;

                    vertex.x = radius * Mathf.Cos(segment);
                    vertex.y = radius * Mathf.Sin(segment);

                    this.vertices.Add(vertex);
                    uvs.Add(new Vector2((vertex.x / outerRadius + 1) / 2.0f, (vertex.y / outerRadius + 1) / 2.0f));
                }
                radius += radiusStep;
            }


            Vector3 n = new Vector3(0, 0, 1);

            for (int i = 0; i < phiSegments; i++)                // concentric circles inside ring

            {
                int thetaSegment = i * thetaSegments;

                for (int o = 0; o <= thetaSegments; o++)                    // number of segments per circle

                {
                    int segment = o + thetaSegment;

                    int v1 = segment + i;
                    int v2 = segment + thetaSegments + i;
                    int v3 = segment + thetaSegments + 1 + i;

                    Face3 face0 = new Face3(v1, v2, v3, new Vector3[] { n, n, n });
                    face0.uvs = new Vector2[] {
                        uvs [v1],
                        uvs [v2],
                        uvs [v3]
                    };
                    this.faces.Add(face0);

                    v1 = segment + i;
                    v2 = segment + thetaSegments + 1 + i;
                    v3 = segment + 1 + i;

                    Face3 face1 = new Face3(v1, v2, v3, new Vector3[] { n, n, n });
                    face1.uvs = new Vector2[] {
                        uvs [v1],
                        uvs [v2],
                        uvs [v3]
                    };
                    this.faces.Add(face1);
                }
            }
        }