Browse Source

Add locking mechanism to prevent updating transform/parent

Godzil 4 years ago
parent
commit
441d758845

+ 2 - 0
source/include/csg.h

@@ -48,6 +48,8 @@ public:
 
     void updateTransform();
 
+    void lock();
+
     void dumpMe(FILE *fp);
 };
 

+ 2 - 0
source/include/group.h

@@ -56,6 +56,8 @@ public:
 
     Group(const char *name = nullptr);
 
+    void lock();
+
     const char *getName() { return this->name; };
 
     void dumpMe(FILE * fp);

+ 2 - 0
source/include/objfile.h

@@ -70,6 +70,8 @@ public:
     void updateBoundingBox();
     void updateTransform();
 
+    void lock();
+
     void dumpMe(FILE * fp);
 };
 

+ 11 - 0
source/include/shape.h

@@ -41,6 +41,7 @@ public:
 protected:
     ShapeType type;
     Matrix localTransformMatrix;
+    bool locked;
 
 protected:
     virtual Intersect localIntersect(Ray r) = 0;
@@ -75,10 +76,20 @@ public:
 
     virtual void dumpMe(FILE *fp);
 
+    /* When an object is locked, the matrix transformation and bounding box can't be updated. This is
+     * usefull to move object between group without changing the real hierarchy between them.
+     * It will also not change the parent member.
+     * This is supposed to be used only before a render is going to start so we can optimise the
+     * way the object are stored to prefer lots of un-needed intersections.
+     */
+    virtual void lock() { this->locked = true; };
+
     Tuple worldToObject(Tuple point) { return this->inverseTransform * point; };
     Tuple objectToWorld(Tuple point) { return this->transformMatrix * point; };
     Tuple normalToWorld(Tuple normalVector);
 
+    void setParent(Shape *parent) { if (!this->locked) { this->parent = parent; };};
+
     void setTransform(Matrix transform);
     void setMaterial(Material material) { this->material = material; this->materialSet = true; };
     Ray transform(Ray r) { return Ray(this->transformMatrix * r.origin, this->transformMatrix * r.direction); };

+ 15 - 2
source/shapes/csg.cpp

@@ -17,8 +17,8 @@ CSG::CSG(OperationType operation, Shape *left, Shape *right) : Shape(Shape::CSG)
 {
     stats.addCsg();
 
-    this->left->parent = this;
-    this->right->parent = this;
+    this->left->setParent(this);
+    this->right->setParent(this);
 
     this->bounds | this->left->getBounds();
     this->bounds | this->right->getBounds();
@@ -134,6 +134,19 @@ void CSG::filterIntersections(Intersect &xs, Intersect &ret)
     }
 }
 
+void CSG::lock()
+{
+    Shape::lock();
+    if(this->left)
+    {
+        this->left->lock();
+    }
+    if(this->right)
+    {
+        this->right->lock();
+    }
+}
+
 void CSG::dumpMe(FILE *fp)
 {
 

+ 26 - 3
source/shapes/group.cpp

@@ -90,7 +90,6 @@ bool Group::includes(Shape *b)
         }
     }
 
-    /* We are force to do them all the time */
     if (this->unboxableObjectCount > 0)
     {
         int i;
@@ -126,7 +125,7 @@ void Group::addObject(Shape *s)
             this->objectList = (Shape **)realloc(this->objectList, sizeof(Shape **) * this->allocatedObjectCount);
         }
 
-        s->parent = this;
+        s->setParent(this);
         s->updateTransform();
 
         this->objectList[this->objectCount++] = s;
@@ -142,7 +141,7 @@ void Group::addObject(Shape *s)
             this->unboxableObjectList = (Shape **)realloc(this->unboxableObjectList, sizeof(Shape **) * this->allocatedUnboxableObjectCount);
         }
 
-        s->parent = this;
+        s->setParent(this);
         s->updateTransform();
 
         this->unboxableObjectList[this->unboxableObjectCount++] = s;
@@ -269,4 +268,28 @@ void Group::dumpMe(FILE *fp)
         fprintf(fp, "},\n");
     }
     Shape::dumpMe(fp);
+}
+
+void Group::lock()
+{
+    Shape::lock();
+
+    /* Now notify included object they have to lock */
+    int i;
+    if (this->objectCount > 0)
+    {
+        for (i = 0 ; i < this->objectCount ; i++)
+        {
+            this->objectList[i]->lock();
+        }
+    }
+
+    if (this->unboxableObjectCount > 0)
+    {
+        for(i = 0; i < this->unboxableObjectCount; i++)
+        {
+            this->unboxableObjectList[i]->lock();
+        }
+    }
+
 }

+ 8 - 1
source/shapes/objfile.cpp

@@ -99,7 +99,7 @@ void OBJFile::addGroup(Group *group)
 {
     this->baseGroup->addObject(group);
 
-    group->parent = this;
+    group->setParent(this);
     group->updateTransform();
     this->bounds | group->getBounds();
 
@@ -461,3 +461,10 @@ int OBJFile::execLine(int argc, char *argv[], uint32_t currentLine)
     }
     return ret;
 }
+
+void OBJFile::lock()
+{
+    Shape::lock();
+
+    this->baseGroup->lock();
+}

+ 7 - 1
source/shapes/shape.cpp

@@ -15,12 +15,14 @@
 
 Shape::Shape(ShapeType type)
 {
+    this->locked = false;
     this->parent = nullptr;
     this->dropShadow = true;
     this->type = type;
     this->localTransformMatrix = Matrix4().identity();
-    this->updateTransform();
     this->materialSet = false;
+
+    this->updateTransform();
 }
 
 Intersect Shape::intersect(Ray r)
@@ -51,6 +53,8 @@ Tuple Shape::normalAt(Tuple point, Intersection *hit)
 
 void Shape::updateTransform()
 {
+    if (this->locked) return;
+
     this->transformMatrix = this->localTransformMatrix;
     if (this->parent != nullptr)
     {
@@ -63,6 +67,8 @@ void Shape::updateTransform()
 
 void Shape::setTransform(Matrix transform)
 {
+    if (this->locked) return;
+
     this->localTransformMatrix = transform;
     this->updateTransform();
 }

+ 22 - 0
tests/shape_test.cpp

@@ -198,6 +198,28 @@ TEST(ShapeTest, Test_the_bouding_box_of_the_translated_shape)
 
     BoundingBox res = t.getBounds();
 
+    ASSERT_EQ(res.min, b.min);
+    ASSERT_EQ(res.max, b.max);
+}
+
+TEST(ShapeTest, A_lock_shape_can_t_have_transformation_changed)
+{
+    TestShape t = TestShape();
+    t.setTransform(translation(10, 0, 0));
+
+    BoundingBox b = BoundingBox(Point(9, -1, -1), Point(11, 1, 1));
+
+    BoundingBox res = t.getBounds();
+
+    ASSERT_EQ(res.min, b.min);
+    ASSERT_EQ(res.max, b.max);
+
+    t.lock();
+
+    t.setTransform(translation(-10, -10,-10));
+
+    res = t.getBounds();
+
     ASSERT_EQ(res.min, b.min);
     ASSERT_EQ(res.max, b.max);
 }