mirror planes detection needs work
[laserbrain_demo] / src / metascene.cc
index c467420..6805fae 100644 (file)
@@ -37,6 +37,7 @@ struct MaterialEditTexture {
 
 struct MaterialEditMirror {
        float reflectivity;
+       int plane;
 };
 
 struct MaterialEdit {
@@ -202,6 +203,8 @@ Scene *MetaScene::extract_nodes(const char *qstr)
 
 int MetaScene::calc_mirror_planes()
 {
+       std::vector<Vec4> world_planes;
+
        int num_mirrors = 0;
        while(mirrors) {
                FlatMirror *m = mirrors;
@@ -223,22 +226,38 @@ int MetaScene::calc_mirror_planes()
                                const Mesh *mesh = ((ObjMesh*)obj)->mesh;
                                if(!mesh) continue;
 
-                               // assume the object is actually flat, so grab the first triangle and make a plane
-                               Triangle face = Triangle(0, (const Vec3*)mesh->get_attrib_data(MESH_ATTR_VERTEX),
-                                               mesh->get_index_data());
-                               face.calc_normal();
-
                                FlatMirror *mir = new FlatMirror;
-                               mir->plane.pt = face.v[0];
-                               mir->plane.normal = face.normal;
                                mir->reflect = obj->mtl.reflect;
+                               mir->node = obj->node;
+
+                               if(obj->mtl.flat_mirror == MTL_MIRROR_AUTO) {
+                                       // grab the first triangle and make a plane
+                                       Triangle face = Triangle(0, (const Vec3*)mesh->get_attrib_data(MESH_ATTR_VERTEX),
+                                                       mesh->get_index_data());
+                                       face.calc_normal();
+
+                                       mir->plane.pt = face.v[0];
+                                       mir->plane.normal = face.normal;
+                               } else {
+                                       int plane_idx = obj->mtl.flat_mirror - MTL_MIRROR_AABB_PX;
+                                       mir->plane = obj->get_aabox().get_plane(plane_idx);
+                                       debug_log("mirror plane: p(%f %f %f) n(%f %f %f)\n", mir->plane.pt.x, mir->plane.pt.y,
+                                                       mir->plane.pt.z, mir->plane.normal.x, mir->plane.normal.y, mir->plane.normal.z);
+                               }
+
+                               float pdist = dot(mir->plane.normal, mir->plane.pt);
+                               Vec4 plane_eq = Vec4(mir->plane.normal.x, mir->plane.normal.y, mir->plane.normal.z, pdist);
+
+                               if(obj->node) {
+                                       plane_eq = obj->node->get_matrix() * plane_eq;
+                               }
 
                                // check to see if we have found this mirror plane already
                                bool found = false;
-                               FlatMirror *node = mirrors;
-                               while(node) {
-                                       if(fabs(dot(mir->plane.normal, node->plane.normal)) < 1e-4 &&
-                                                       fabs(dot(mir->plane.normal, normalize(mir->plane.pt - node->plane.pt))) < 1e-4) {
+                               int nplanes = world_planes.size();
+                               for(int k=0; k<nplanes; k++) {
+                                       if(1.0f - dot(plane_eq.xyz(), world_planes[k].xyz()) < 1e-4f &&
+                                                       fabs(plane_eq.w - world_planes[k].w) < 1e-4) {
                                                found = true;
                                                break;
                                        }
@@ -248,6 +267,9 @@ int MetaScene::calc_mirror_planes()
                                        mir->next = mirrors;
                                        mirrors = mir;
 
+                                       world_planes.push_back(plane_eq);
+
+                                       mir->objects.push_back(obj);
                                        objmirror[obj] = mir;   // associate with object
                                        ++num_mirrors;
                                } else {
@@ -494,6 +516,35 @@ static bool proc_mtledit(MetaScene *mscn, MaterialEdit *med, struct ts_node *nod
                if(strcmp(cn->name, "mirror") == 0) {
                        // make this object a flat mirror (hopefully the object is flat otherwise this won't work)
                        float refl = 1.0f;
+                       int plane = MTL_MIRROR_AUTO;
+
+                       struct ts_attr *aplane = ts_get_attr(cn, "plane");
+                       if(aplane) {
+                               if(aplane->val.type == TS_NUMBER) {
+                                       plane = MTL_MIRROR_AABB_PX + aplane->val.inum;
+                               } else {
+                                       char csign, caxis;
+                                       if(sscanf(aplane->val.str, "aabb%c%c", &csign, &caxis) != 2 || (csign != '+' && csign != '-')) {
+                                               error_log("invalid reflect plane specifier: %s\n", aplane->val.str);
+                                               continue;
+                                       }
+
+                                       switch(tolower(caxis)) {
+                                       case 'x':
+                                               plane = csign == '+' ? MTL_MIRROR_AABB_PX : MTL_MIRROR_AABB_NX;
+                                               break;
+                                       case 'y':
+                                               plane = csign == '+' ? MTL_MIRROR_AABB_PY : MTL_MIRROR_AABB_NY;
+                                               break;
+                                       case 'z':
+                                               plane = csign == '+' ? MTL_MIRROR_AABB_PZ : MTL_MIRROR_AABB_NZ;
+                                               break;
+                                       default:
+                                               error_log("invalid reflect plane specifier: %s\n", aplane->val.str);
+                                               continue;
+                                       }
+                               }
+                       }
 
                        struct ts_attr *arefl = ts_get_attr(cn, "reflect");
                        if(arefl) {
@@ -507,6 +558,7 @@ static bool proc_mtledit(MetaScene *mscn, MaterialEdit *med, struct ts_node *nod
 
                        med->type = MTL_EDIT_MIRROR;
                        med->mirror.reflectivity = refl;
+                       med->mirror.plane = plane;
                        break;
                }
        }
@@ -573,7 +625,7 @@ static void apply_mtledit(Material *mtl, const MaterialEdit &med)
                break;
 
        case MTL_EDIT_MIRROR:
-               mtl->flat_mirror = med.mirror.reflectivity > 1e-6;
+               mtl->flat_mirror = med.mirror.plane;
                mtl->reflect = med.mirror.reflectivity;
                break;
        }