public void copyFaceNormalToVertexNormals() { for (int f = 0, fl = this.faces.Count; f < fl; f++) { Face3 face = this.faces[f]; face.SetFaceNormalToVertexNormals(); } }
// 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(); }
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); } }
// 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); }
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); }
// 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; } }
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); }
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(); // }
// 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); }
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); } } }
public PolyhedronGeometry(Vector3[] vertices, Face3[] faces, JsNumber radius, JsNumber detail) { }
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(); }
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 }
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); }
// 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); }
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 } }
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); } } }