Smooth triangles! And support for them in the OBJ File parser.

Also add an interesting tea party scene!
This commit is contained in:
Godzil
2020-03-06 15:07:26 +00:00
parent 73012b6dd1
commit e57b5715e8
38 changed files with 705 additions and 75 deletions

View File

@@ -99,7 +99,7 @@ Intersect Cone::localIntersect(Ray r)
return ret;
}
Tuple Cone::localNormalAt(Tuple point)
Tuple Cone::localNormalAt(Tuple point, Intersection *hit)
{
/* Compute the square of the distance from the Y axis */
double dist = point.x * point.x + point.z * point.z;

View File

@@ -59,7 +59,7 @@ Intersect Cube::localIntersect(Ray r)
return ret;
}
Tuple Cube::localNormalAt(Tuple point)
Tuple Cube::localNormalAt(Tuple point, Intersection *hit)
{
double maxC = max3(fabs(point.x), fabs(point.y), fabs(point.z));

View File

@@ -90,7 +90,7 @@ Intersect Cylinder::localIntersect(Ray r)
return ret;
}
Tuple Cylinder::localNormalAt(Tuple point)
Tuple Cylinder::localNormalAt(Tuple point, Intersection *hit)
{
/* Compute the square of the distance from the Y axis */
double dist = point.x * point.x + point.z * point.z;

View File

@@ -72,7 +72,7 @@ Intersect Group::localIntersect(Ray r)
return Intersect();
}
Tuple Group::localNormalAt(Tuple point)
Tuple Group::localNormalAt(Tuple point, Intersection *hit)
{
return Vector(1, 0, 0);
}

View File

@@ -17,6 +17,7 @@
#include <math_helper.h>
#include <group.h>
#include <triangle.h>
#include <smoothtriangle.h>
#define MIN_ALLOC (2)
#define DEFAULT_GROUP (0)
@@ -33,6 +34,11 @@ OBJFile::OBJFile() : Shape(SHAPE_OBJFILE), ignoredLines(0)
this->vertexList = (Point **)calloc(sizeof(Point **), MIN_ALLOC);
this->vertexCount = 0;
this->allocatedVertexNormalCount = MIN_ALLOC;
this->vertexNormalList = (Vector **)calloc(sizeof(Vector **), MIN_ALLOC);
this->vertexNormalCount = 0;
/* There is always a default group */
this->addGroup(new Group());
};
@@ -89,13 +95,24 @@ void OBJFile::addVertex(Point *vertex)
this->vertexList[this->vertexCount++] = vertex;
}
void OBJFile::addVertexNormal(Vector *vertexNormal)
{
if ((this->vertexNormalCount + 1) > this->allocatedVertexNormalCount)
{
this->allocatedVertexNormalCount *= 2;
this->vertexNormalList = (Vector **)realloc(this->vertexNormalList, sizeof(Vector **) * this->allocatedVertexNormalCount);
}
this->vertexNormalList[this->vertexNormalCount++] = vertexNormal;
}
Intersect OBJFile::intersect(Ray r)
{
Intersect ret;
int i, j;
if (this->faceGroupCount > 0)
{
//if (this->bounds.intesectMe(r))
if (this->bounds.intesectMe(r))
{
for (i = 0 ; i < this->faceGroupCount ; i++)
{
@@ -118,7 +135,7 @@ Intersect OBJFile::localIntersect(Ray r)
return Intersect();
}
Tuple OBJFile::localNormalAt(Tuple point)
Tuple OBJFile::localNormalAt(Tuple point, Intersection *hit)
{
return Vector(0, 1, 0);
}
@@ -262,11 +279,51 @@ void OBJFile::parseLine(char *line, uint32_t currentLine)
}
}
static int parseFaceVertex(char *buf, uint32_t &v, uint32_t &vt, uint32_t &vn)
{
uint32_t bufPos = 0;
uint32_t lineLength = strlen(buf);
char *tmp = buf;
vt = INT32_MAX;
vn = INT32_MAX;
int ret = 0;
int token = 0;
while(bufPos < lineLength)
{
char *next = strchr(buf, '/');
if (next != nullptr)
{
*next = '\0';
bufPos = next - buf;
}
else
{
bufPos = lineLength;
}
if (strlen(buf) > 0)
{
switch(token)
{
case 0: v = atol(buf); break;
case 1: vt = atol(buf); break;
case 2: vn = atol(buf); break;
default: printf("ERROR: Too many entry for a face vertice!"); ret = 1;
}
}
buf = next + 1;
token++;
}
return ret;
}
/* Actually execute the line */
int OBJFile::execLine(int argc, char *argv[], uint32_t currentLine)
{
int ret = 1;
if (strncmp(argv[0], "v", 1) == 0)
if (strncmp(argv[0], "v", 2) == 0)
{
/* Vertice entry */
if (argc != 4)
@@ -279,25 +336,71 @@ int OBJFile::execLine(int argc, char *argv[], uint32_t currentLine)
ret = 0;
}
}
else if (strncmp(argv[0], "f", 1) == 0)
else if (strncmp(argv[0], "vn", 3) == 0)
{
/* Vertice entry */
/* Vertice Normal entry */
if (argc != 4)
{
printf("ERROR: Malformed file at line %d: Vertices normal expect 3 parameters!\n", currentLine);
}
else
{
this->addVertexNormal(new Vector(atof(argv[1]), atof(argv[2]), atof(argv[3])));
ret = 0;
}
}
else if (strncmp(argv[0], "f", 2) == 0)
{
/* Faces entry */
int i;
uint32_t v[MAX_ARGS], vt[MAX_ARGS], vn[MAX_ARGS];
for(i = 1; i < argc; i++)
{
parseFaceVertex(argv[i], v[i], vt[i], vn[i]);
}
if (argc == 4)
{
Shape *t = new Triangle(this->vertices(atoi(argv[1])),
this->vertices(atoi(argv[2])),
this->vertices(atoi(argv[3])));
Shape *t;
if (vn[1] == INT32_MAX)
{
t = new Triangle(this->vertices(v[1]),
this->vertices(v[2]),
this->vertices(v[3]));
}
else
{
t = new SmoothTriangle(this->vertices(v[1]),
this->vertices(v[2]),
this->vertices(v[3]),
this->verticesNormal(vn[1]),
this->verticesNormal(vn[2]),
this->verticesNormal(vn[3]));
}
this->faceGroupList[this->faceGroupCount - 1]->addObject(t);
ret = 0;
}
else if (argc > 4)
{
int i;
for(i = 2; i < (argc - 1); i++)
{
Shape *t = new Triangle(this->vertices(atoi(argv[1])),
this->vertices(atoi(argv[i])),
this->vertices(atoi(argv[i+1])));
Shape *t;
if (vn[1] == INT32_MAX)
{
t = new Triangle(this->vertices(v[1]),
this->vertices(v[i]),
this->vertices(v[i + 1]));
}
else
{
t = new SmoothTriangle(this->vertices(v[1]),
this->vertices(v[i]),
this->vertices(v[i + 1]),
this->verticesNormal(vn[1]),
this->verticesNormal(vn[i]),
this->verticesNormal(vn[i + 1]));
}
this->faceGroupList[this->faceGroupCount - 1]->addObject(t);
}
ret = 0;
@@ -307,7 +410,7 @@ int OBJFile::execLine(int argc, char *argv[], uint32_t currentLine)
printf("ERROR: Malformed file at line %d: Too few/many parameters!\n", currentLine);
}
}
else if (strncmp(argv[0], "g", 1) == 0)
else if (strncmp(argv[0], "g", 2) == 0)
{
if (argc == 2)
{

View File

@@ -30,7 +30,7 @@ Intersect Plane::localIntersect(Ray r)
return ret;
}
Tuple Plane::localNormalAt(Tuple point)
Tuple Plane::localNormalAt(Tuple point, Intersection *hit)
{
return Vector(0, 1, 0);
}

View File

@@ -20,6 +20,7 @@ Shape::Shape(ShapeType type)
this->type = type;
this->localTransformMatrix = Matrix4().identity();
this->updateTransform();
this->materialSet = false;
}
Intersect Shape::intersect(Ray r)
@@ -37,11 +38,11 @@ Tuple Shape::normalToWorld(Tuple normalVector)
return world_normal.normalise();
};
Tuple Shape::normalAt(Tuple point)
Tuple Shape::normalAt(Tuple point, Intersection *hit)
{
Tuple local_point = this->worldToObject(point);
Tuple local_normal = this->localNormalAt(local_point);
Tuple local_normal = this->localNormalAt(local_point, hit);
Tuple world_normal = this->normalToWorld(local_normal);

View File

@@ -0,0 +1,28 @@
/*
* DoRayMe - a quick and dirty Raytracer
* Smooth Triangle implementation
*
* Created by Manoël Trapier
* Copyright (c) 2020 986-Studio.
*
*/
#include <ray.h>
#include <shape.h>
#include <triangle.h>
#include <smoothtriangle.h>
#include <math_helper.h>
#include <renderstat.h>
SmoothTriangle::SmoothTriangle(Point p1, Point p2, Point p3, Vector n1, Vector n2, Vector n3) : Triangle(p1, p2, p3),
n1(n1), n2(n2), n3(n3)
{
this->type = SHAPE_SMOOTHTRIANGLE;
stats.addSmoothTriangle();
}
Tuple SmoothTriangle::localNormalAt(Tuple point, Intersection *hit)
{
return (this->n2 * hit->u +
this->n3 * hit->v +
this->n1 * (1 - hit->u - hit->v)).normalise();
}

View File

@@ -35,7 +35,7 @@ Intersect Sphere::localIntersect(Ray r)
return ret;
}
Tuple Sphere::localNormalAt(Tuple point)
Tuple Sphere::localNormalAt(Tuple point, Intersection *hit)
{
return (point - Point(0, 0, 0)).normalise();
}

View File

@@ -19,7 +19,7 @@ Intersect TestShape::localIntersect(Ray r)
return Intersect();
}
Tuple TestShape::localNormalAt(Tuple point)
Tuple TestShape::localNormalAt(Tuple point, Intersection *hit)
{
return Vector(point.x, point.y, point.z);
}

View File

@@ -1,6 +1,6 @@
/*
* DoRayMe - a quick and dirty Raytracer
* Cone implementation
* Triangle implementation
*
* Created by Manoël Trapier
* Copyright (c) 2020 986-Studio.
@@ -49,12 +49,12 @@ Intersect Triangle::localIntersect(Ray r)
}
double t = f * this->e2.dot(originCrossE1);
ret.add(Intersection(t, this));
ret.add(Intersection(t, this, u, v));
return ret;
}
Tuple Triangle::localNormalAt(Tuple point)
Tuple Triangle::localNormalAt(Tuple point, Intersection *hit)
{
return this->normal;
}