From 441d758845239552e9ea4a1cc78618e821f1333b Mon Sep 17 00:00:00 2001 From: Godzil Date: Tue, 10 Mar 2020 13:55:27 +0000 Subject: [PATCH] Add locking mechanism to prevent updating transform/parent --- source/include/csg.h | 2 ++ source/include/group.h | 2 ++ source/include/objfile.h | 2 ++ source/include/shape.h | 11 +++++++++++ source/shapes/csg.cpp | 17 +++++++++++++++-- source/shapes/group.cpp | 29 ++++++++++++++++++++++++++--- source/shapes/objfile.cpp | 9 ++++++++- source/shapes/shape.cpp | 8 +++++++- tests/shape_test.cpp | 22 ++++++++++++++++++++++ 9 files changed, 95 insertions(+), 7 deletions(-) diff --git a/source/include/csg.h b/source/include/csg.h index 75b9a42..06c1396 100644 --- a/source/include/csg.h +++ b/source/include/csg.h @@ -48,6 +48,8 @@ public: void updateTransform(); + void lock(); + void dumpMe(FILE *fp); }; diff --git a/source/include/group.h b/source/include/group.h index 68ebc8c..09673fb 100644 --- a/source/include/group.h +++ b/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); diff --git a/source/include/objfile.h b/source/include/objfile.h index 6d92988..e280729 100644 --- a/source/include/objfile.h +++ b/source/include/objfile.h @@ -70,6 +70,8 @@ public: void updateBoundingBox(); void updateTransform(); + void lock(); + void dumpMe(FILE * fp); }; diff --git a/source/include/shape.h b/source/include/shape.h index 6c8f8c0..6c1206c 100644 --- a/source/include/shape.h +++ b/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); }; diff --git a/source/shapes/csg.cpp b/source/shapes/csg.cpp index 40d950d..2e5b3e8 100644 --- a/source/shapes/csg.cpp +++ b/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) { diff --git a/source/shapes/group.cpp b/source/shapes/group.cpp index 3da9e55..ce0e5a3 100644 --- a/source/shapes/group.cpp +++ b/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(); + } + } + } \ No newline at end of file diff --git a/source/shapes/objfile.cpp b/source/shapes/objfile.cpp index c443e59..01b0f1e 100644 --- a/source/shapes/objfile.cpp +++ b/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(); +} \ No newline at end of file diff --git a/source/shapes/shape.cpp b/source/shapes/shape.cpp index ffc41bc..142243f 100644 --- a/source/shapes/shape.cpp +++ b/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(); } diff --git a/tests/shape_test.cpp b/tests/shape_test.cpp index fd7ca6d..1f53bc1 100644 --- a/tests/shape_test.cpp +++ b/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); } \ No newline at end of file