/* * DoRayMe - a quick and dirty Raytracer * Object header * * Created by Manoƫl Trapier * Copyright (c) 2020 986-Studio. * */ #ifndef DORAYME_SHAPE_H #define DORAYME_SHAPE_H class Shape; #include #include #include #include #include #include #include /* Base class for all object that can be presented in the world */ class Shape { public: enum ShapeType { NONE, SPHERE, PLANE, CUBE, CYLINDER, CONE, GROUP, TRIANGLE, OBJFILE, SMOOTHTRIANGLE, CSG, }; protected: ShapeType type; Matrix localTransformMatrix; bool locked; protected: virtual Intersect localIntersect(Ray r) = 0; virtual Tuple localNormalAt(Tuple point, Intersection *hit) = 0; public: Matrix transformMatrix; Matrix inverseTransform; Matrix transposedInverseTransform; Material material; bool dropShadow; Shape *parent; bool materialSet; public: Shape(ShapeType = Shape::NONE); ShapeType getType() { return this->type; }; virtual Intersect intersect(Ray r); Tuple normalAt(Tuple point, Intersection *hit = nullptr); /* Bounding box points are always world value */ virtual BoundingBox getLocalBounds(); virtual BoundingBox getBounds(); virtual bool haveFiniteBounds() { return true; }; virtual void updateTransform(); virtual bool includes(Shape *b) { return this == b; }; 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); }; Ray invTransform(Ray r) { return Ray(this->inverseTransform * r.origin, this->inverseTransform * r.direction); }; bool operator==(const Shape &b) const { return this->material == b.material && this->type == b.type && this->transformMatrix == b.transformMatrix; }; }; #endif /* DORAYME_SHAPE_H */