Free as in Freedom: Codeberg.org. Create your repos!
Browse Source

Compute vertex tangents and create triangle mesh from subdivision mesh.

tags/v0.4.4
Jan Walter 5 months ago
parent
commit
2ab342b08e
4 changed files with 121 additions and 82 deletions
  1. BIN
      assets/scenes/killeroos.tar.gz
  2. 14
    3
      src/core/api.rs
  3. 11
    0
      src/core/geometry.rs
  4. 96
    79
      src/shapes/loopsubdiv.rs

BIN
assets/scenes/killeroos.tar.gz View File


+ 14
- 3
src/core/api.rs View File

@@ -1242,7 +1242,6 @@ fn get_shapes_and_materials(
1242 1242
         println!("TODO: CreateHeightfield");
1243 1243
     } else if api_state.param_set.name == String::from("loopsubdiv") {
1244 1244
         // CreateLoopSubdiv
1245
-        println!("WORK: CreateLoopSubdiv");
1246 1245
         let n_levels: i32 = api_state.param_set.find_one_int(
1247 1246
             String::from("levels"),
1248 1247
             api_state.param_set.find_one_int(String::from("nlevels"), 3),
@@ -1257,10 +1256,10 @@ fn get_shapes_and_materials(
1257 1256
             panic!("Vertex positions \"P\" not provided for LoopSubdiv shape.");
1258 1257
         }
1259 1258
         // don't actually use this for now...
1260
-        let scheme: String = api_state
1259
+        let _scheme: String = api_state
1261 1260
             .param_set
1262 1261
             .find_one_string(String::from("scheme"), String::from("loop"));
1263
-        loop_subdivide(
1262
+        let mesh = loop_subdivide(
1264 1263
             &obj_to_world,
1265 1264
             &world_to_obj,
1266 1265
             api_state.graphics_state.reverse_orientation,
@@ -1268,6 +1267,18 @@ fn get_shapes_and_materials(
1268 1267
             &vertex_indices,
1269 1268
             &p,
1270 1269
         );
1270
+        let mtl: Option<Arc<Material + Send + Sync>> = create_material(&api_state, bsdf_state);
1271
+        for id in 0..mesh.n_triangles {
1272
+            let triangle = Arc::new(Triangle::new(
1273
+                mesh.object_to_world,
1274
+                mesh.world_to_object,
1275
+                mesh.reverse_orientation,
1276
+                mesh.clone(),
1277
+                id,
1278
+            ));
1279
+            shapes.push(triangle.clone());
1280
+            materials.push(mtl.clone());
1281
+        }
1271 1282
     } else if api_state.param_set.name == String::from("nurbs") {
1272 1283
         // CreateNURBS
1273 1284
         let nu: i32 = api_state.param_set.find_one_int(String::from("nu"), -1);

+ 11
- 0
src/core/geometry.rs View File

@@ -298,6 +298,17 @@ impl<T> Vector3<T> {
298 298
     }
299 299
 }
300 300
 
301
+impl<T> AddAssign<Vector3<T>> for Vector3<T>
302
+where
303
+    T: AddAssign,
304
+{
305
+    fn add_assign(&mut self, rhs: Vector3<T>) {
306
+        self.x += rhs.x;
307
+        self.y += rhs.y;
308
+        self.z += rhs.z;
309
+    }
310
+}
311
+
301 312
 impl<T> Add for Vector3<T>
302 313
 where
303 314
     T: Copy + Add<T, Output = T>,

+ 96
- 79
src/shapes/loopsubdiv.rs View File

@@ -1,22 +1,15 @@
1 1
 // std
2 2
 use std;
3 3
 use std::collections::{HashMap, HashSet};
4
+use std::f32::consts::PI;
4 5
 use std::hash::{Hash, Hasher};
5 6
 use std::sync::Arc;
6 7
 // pbrt
7
-use core::geometry::{
8
-    bnd3_expand, bnd3_union_bnd3, nrm_abs_dot_vec3, nrm_cross_vec3, nrm_dot_nrm, nrm_normalize,
9
-    pnt3_distance, pnt3_distance_squared, pnt3_lerp, vec2_dot, vec3_coordinate_system,
10
-    vec3_cross_vec3, vec3_normalize,
11
-};
12
-use core::geometry::{Bounds3f, Normal3f, Point2f, Point3f, Ray, Vector2f, Vector3f};
13
-use core::interaction::{Interaction, InteractionCommon, SurfaceInteraction};
14
-use core::material::Material;
15
-use core::paramset::ParamSet;
8
+use core::geometry::vec3_cross_vec3;
9
+use core::geometry::{Normal3f, Point3f, Vector3f};
16 10
 use core::pbrt::Float;
17
-use core::pbrt::{clamp_t, float_to_bits, lerp};
18
-use core::shape::Shape;
19 11
 use core::transform::Transform;
12
+use shapes::triangle::TriangleMesh;
20 13
 
21 14
 // see loopsubdiv.cpp
22 15
 
@@ -70,7 +63,7 @@ impl SDVertex {
70 63
         } else {
71 64
             // get one-ring vertices for boundary vertex
72 65
             let mut fi: i32 = self.start_face;
73
-            let mut fi2: i32 = -1_i32;
66
+            let mut fi2: i32;
74 67
             let mut pi = 0_usize;
75 68
             loop {
76 69
                 fi2 = faces[fi as usize].next_face(vi);
@@ -201,7 +194,7 @@ impl SDFace {
201 194
         self.v[prev(fi) as usize]
202 195
     }
203 196
     pub fn other_vert(&self, vi0: i32, vi1: i32) -> i32 {
204
-        let mut fi: i32 = -1;
197
+        let fi: i32 = -1;
205 198
         for i in 0..3_usize {
206 199
             if self.v[i] != vi0 && self.v[i] != vi1 {
207 200
                 return self.v[i];
@@ -279,7 +272,7 @@ pub fn loop_subdivide(
279 272
     n_levels: i32,
280 273
     vertex_indices: &Vec<i32>,
281 274
     p: &Vec<Point3f>,
282
-) -> Vec<Arc<Shape + Send + Sync>> {
275
+) -> Arc<TriangleMesh> {
283 276
     // allocate _LoopSubdiv_ vertices and faces
284 277
     let mut verts: Vec<Arc<SDVertex>> = Vec::with_capacity(p.len());
285 278
     for i in 0..p.len() {
@@ -287,7 +280,7 @@ pub fn loop_subdivide(
287 280
     }
288 281
     let n_faces: usize = vertex_indices.len() / 3;
289 282
     let mut faces: Vec<Arc<SDFace>> = Vec::with_capacity(n_faces);
290
-    for i in 0..n_faces {
283
+    for _i in 0..n_faces {
291 284
         faces.push(Arc::new(SDFace::default()));
292 285
     }
293 286
     // set face to vertex pointers
@@ -351,7 +344,7 @@ pub fn loop_subdivide(
351 344
         }
352 345
         let valence = verts[vi].valence(vi as i32, &faces);
353 346
         if let Some(v) = Arc::get_mut(&mut verts[vi]) {
354
-            v.boundary = (fi == -1_i32);
347
+            v.boundary = fi == -1_i32;
355 348
             if !v.boundary && valence == 6 {
356 349
                 v.regular = true;
357 350
             } else if v.boundary && valence == 4 {
@@ -362,7 +355,7 @@ pub fn loop_subdivide(
362 355
         }
363 356
     }
364 357
     // refine _LoopSubdiv_ into triangles
365
-    for i in 0..n_levels {
358
+    for _i in 0..n_levels {
366 359
         // update _faces_ and _verts_ for next level of subdivision
367 360
         let mut new_faces: Vec<Arc<SDFace>> = Vec::new();
368 361
         let mut new_vertices: Vec<Arc<SDVertex>> = Vec::new();
@@ -393,7 +386,7 @@ pub fn loop_subdivide(
393 386
             if let Some(child) = Arc::get_mut(&mut new_vertices[ci]) {
394 387
                 if !verts[vi].boundary {
395 388
                     // apply one-ring rule for even vertex
396
-                    if (verts[vi].regular) {
389
+                    if verts[vi].regular {
397 390
                         child.p = weight_one_ring(
398 391
                             verts[vi].clone(),
399 392
                             1.0 as Float / 16.0 as Float,
@@ -436,7 +429,7 @@ pub fn loop_subdivide(
436 429
                     new_vertices.push(Arc::new(SDVertex::default()));
437 430
                     if let Some(vert) = Arc::get_mut(&mut new_vertices[nvi]) {
438 431
                         vert.regular = true;
439
-                        vert.boundary = (faces[fi].f[k as usize] == -1_i32);
432
+                        vert.boundary = faces[fi].f[k as usize] == -1_i32;
440 433
                         vert.start_face = faces[fi].children[3];
441 434
                         // apply edge rules to compute new vertex position
442 435
                         if vert.boundary {
@@ -578,66 +571,90 @@ pub fn loop_subdivide(
578 571
             v.p = p_limit[i];
579 572
         }
580 573
     }
581
-
582
-    // // Compute vertex tangents on limit surface
583
-    // std::vector<Normal3f> Ns;
584
-    // Ns.reserve(v.size());
585
-    // std::vector<Point3f> pRing(16, Point3f());
586
-    // for (SDVertex *vertex : v) {
587
-    //     Vector3f S(0, 0, 0), T(0, 0, 0);
588
-    //     int valence = vertex.valence();
589
-    //     if (valence > (int)pRing.size()) pRing.resize(valence);
590
-    //     vertex.oneRing(&pRing[0]);
591
-    //     if (!vertex.boundary) {
592
-    //         // Compute tangents of interior face
593
-    //         for (int j = 0; j < valence; ++j) {
594
-    //             S += std::cos(2 * Pi * j / valence) * Vector3f(pRing[j]);
595
-    //             T += std::sin(2 * Pi * j / valence) * Vector3f(pRing[j]);
596
-    //         }
597
-    //     } else {
598
-    //         // Compute tangents of boundary face
599
-    //         S = pRing[valence - 1] - pRing[0];
600
-    //         if (valence == 2)
601
-    //             T = Vector3f(pRing[0] + pRing[1] - 2 * vertex.p);
602
-    //         else if (valence == 3)
603
-    //             T = pRing[1] - vertex.p;
604
-    //         else if (valence == 4)  // regular
605
-    //             T = Vector3f(-1 * pRing[0] + 2 * pRing[1] + 2 * pRing[2] +
606
-    //                          -1 * pRing[3] + -2 * vertex.p);
607
-    //         else {
608
-    //             Float theta = Pi / float(valence - 1);
609
-    //             T = Vector3f(std::sin(theta) * (pRing[0] + pRing[valence - 1]));
610
-    //             for (int k = 1; k < valence - 1; ++k) {
611
-    //                 Float wt = (2 * std::cos(theta) - 2) * std::sin((k)*theta);
612
-    //                 T += Vector3f(wt * pRing[k]);
613
-    //             }
614
-    //             T = -T;
615
-    //         }
616
-    //     }
617
-    //     Ns.push_back(Normal3f(Cross(S, T)));
618
-    // }
619
-
620
-    // // Create triangle mesh from subdivision mesh
621
-    // {
622
-    //     size_t ntris = f.size();
623
-    //     std::unique_ptr<int[]> verts(new int[3 * ntris]);
624
-    //     int *vp = verts.get();
625
-    //     size_t totVerts = v.size();
626
-    //     std::map<SDVertex *, int> usedVerts;
627
-    //     for (size_t i = 0; i < totVerts; ++i) usedVerts[v[i]] = i;
628
-    //     for (size_t i = 0; i < ntris; ++i) {
629
-    //         for (int j = 0; j < 3; ++j) {
630
-    //             *vp = usedVerts[f[i]->v[j]];
631
-    //             ++vp;
632
-    //         }
633
-    //     }
634
-    //     return CreateTriangleMesh(ObjectToWorld, WorldToObject,
635
-    //                               reverseOrientation, ntris, verts.get(),
636
-    //                               totVerts, pLimit.get(), nullptr, &Ns[0],
637
-    //                               nullptr, nullptr, nullptr);
638
-    // }
639
-    // WORK
640
-    Vec::new()
574
+    // compute vertex tangents on limit surface
575
+    let mut ns: Vec<Normal3f> = Vec::with_capacity(verts.len());
576
+    let mut p_ring: Vec<Point3f> = Vec::new();
577
+    p_ring.resize(16_usize, Point3f::default());
578
+    for vi in 0..verts.len() {
579
+        let vertex = verts[vi].clone();
580
+        let mut s: Vector3f = Vector3f::default();
581
+        let mut t: Vector3f = Vector3f::default();
582
+        let valence: i32 = vertex.valence(vi as i32, &faces);
583
+        if valence as usize > p_ring.len() {
584
+            p_ring.resize(valence as usize, Point3f::default());
585
+        }
586
+        vertex.one_ring(&mut p_ring, vi as i32, &faces, &verts);
587
+        if !vertex.boundary {
588
+            // compute tangents of interior face
589
+            for j in 0..valence as usize {
590
+                s += Vector3f::from(p_ring[j])
591
+                    * (2.0 as Float * PI * j as Float / valence as Float).cos();
592
+                t += Vector3f::from(p_ring[j])
593
+                    * (2.0 as Float * PI * j as Float / valence as Float).sin();
594
+            }
595
+        } else {
596
+            // compute tangents of boundary face
597
+            s = p_ring[(valence - 1) as usize] - p_ring[0_usize];
598
+            if valence == 2_i32 {
599
+                t = Vector3f::from(p_ring[0] + p_ring[1] - vertex.p * 2.0 as Float);
600
+            } else if valence == 3_i32 {
601
+                t = p_ring[1] - vertex.p;
602
+            } else if valence == 4_i32 {
603
+                // regular
604
+                t = Vector3f::from(
605
+                    p_ring[0] * -1.0 as Float
606
+                        + p_ring[1] * 2.0 as Float
607
+                        + p_ring[2] * 2.0 as Float
608
+                        + p_ring[3] * -1. * 2.0 as Float
609
+                        + vertex.p * -2.0 as Float,
610
+                );
611
+            } else {
612
+                let theta: Float = PI / (valence - 1) as Float;
613
+                t = Vector3f::from((p_ring[0] + p_ring[(valence - 1) as usize]) * theta.sin());
614
+                for k in 1..(valence - 1) as usize {
615
+                    let wt: Float =
616
+                        (2.0 as Float * theta.cos() - 2.0 as Float) * (k as Float * theta).sin();
617
+                    t += Vector3f::from(p_ring[k] * wt);
618
+                }
619
+                t = -t;
620
+            }
621
+        }
622
+        ns.push(Normal3f::from(vec3_cross_vec3(&s, &t)));
623
+    }
624
+    // create triangle mesh from subdivision mesh
625
+    let ntris: usize = faces.len();
626
+    let mut vertex_indices: Vec<usize> = Vec::with_capacity(3 * ntris);
627
+    let tot_verts: usize = verts.len();
628
+    for i in 0..ntris {
629
+        for j in 0..3_usize {
630
+            vertex_indices.push(faces[i].v[j] as usize);
631
+        }
632
+    }
633
+    // transform mesh vertices to world space
634
+    let mut p_ws: Vec<Point3f> = Vec::new();
635
+    let n_vertices: usize = p_limit.len();
636
+    for i in 0..n_vertices {
637
+        p_ws.push(object_to_world.transform_point(&p_limit[i]));
638
+    }
639
+    // transform normals to world space
640
+    let mut n_ws: Vec<Normal3f> = Vec::new();
641
+    let n_normals: usize = ns.len();
642
+    for i in 0..n_normals {
643
+        n_ws.push(object_to_world.transform_normal(&ns[i]));
644
+    }
645
+    Arc::new(TriangleMesh::new(
646
+        *object_to_world,
647
+        *world_to_object,
648
+        reverse_orientation,
649
+        false, // transform_swaps_handedness
650
+        ntris,
651
+        vertex_indices,
652
+        tot_verts,
653
+        p_ws, // in world space
654
+        Vec::new(),
655
+        n_ws, // in world space
656
+        Vec::new(),
657
+    ))
641 658
 }
642 659
 
643 660
 fn weight_one_ring(

Loading…
Cancel
Save