Files
dorayme/source/shapes/shape.cpp
Godzil 9849c16f66 Couple of small optimisation
Add option to build for gprof
Do not build by default with the renderstat (they have a reasonable impact on performances)
Separated created ray and castedray in the stats
Trying to force some simple function to be inlined
2020-03-13 18:22:35 +00:00

136 lines
3.3 KiB
C++

/*
* DoRayMe - a quick and dirty Raytracer
* Object implementation
*
* Created by Manoël Trapier
* Copyright (c) 2020 986-Studio.
*
*/
#include <ray.h>
#include <shape.h>
#include <matrix.h>
#include <tuple.h>
#include <intersect.h>
Shape::Shape(ShapeType type)
{
this->objectId = Shape::newObjectId();
this->locked = false;
this->parent = nullptr;
this->dropShadow = true;
this->type = type;
this->localTransformMatrix = Matrix4().identity();
this->materialSet = false;
this->updateTransform();
}
uint64_t Shape::newObjectId()
{
static uint64_t id = 0;
uint64_t ret;
ret = id++;
return ret;
}
Tuple Shape::normalToWorld(Tuple normalVector)
{
Tuple world_normal = this->transposedInverseTransform * normalVector;
/* W may get wrong, so hack it. This is perfectly normal as we are using a 4x4 matrix instead of a 3x3 */
world_normal.w = 0;
return world_normal.normalise();
};
Tuple Shape::normalAt(Tuple point, Intersection *hit)
{
Tuple local_point = this->worldToObject(point);
Tuple local_normal = this->localNormalAt(local_point, hit);
Tuple world_normal = this->normalToWorld(local_normal);
return world_normal;
}
void Shape::updateTransform()
{
if (this->locked) return;
this->transformMatrix = this->localTransformMatrix;
if (this->parent != nullptr)
{
this->transformMatrix = this->parent->transformMatrix * this->transformMatrix;
}
this->inverseTransform = this->transformMatrix.inverse();
this->transposedInverseTransform = this->inverseTransform.transpose();
}
void Shape::setTransform(Matrix transform)
{
if (this->locked) return;
this->localTransformMatrix = transform;
this->updateTransform();
}
BoundingBox Shape::getLocalBounds()
{
return BoundingBox(Point(-1, -1, -1), Point(1,1,1));
}
BoundingBox Shape::getBounds()
{
BoundingBox ret;
BoundingBox me = this->getLocalBounds();
ret | this->objectToWorld(Point(me.min.x, me.min.y, me.min.z));
ret | this->objectToWorld(Point(me.min.x, me.min.y, me.max.z));
ret | this->objectToWorld(Point(me.min.x, me.max.y, me.min.z));
ret | this->objectToWorld(Point(me.max.x, me.min.y, me.min.z));
ret | this->objectToWorld(Point(me.max.x, me.max.y, me.min.z));
ret | this->objectToWorld(Point(me.max.x, me.min.y, me.max.z));
ret | this->objectToWorld(Point(me.min.x, me.max.y, me.max.z));
ret | this->objectToWorld(Point(me.max.x, me.max.y, me.max.z));
return ret;
}
Material *Shape::getMaterial()
{
Shape *s = this;
while((!s->materialSet) && (s->parent != nullptr))
{
s = s->parent;
}
return &s->material;
}
void Shape::dumpMe(FILE *fp)
{
if (this->materialSet)
{
fprintf(fp, "\"Material\": {\n");
this->material.dumpMe(fp);
fprintf(fp, "},\n");
}
fprintf(fp, "\"DropShadow\": %d,\n", this->dropShadow);
fprintf(fp, "\"Locked\": %d,\n", this->locked);
fprintf(fp, "\"MaterialSet\": %d,\n", this->materialSet);
if (this->haveFiniteBounds())
{
fprintf(fp, "\"BoundingBox\": {\n");
this->getBounds().dumpMe(fp);
fprintf(fp, "},\n");
}
fprintf(fp, "\"id\": %ld,\n", this->getObjectId());
if (this->parent)
{
fprintf(fp, "\"parentId\": %ld,\n", this->parent->getObjectId());
}
}