shape.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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->parent = nullptr;
  17. this->dropShadow = true;
  18. this->type = type;
  19. this->localTransformMatrix = Matrix4().identity();
  20. this->updateTransform();
  21. }
  22. Intersect Shape::intersect(Ray r)
  23. {
  24. return this->localIntersect(this->invTransform(r));
  25. };
  26. Tuple Shape::normalToWorld(Tuple normalVector)
  27. {
  28. Tuple world_normal = this->transposedInverseTransform * normalVector;
  29. /* W may get wrong, so hack it. This is perfectly normal as we are using a 4x4 matrix instead of a 3x3 */
  30. world_normal.w = 0;
  31. return world_normal.normalise();
  32. };
  33. Tuple Shape::normalAt(Tuple point)
  34. {
  35. Tuple local_point = this->worldToObject(point);
  36. Tuple local_normal = this->localNormalAt(local_point);
  37. Tuple world_normal = this->normalToWorld(local_normal);
  38. return world_normal;
  39. }
  40. void Shape::updateTransform()
  41. {
  42. this->transformMatrix = this->localTransformMatrix;
  43. if (this->parent != nullptr)
  44. {
  45. this->transformMatrix = this->parent->transformMatrix * this->transformMatrix;
  46. }
  47. this->inverseTransform = this->transformMatrix.inverse();
  48. this->transposedInverseTransform = this->inverseTransform.transpose();
  49. }
  50. void Shape::setTransform(Matrix transform)
  51. {
  52. this->localTransformMatrix = transform;
  53. this->updateTransform();
  54. }
  55. BoundingBox Shape::getLocalBounds()
  56. {
  57. return BoundingBox(Point(-1, -1, -1), Point(1,1,1));
  58. }
  59. BoundingBox Shape::getBounds()
  60. {
  61. BoundingBox ret;
  62. BoundingBox me = this->getLocalBounds();
  63. ret | this->objectToWorld(Point(me.min.x, me.min.y, me.min.z));
  64. ret | this->objectToWorld(Point(me.min.x, me.min.y, me.max.z));
  65. ret | this->objectToWorld(Point(me.min.x, me.max.y, me.min.z));
  66. ret | this->objectToWorld(Point(me.max.x, me.min.y, me.min.z));
  67. ret | this->objectToWorld(Point(me.max.x, me.max.y, me.min.z));
  68. ret | this->objectToWorld(Point(me.max.x, me.min.y, me.max.z));
  69. ret | this->objectToWorld(Point(me.min.x, me.max.y, me.max.z));
  70. ret | this->objectToWorld(Point(me.max.x, me.max.y, me.max.z));
  71. return ret;
  72. }
  73. void Shape::dumpMe(FILE *fp)
  74. {
  75. fprintf(fp, "\"Material\": {\n");
  76. this->material.dumpMe(fp);
  77. fprintf(fp, "},\n");
  78. fprintf(fp, "\"DropShadow\": %d,\n", this->dropShadow);
  79. fprintf(fp, "\"BoundingBox\": {\n");
  80. this->getBounds().dumpMe(fp);
  81. fprintf(fp, "},\n");
  82. }