shape.cpp 2.6 KB

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