private int lastCircle(Vector3 v1, Vector3 v2, SceneBrep scene, Matrix4 m) { _ = createCircleAround(v1, v2); Vector3 center = getCenter(last_circle); Vector3 dif = (v2 - v1) * size; _ = (v2 - v1) * (1 - size); int[] v = new int[cdetail]; for (int i = 0; i < cdetail; i++) { v[i] = scene.AddVertex(Vector3.TransformPosition(last_circle[i] + dif, m)); scene.SetNormal(v[i], Vector3.TransformVector(last_circle[i] - center, m).Normalized()); float r = (last_circle[i].X + 1.1f) / 2.5f; float g = (last_circle[i].Y + 1.1f) / 2.5f; float b = (last_circle[i].Z + 1.1f) / 2.5f; scene.SetColor(v[i], new Vector3(r, g, b)); } for (int i = 0; i < cdetail - 1; i++) { scene.AddTriangle(connect_indices[i], v[i], connect_indices[i + 1]); scene.AddTriangle(connect_indices[i + 1], v[i], v[i + 1]); } scene.AddTriangle(connect_indices[cdetail - 1], v[cdetail - 1], connect_indices[0]); scene.AddTriangle(connect_indices[0], v[cdetail - 1], v[0]); return(cdetail * 2); }
private int CreateTetrahedron(SceneBrep scene, Matrix4 m, Vector3 center, float size) { int[] v = new int[4]; float z = (float)(size * Math.Sqrt(0.5)); Vector3 A = new Vector3(size, 0.0f, -z); Vector3 B = new Vector3(-size, 0.0f, -z); Vector3 C = new Vector3(0.0f, size, z); Vector3 D = new Vector3(0.0f, -size, z); // vertices: v[0] = scene.AddVertex(Vector3.TransformPosition(A, m)); v[1] = scene.AddVertex(Vector3.TransformPosition(B, m)); v[2] = scene.AddVertex(Vector3.TransformPosition(C, m)); v[3] = scene.AddVertex(Vector3.TransformPosition(D, m)); // normal vectors: scene.SetNormal(v[0], Vector3.TransformVector(A, m).Normalized()); scene.SetNormal(v[1], Vector3.TransformVector(B, m).Normalized()); scene.SetNormal(v[2], Vector3.TransformVector(C, m).Normalized()); scene.SetNormal(v[3], Vector3.TransformVector(D, m).Normalized()); // texture coordinates: scene.SetTxtCoord(v[0], new Vector2(1.0f, 0.0f)); scene.SetTxtCoord(v[1], new Vector2(0.0f, 0.0f)); scene.SetTxtCoord(v[2], new Vector2(1.0f, 1.0f)); scene.SetTxtCoord(v[3], new Vector2(0.0f, 1.0f)); // colors: long seed = (long)Math.Min(long.MaxValue, (m.Row3.LengthSquared * 10000.0f)); seed = RandomStatic.numericRecipes(seed); float r = (seed & 255) / 255.0f; seed = RandomStatic.numericRecipes(seed); float g = (seed & 255) / 255.0f; seed = RandomStatic.numericRecipes(seed); float b = (seed & 255) / 255.0f; scene.SetColor(v[0], new Vector3(r, g, b)); r = Math.Min(r + 0.2f, 1.0f); scene.SetColor(v[1], new Vector3(r, g, b)); g = Math.Min(g + 0.2f, 1.0f); scene.SetColor(v[2], new Vector3(r, g, b)); b = Math.Min(b + 0.2f, 1.0f); scene.SetColor(v[3], new Vector3(r, g, b)); // triangle faces: scene.AddTriangle(v[0], v[1], v[2]); scene.AddTriangle(v[2], v[1], v[3]); scene.AddTriangle(v[1], v[0], v[3]); scene.AddTriangle(v[2], v[3], v[0]); return(4); }
void ConnectTwoCircles(SceneBrep scene, List <List <Vector3> > MeshV, int total, int index) { List <int> firstCirc = new List <int>(); List <int> secCirc = new List <int>(); int count = MeshV[index].Count; if (index != 0) { for (int i = total; i > total - count; i--) { firstCirc.Add(i); secCirc.Add(i - count); } //for (int i = 0; i < firstCirc.Count; i++) { // scene.AddLine(firstCirc[i], secCirc[i]); // scene.AddLine(firstCirc[i], secCirc[(i + 1 == secCirc .Count ? 0 : i+1)]); //} } else { for (int i = total; i > total - count; i--) { firstCirc.Add(i); secCirc.Add(total - i + count); } //for (int i = 0; i < firstCirc.Count; i++) { // scene.AddLine(firstCirc[i], secCirc[i]); // scene.AddLine(firstCirc[i], secCirc[(i + 1 == secCirc.Count ? 0 : i+1)]); //} } for (int i = 0; i < firstCirc.Count; i++) { scene.AddTriangle(firstCirc[i], secCirc[i], secCirc[(i + 1 == secCirc.Count ? 0 : i + 1)]); this.GeneratedFaces++; scene.AddTriangle( firstCirc[(i + 1 == firstCirc.Count ? 0 : i + 1)], firstCirc[i], secCirc[(i + 1 == secCirc.Count ? 0 : i + 1)]); this.GeneratedFaces++; } }
/// <summary> /// Do Loop subdivision of the input control triangle mesh. /// </summary> /// <param name="scene">Input scene (must not be changed).</param> /// <param name="epsilon">Reference error toleration (size of undivided triangle).</param> /// <param name="normals">Generate normals? (optional)</param> /// <param name="colors">Generate colors? (optional)</param> /// <param name="txtcoord">Generate texture coordinates? (optional)</param> /// <param name="time">Current time for animation (optional)</param> /// <param name="param">Optional additional parameters.</param> /// <returns>Number of generated points.</returns> public int Subdivide(SceneBrep scene, float epsilon, bool normals, bool colors, bool txtcoord, float time, string param) { result = scene.Clone(); // !!!{{ TODO: put your Loop subdivision code here // pilot: do one (trivial) division int triangles = result.Triangles; int tr; for (tr = 0; tr < triangles; tr++) { int A, B, C; result.GetTriangleVertices(tr, out A, out B, out C); Vector3 vA = result.GetVertex(A); Vector3 vB = result.GetVertex(B); Vector3 vC = result.GetVertex(C); Vector3 vA2 = (vB + vC) * 0.5f; Vector3 vB2 = (vA + vC) * 0.5f; Vector3 vC2 = (vA + vB) * 0.5f; int A2 = result.AddVertex(vA2); int B2 = result.AddVertex(vB2); int C2 = result.AddVertex(vC2); result.AddTriangle(B2, C2, A2); result.AddTriangle(B2, A2, C); result.AddTriangle(C2, B, A2); result.SetTriangleVertices(tr, A, C2, B2); } //result.BuildCornerTable(); return(result.Vertices); // !!!}} }
/// <summary> /// Construct a new control mesh for subdivision (formally the Brep solid..). /// </summary> /// <param name="scene">B-rep scene to be modified</param> /// <param name="m">Transform matrix (object-space to world-space)</param> /// <param name="time">Current time in seconds</param> /// <param name="param">Shape parameters if needed</param> public void ControlMesh(SceneBrep scene, Matrix4 m, float time, string param) { // !!!{{ TODO: put your Control-mesh-construction code here List <int> upper = new List <int>(); upper.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(0, 1, 0), m))); upper.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(1, 1, 0), m))); upper.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(1, 1, 1), m))); upper.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(0, 1, 1), m))); List <int> lower = new List <int>(); lower.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(0, 0, 0), m))); lower.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(1, 0, 0), m))); lower.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(1, 0, 1), m))); lower.Add(scene.AddVertex(Vector3.TransformPosition(new Vector3(0, 0, 1), m))); // Lower face scene.AddTriangle(lower[0], lower[1], lower[2]); scene.AddTriangle(lower[2], lower[3], lower[0]); // Upper face scene.AddTriangle(upper[2], upper[1], upper[0]); scene.AddTriangle(upper[0], upper[3], upper[2]); // Side faces for (int i = 0; i < upper.Count; i++) { int j = i < (upper.Count - 1) ? i + 1 : 0; scene.AddTriangle(upper[i], upper[j], lower[i]); scene.AddTriangle(lower[i], upper[j], lower[j]); } // !!!}} }
/// <summary> /// Reads one 3D scene from a given stream (containing text variant of Wavefront OBJ format). /// </summary> /// <param name="reader">Already open text reader</param> /// <param name="scene">Scene to be modified</param> /// <param name="scene">Matrix for instancing</param> /// <returns>Number of faces read</returns> public int ReadBrep( StreamReader reader, SceneBrep scene, Matrix4 m ) { if ( reader == null ) return SceneBrep.NULL; Debug.Assert( scene != null ); int v0 = scene.Vertices; int faces = 0; List<Vector3> normals = new List<Vector3>( 256 ); int[] f = new int[ 3 ]; do { string line = reader.ReadLine(); if ( line == null ) break; int commentPos = line.IndexOf( COMMENT ); if ( commentPos >= 0 ) line = line.Substring( 0, commentPos ); string[] tokens = line.Split( ' ' ); switch ( tokens[ 0 ] ) { case VERTEX: if ( tokens.Length < 4 ) continue; Vector3 coord; if ( !float.TryParse( tokens[ 1 ], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.X ) || !float.TryParse( tokens[ 2 ], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.Y ) || !float.TryParse( tokens[ 3 ], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.Z ) ) continue; if ( MirrorConversion ) coord.Z = -coord.Z; scene.AddVertex( Vector3.Transform( coord, m ) ); break; case VERTEX_NORMAL: if ( tokens.Length < 4 ) continue; Vector3 norm; if ( !float.TryParse( tokens[ 1 ], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.X ) || !float.TryParse( tokens[ 2 ], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.Y ) || !float.TryParse( tokens[ 3 ], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.Z ) ) continue; if ( MirrorConversion ) norm.Z = -norm.Z; normals.Add( Vector3.TransformNormal( norm, m ) ); break; case FACE: if ( tokens.Length < 4 ) continue; int i; for ( i = 0; i < 3; i++ ) { string[] vt = tokens[ i + 1 ].Split( '/' ); int ti, ni; ti = ni = SceneBrep.NULL; // 0 .. vertex coord index if ( !int.TryParse( vt[ 0 ], out f[ i ] ) ) break; f[ i ] = v0 + f[ i ] - 1; if ( vt.Length >= 2 ) { // 1 .. texture coord index (not yet) int.TryParse( vt[ 1 ], out ti ); ti--; if ( vt.Length >= 3 ) { // 2 .. normal vector index int.TryParse( vt[ 2 ], out ni ); ni--; } } if ( ni >= 0 && ni < normals.Count ) scene.SetNormal( f[ i ], normals[ ni ] ); } if ( i >= 3 ) { scene.AddTriangle( f[ 0 ], f[ 1 ], f[ 2 ] ); faces++; } break; } } while ( !reader.EndOfStream ); return faces; }
private int createBentPipe(SceneBrep scene, Matrix4 m, Vector3 v1, Vector3 v2, Vector3 v3) { Vector3[] centers = new Vector3[bdetail]; Vector3 oned = (v1 - v2) * size; Vector3 twod = (v3 - v2) * size; Vector3 rtwod = (v3 - v2) * (1 - size); Vector3 rot_point = v2 + oned + twod; Vector3 test_point = oned + twod; test_point.X = Math.Abs(test_point.X); test_point.Y = Math.Abs(test_point.Y); test_point.Z = Math.Abs(test_point.Z); double angle = -(Math.PI / 2) / (bdetail - 1); char axis; if (test_point.Y < test_point.X) { axis = (test_point.Z < test_point.Y) ? 'z' : 'y'; } else { axis = (test_point.Z < test_point.X) ? 'z' : 'x'; } MyMatrix4 mat = MyMatrix4.getSingleRotationMatrix(angle, axis); float l = longestSide(last_circle[0] - v1); Vector3 sp = rotateAroundPoint(last_circle[0], rot_point, mat); float l2 = longestSide(sp - v1); if (l2 < l) { mat = MyMatrix4.getSingleRotationMatrix(-angle, axis); } Vector3[] field = new Vector3[bdetail * cdetail]; Array.Copy(last_circle, field, cdetail); centers[0] = getCenter(last_circle); Vector3[] new_circle = new Vector3[cdetail]; for (int i = 1; i < bdetail; i++) { Array.ConstrainedCopy(field, (i - 1) * cdetail, new_circle, 0, cdetail); new_circle = rotateAroundPoint(new_circle, rot_point, mat); Array.ConstrainedCopy(new_circle, 0, field, i * cdetail, cdetail); centers[i] = getCenter(new_circle); } Array.ConstrainedCopy(field, (bdetail - 1) * cdetail, last_circle, 0, cdetail); for (int i = 0; i < cdetail; i++) { last_circle[i] += rtwod - twod; } int[] v = new int[field.Length]; for (int i = 0; i < field.Length; i++) { v[i] = scene.AddVertex(Vector3.TransformPosition(field[i], m)); scene.SetNormal(v[i], Vector3.TransformVector(field[i] - centers[i / cdetail], m).Normalized()); float r = (field[i].X + 1.1f) / 2.5f; float g = (field[i].Y + 1.1f) / 2.5f; float b = (field[i].Z + 1.1f) / 2.5f; scene.SetColor(v[i], new Vector3(r, g, b)); } for (int i = 0; i < cdetail - 1; i++) { scene.AddTriangle(connect_indices[i], v[i], connect_indices[i + 1]); scene.AddTriangle(connect_indices[i + 1], v[i], v[i + 1]); } scene.AddTriangle(connect_indices[cdetail - 1], v[cdetail - 1], connect_indices[0]); scene.AddTriangle(connect_indices[0], v[cdetail - 1], v[0]); for (int i = 0; i < (bdetail - 1); i++) { for (int j = 0; j < cdetail - 1; j++) { int a = i * cdetail + j; scene.AddTriangle(v[a], v[a + cdetail], v[a + 1]); scene.AddTriangle(v[a + 1], v[a + cdetail], v[a + cdetail + 1]); } int b = i * cdetail + cdetail - 1; scene.AddTriangle(v[b], v[b + cdetail], v[b - cdetail + 1]); scene.AddTriangle(v[b - cdetail + 1], v[b + cdetail], v[b + 1]); } Array.ConstrainedCopy(v, (bdetail - 1) * cdetail, connect_indices, 0, cdetail); return(bdetail * cdetail * 2 + cdetail * 2); }
public int ReadBrep(string fileName, SceneBrep scene) { Debug.Assert(scene != null); this.scene = scene; scene.Reset(); if (fileName == null || fileName.Length == 0) { throw new IOException("Invalid file name"); } if (fileName.EndsWith(".gz")) { headerReader = new StreamReader(new GZipStream(new FileStream(fileName, FileMode.Open), CompressionMode.Decompress)); } else { var fs = new FileStream(fileName, FileMode.Open); headerReader = new StreamReader(fs); } // prepare buffers for data filling if (!ParseHeader()) { return(-1); } // read vertices var vertexReader = GetReader("vertex"); var element = vertexReader.ReadElement(); List <Vector2> txtCoords = new List <Vector2>(256); int[] f = new int[3]; int v0 = scene.Vertices; int lastVertex = v0 - 1; while (element != null) { lastVertex = scene.AddVertex(Vector3.TransformPosition(element.GetVertex(), matrix)); if (DoNormals) { Vector3.TransformNormal(element.GetNormal(), matrix); scene.SetNormal(lastVertex, element.GetNormal()); } if (DoTxtCoords) { scene.SetTxtCoord(lastVertex, element.GetTextureCoordinate()); } if (DoColors) { scene.SetColor(lastVertex, element.GetVertexColor()); } element = vertexReader.ReadElement(); } // read triangles var faceReader = GetReader("face"); element = faceReader.ReadElement(); while (element != null) { int A, B, C; element.GetTriangleVertices(out A, out B, out C); scene.AddTriangle(A, B, C); element = faceReader.ReadElement(); } headerReader.Close(); vertexReader.Close(); faceReader.Close(); return(scene.Triangles); }
/// <summary> /// Reads one 3D scene from a given stream (containing text variant of Wavefront OBJ format). /// </summary> /// <param name="reader">Already open text reader</param> /// <param name="scene">Scene to be modified</param> /// <param name="scene">Matrix for instancing</param> /// <returns>Number of faces read</returns> public int ReadBrep(StreamReader reader, SceneBrep scene, Matrix4 m) { if (reader == null) { return(SceneBrep.NULL); } Debug.Assert(scene != null); int v0 = scene.Vertices; int lastVertex = v0 - 1; int faces = 0; List <Vector2> txtCoords = new List <Vector2>(256); List <Vector3> normals = new List <Vector3>(256); int lastTxtCoord = -1; int lastNormal = -1; int[] f = new int[3]; do { string line = reader.ReadLine(); if (line == null) { break; } int commentPos = line.IndexOf(COMMENT); if (commentPos >= 0) { line = line.Substring(0, commentPos); } string[] tokens = line.Split(DELIMITERS, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length < 1) { continue; } switch (tokens[0]) { case VERTEX: if (tokens.Length < 4) { continue; } Vector3 coord; if (!float.TryParse(tokens[1], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.X) || !float.TryParse(tokens[2], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.Y) || !float.TryParse(tokens[3], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.Z)) { continue; } if (MirrorConversion) { coord.Z = -coord.Z; } lastVertex = scene.AddVertex(Vector3.TransformPosition(coord, m)); break; case VERTEX_TEXTURE: if (tokens.Length < 3) { continue; } Vector2 txtCoord; if (!float.TryParse(tokens[1], NumberStyles.Float, CultureInfo.InvariantCulture, out txtCoord.X) || !float.TryParse(tokens[2], NumberStyles.Float, CultureInfo.InvariantCulture, out txtCoord.Y)) { continue; } if (TextureUpsideDown) { txtCoord.Y = 1.0f - txtCoord.Y; } txtCoords.Add(txtCoord); lastTxtCoord++; break; case VERTEX_NORMAL: if (tokens.Length < 4) { continue; } Vector3 norm; if (!float.TryParse(tokens[1], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.X) || !float.TryParse(tokens[2], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.Y) || !float.TryParse(tokens[3], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.Z)) { continue; } if (MirrorConversion) { norm.Z = -norm.Z; } normals.Add(Vector3.TransformNormal(norm, m)); lastNormal++; break; case FACE: if (tokens.Length < 4) { continue; } int N = tokens.Length - 1; if (f.Length < N) { f = new int[N]; } int i; for (i = 0; i < N; i++) // read indices for one vertex { string[] vt = tokens[i + 1].Split('/'); int ti, ni; ti = ni = 0; // 0 => value not present // 0 .. vertex coord index if (!int.TryParse(vt[0], out f[i]) || f[i] == 0) { break; } if (f[i] > 0) { f[i] = v0 + f[i] - 1; } else { f[i] = lastVertex + 1 - f[i]; } if (vt.Length > 1) { // 1 .. texture coord index (not yet) if (!int.TryParse(vt[1], out ti)) { ti = 0; } if (vt.Length > 2) { // 2 .. normal vector index if (!int.TryParse(vt[2], out ni)) { ni = 0; } } } // there was a texture coord.. if (ti != 0) { if (ti > 0) { ti--; } else { ti = lastTxtCoord + 1 - ti; } if (ti >= 0 && ti < txtCoords.Count) { scene.SetTxtCoord(f[i], txtCoords[ti]); } } // there was a normal.. if (ni != 0) { if (ni > 0) { ni--; } else { ni = lastNormal + 1 - ni; } if (ni >= 0 && ni < normals.Count) { scene.SetNormal(f[i], normals[ni]); } } } N = i; for (i = 1; i < N - 1; i++) { scene.AddTriangle(f[0], f[i], f[i + 1]); faces++; } break; } } while (!reader.EndOfStream); return(faces); }
/// <summary> /// Reads one 3D scene from a given stream (containing text variant of Wavefront OBJ format). /// </summary> /// <param name="reader">Already open text reader</param> /// <param name="scene">Scene to be modified</param> /// <param name="scene">Matrix for instancing</param> /// <returns>Number of faces read</returns> public int ReadBrep( StreamReader reader, SceneBrep scene, Matrix4 m ) { if ( reader == null ) return SceneBrep.NULL; Debug.Assert( scene != null ); int v0 = scene.Vertices; int lastVertex = v0 - 1; int faces = 0; List<Vector3> normals = new List<Vector3>( 256 ); int lastNormal = -1; int[] f = new int[ 3 ]; do { string line = reader.ReadLine(); if ( line == null ) break; int commentPos = line.IndexOf( COMMENT ); if ( commentPos >= 0 ) line = line.Substring( 0, commentPos ); string[] tokens = line.Split( DELIMITERS , StringSplitOptions.RemoveEmptyEntries ); if ( tokens.Length < 1 ) continue; switch ( tokens[ 0 ] ) { case VERTEX: if ( tokens.Length < 4 ) continue; Vector3 coord; if ( !float.TryParse( tokens[ 1 ], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.X ) || !float.TryParse( tokens[ 2 ], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.Y ) || !float.TryParse( tokens[ 3 ], NumberStyles.Float, CultureInfo.InvariantCulture, out coord.Z ) ) continue; if ( MirrorConversion ) coord.Z = -coord.Z; lastVertex = scene.AddVertex( Vector3.Transform( coord, m ) ); break; case VERTEX_NORMAL: if ( tokens.Length < 4 ) continue; Vector3 norm; if ( !float.TryParse( tokens[ 1 ], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.X ) || !float.TryParse( tokens[ 2 ], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.Y ) || !float.TryParse( tokens[ 3 ], NumberStyles.Float, CultureInfo.InvariantCulture, out norm.Z ) ) continue; if ( MirrorConversion ) norm.Z = -norm.Z; normals.Add( Vector3.TransformNormal( norm, m ) ); lastNormal++; break; case FACE: if ( tokens.Length < 4 ) continue; int N = tokens.Length - 1; if ( f.Length < N ) f = new int[ N ]; int i; for ( i = 0; i < N; i++ ) // read indices for one vertex { string[] vt = tokens[ i + 1 ].Split( '/' ); int ti, ni; ti = ni = 0; // 0 => value not present // 0 .. vertex coord index if ( !int.TryParse( vt[ 0 ], out f[ i ] ) || f[ i ] == 0 ) break; if ( f[ i ] > 0 ) f[ i ] = v0 + f[ i ] - 1; else f[ i ] = lastVertex + 1 - f[ i ]; if ( vt.Length > 1 ) { // 1 .. texture coord index (not yet) if ( !int.TryParse( vt[ 1 ], out ti ) ) ti = 0; if ( vt.Length > 2 ) { // 2 .. normal vector index if ( !int.TryParse( vt[ 2 ], out ni ) ) ni = 0; } } // there was a normal.. if ( ni != 0 ) { if ( ni > 0 ) ni--; else ni = lastNormal + 1 - ni; if ( ni >= 0 && ni < normals.Count ) scene.SetNormal( f[ i ], normals[ ni ] ); } } N = i; for ( i = 1; i < N - 1; i++ ) { scene.AddTriangle( f[ 0 ], f[ i ], f[ i + 1 ] ); faces++; } break; } } while ( !reader.EndOfStream ); return faces; }