shape.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * DoRayMe - a quick and dirty Raytracer
  3. * Object implementation
  4. *
  5. * Created by Manoël Trapier
  6. * Copyright (c) 2020 986-Studio.
  7. *
  8. */
  9. #include <ray.h>
  10. #include <shape.h>
  11. #include <matrix.h>
  12. #include <tuple.h>
  13. #include <intersect.h>
  14. Shape::Shape(ShapeType type)
  15. {
  16. this->locked = false;
  17. this->parent = nullptr;
  18. this->dropShadow = true;
  19. this->type = type;
  20. this->localTransformMatrix = Matrix4().identity();
  21. this->materialSet = false;
  22. this->updateTransform();
  23. }
  24. void Shape::intersect(Ray &r, Intersect &xs)
  25. {
  26. this->localIntersect(this->invTransform(r), xs);
  27. };
  28. Tuple Shape::normalToWorld(Tuple normalVector)
  29. {
  30. Tuple world_normal = this->transposedInverseTransform * normalVector;
  31. /* W may get wrong, so hack it. This is perfectly normal as we are using a 4x4 matrix instead of a 3x3 */
  32. world_normal.w = 0;
  33. return world_normal.normalise();
  34. };
  35. Tuple Shape::normalAt(Tuple point, Intersection *hit)
  36. {
  37. Tuple local_point = this->worldToObject(point);
  38. Tuple local_normal = this->localNormalAt(local_point, hit);
  39. Tuple world_normal = this->normalToWorld(local_normal);
  40. return world_normal;
  41. }
  42. void Shape::updateTransform()
  43. {
  44. if (this->locked) return;
  45. this->transformMatrix = this->localTransformMatrix;
  46. if (this->parent != nullptr)
  47. {
  48. this->transformMatrix = this->parent->transformMatrix * this->transformMatrix;
  49. }
  50. this->inverseTransform = this->transformMatrix.inverse();
  51. this->transposedInverseTransform = this->inverseTransform.transpose();
  52. }
  53. void Shape::setTransform(Matrix transform)
  54. {
  55. if (this->locked) return;
  56. this->localTransformMatrix = transform;
  57. this->updateTransform();
  58. }
  59. BoundingBox Shape::getLocalBounds()
  60. {
  61. return BoundingBox(Point(-1, -1, -1), Point(1,1,1));
  62. }
  63. BoundingBox Shape::getBounds()
  64. {
  65. BoundingBox ret;
  66. BoundingBox me = this->getLocalBounds();
  67. ret | this->objectToWorld(Point(me.min.x, me.min.y, me.min.z));
  68. ret | this->objectToWorld(Point(me.min.x, me.min.y, me.max.z));
  69. ret | this->objectToWorld(Point(me.min.x, me.max.y, me.min.z));
  70. ret | this->objectToWorld(Point(me.max.x, me.min.y, me.min.z));
  71. ret | this->objectToWorld(Point(me.max.x, me.max.y, me.min.z));
  72. ret | this->objectToWorld(Point(me.max.x, me.min.y, me.max.z));
  73. ret | this->objectToWorld(Point(me.min.x, me.max.y, me.max.z));
  74. ret | this->objectToWorld(Point(me.max.x, me.max.y, me.max.z));
  75. return ret;
  76. }
  77. void Shape::dumpMe(FILE *fp)
  78. {
  79. if (this->materialSet)
  80. {
  81. fprintf(fp, "\"Material\": {\n");
  82. this->material.dumpMe(fp);
  83. fprintf(fp, "},\n");
  84. }
  85. fprintf(fp, "\"DropShadow\": %d,\n", this->dropShadow);
  86. fprintf(fp, "\"Locked\": %d,\n", this->locked);
  87. fprintf(fp, "\"MaterialSet\": %d,\n", this->materialSet);
  88. if (this->haveFiniteBounds())
  89. {
  90. fprintf(fp, "\"BoundingBox\": {\n");
  91. this->getBounds().dumpMe(fp);
  92. fprintf(fp, "},\n");
  93. }
  94. fprintf(fp, "\"id\": %p,\n", this);
  95. if (this->parent)
  96. {
  97. fprintf(fp, "\"parentId\": %p,\n", this->parent);
  98. }
  99. }