OBJFile now use group instead of it own list.

Change the group function to find group by name, and now name group when needed, and change tests to use group name instead of number.

Also now the default group is the base group, not a separate group.

Bonus: Add a destructor to cleanup memory
Added a function to get base group. OBJFile will still behave as a valid shape, but now we can skip it in the generated world by adding the base group instead.

Code is now cleaner.
This commit is contained in:
Godzil
2020-03-09 16:03:27 +00:00
parent 66a8b98aeb
commit 15a861802a
3 changed files with 86 additions and 74 deletions

View File

@@ -18,9 +18,9 @@
class OBJFile : public Shape
{
private:
uint32_t allocatedFaceGroupCount;
Group* *faceGroupList;
uint32_t faceGroupCount;
Group *baseGroup;
Group *currentGroup;
uint32_t allocatedVertexCount;
Point* *vertexList;
@@ -51,16 +51,20 @@ public:
OBJFile();
OBJFile(const char *filepath);
~OBJFile();
int parseOBJFile(const char *content);
/* OBJ file expect the first vertice to be 1 and not 0 */
Point vertices(uint32_t i) { return *this->vertexList[i - 1]; };
Vector verticesNormal(uint32_t i) { return *this->vertexNormalList[i - 1]; };
Group *groups(uint32_t i) { return this->faceGroupList[i]; };
Group *groups(const char *groupName);
Intersect intersect(Ray r);
BoundingBox getLocalBounds();
BoundingBox getBounds();
Shape *getBaseGroup() { return this->baseGroup; };
bool includes(Shape *b);
void updateBoundingBox();
@@ -69,4 +73,6 @@ public:
void dumpMe(FILE * fp);
};
#define OBJ_DEFAULT_GROUP "_DefaultObjGroup_"
#endif /* DORAYME_OBJFILE_H */

View File

@@ -26,23 +26,49 @@ OBJFile::OBJFile() : Shape(Shape::OBJFILE), ignoredLines(0)
{
stats.addOBJFile();
this->allocatedFaceGroupCount = MIN_ALLOC;
this->faceGroupList = (Group **)calloc(sizeof(Group **), MIN_ALLOC);
this->faceGroupCount = 0;
this->allocatedVertexCount = MIN_ALLOC;
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());
/* The base group */
this->baseGroup = new Group(OBJ_DEFAULT_GROUP);
this->currentGroup = this->baseGroup;
};
OBJFile::~OBJFile()
{
int i;
if (vertexCount > 0)
{
for(i = 0; i < vertexCount; i++)
{
delete this->vertexList[i];
this->vertexList[i] = nullptr;
}
}
free(this->vertexList);
this->vertexList = nullptr;
if (vertexNormalCount > 0)
{
for(i = 0; i < vertexNormalCount; i++)
{
delete this->vertexNormalList[i];
this->vertexNormalList[i] = nullptr;
}
}
free(this->vertexNormalList);
this->vertexNormalList = nullptr;
/* It is not our responsibility to clear the group object as this object may be destroyed before the
* render is done
*/
}
OBJFile::OBJFile(const char *filepath) : OBJFile()
{
FILE *fp;
@@ -71,18 +97,13 @@ OBJFile::OBJFile(const char *filepath) : OBJFile()
void OBJFile::addGroup(Group *group)
{
if ((this->faceGroupCount + 1) > this->allocatedFaceGroupCount)
{
this->allocatedFaceGroupCount *= 2;
this->faceGroupList = (Group **)realloc(this->faceGroupList, sizeof(Group **) * this->allocatedFaceGroupCount);
}
this->baseGroup->addObject(group);
group->parent = this;
group->updateTransform();
this->faceGroupList[this->faceGroupCount++] = group;
this->bounds | group->getBounds();
this->currentGroup = group;
}
void OBJFile::addVertex(Point *vertex)
@@ -107,44 +128,40 @@ void OBJFile::addVertexNormal(Vector *vertexNormal)
this->vertexNormalList[this->vertexNormalCount++] = vertexNormal;
}
Intersect OBJFile::intersect(Ray r)
Group *OBJFile::groups(const char *groupName)
{
Intersect ret;
int i, j;
if (this->faceGroupCount > 0)
if (strncmp(groupName, this->baseGroup->getName(), strlen(groupName)) == 0)
{
if (this->bounds.intesectMe(r))
return this->baseGroup;
}
int i;
for(i = 0; i < this->baseGroup->getObjectCount(); i++)
{
Shape *cur = (*this->baseGroup)[i];
if (cur->getType() == Shape::GROUP)
{
for (i = 0 ; i < this->faceGroupCount ; i++)
Group *curGrp = (Group *)cur;
if (strncmp(groupName, curGrp->getName(), strlen(groupName)) == 0)
{
Intersect xs = this->faceGroupList[i]->intersect(r);
if (xs.count() > 0)
{
for (j = 0 ; j < xs.count() ; j++)
{
ret.add(xs[j]);
}
}
return curGrp;
}
}
}
return ret;
/* Not found */
return nullptr;
}
Intersect OBJFile::intersect(Ray r)
{
return this->baseGroup->intersect(r);
}
bool OBJFile::includes(Shape *b)
{
int i;
if (this->faceGroupCount > 0)
{
for (i = 0 ; i < this->faceGroupCount ; i++)
{
if (this->faceGroupList[i] == b)
{
return true;
}
}
}
return false;
return this->baseGroup->includes(b);
}
Intersect OBJFile::localIntersect(Ray r)
@@ -173,14 +190,7 @@ void OBJFile::updateBoundingBox()
int i;
this->bounds.reset();
for(i = 0; i < this->faceGroupCount; i++)
{
if (this->faceGroupList[i]->haveFiniteBounds())
{
BoundingBox objB = this->faceGroupList[i]->getBounds();
this->bounds | objB;
}
}
this->bounds | this->baseGroup->getBounds();
}
void OBJFile::updateTransform()
@@ -188,10 +198,8 @@ void OBJFile::updateTransform()
int i;
Shape::updateTransform();
for (i = 0 ; i < this->faceGroupCount ; i++)
{
this->faceGroupList[i]->updateTransform();
}
this->baseGroup->updateTransform();
/* Once the full stack being notified of the changes, let's update the
* bounding box
@@ -204,12 +212,7 @@ void OBJFile::dumpMe(FILE * fp)
int i;
fprintf(fp, "\"Type\": \"OBJFile\",\n");
fprintf(fp, "\"Objects\": {\n");
for(i = 0; i < this->faceGroupCount; i++)
{
fprintf(fp, "\"%d\": {\n", i);
this->faceGroupList[i]->dumpMe(fp);
fprintf(fp, "},\n");
}
this->baseGroup->dumpMe(fp);
fprintf(fp, "},\n");
Shape::dumpMe(fp);
@@ -399,7 +402,7 @@ int OBJFile::execLine(int argc, char *argv[], uint32_t currentLine)
this->verticesNormal(vn[2]),
this->verticesNormal(vn[3]));
}
this->faceGroupList[this->faceGroupCount - 1]->addObject(t);
this->currentGroup->addObject(t);
ret = 0;
}
else if (argc > 4)
@@ -423,7 +426,7 @@ int OBJFile::execLine(int argc, char *argv[], uint32_t currentLine)
this->verticesNormal(vn[i]),
this->verticesNormal(vn[i + 1]));
}
this->faceGroupList[this->faceGroupCount - 1]->addObject(t);
this->currentGroup->addObject(t);
}
ret = 0;
}
@@ -436,7 +439,7 @@ int OBJFile::execLine(int argc, char *argv[], uint32_t currentLine)
{
if (argc == 2)
{
this->addGroup(new Group());
this->addGroup(new Group(argv[1]));
}
else
{

View File

@@ -55,7 +55,7 @@ TEST(OBJFileTest, Parsing_triangle_faces)
OBJFile parser = OBJFile();
parser.parseOBJFile(file);
Group *g0 = parser.groups(0);
Group *g0 = parser.groups(OBJ_DEFAULT_GROUP);
Triangle *t1 = (Triangle *)(*g0)[0];
Triangle *t2 = (Triangle *)(*g0)[1];
@@ -82,7 +82,7 @@ TEST(OBJFileTest, Triangulating_polygons)
OBJFile parser = OBJFile();
parser.parseOBJFile(file);
Group *g0 = parser.groups(0);
Group *g0 = parser.groups(OBJ_DEFAULT_GROUP);
Triangle *t1 = (Triangle *)(*g0)[0];
Triangle *t2 = (Triangle *)(*g0)[1];
@@ -105,9 +105,12 @@ TEST(OBJFileTest, Triangle_in_groups)
{
OBJFile parser = OBJFile("triangles.obj");
/* TODO: Add group name search/test */
Group *g1 = parser.groups(1);
Group *g2 = parser.groups(2);
Group *g1 = parser.groups("FirstGroup");
Group *g2 = parser.groups("SecondGroup");
/* The groups must exists */
ASSERT_NE(g1, nullptr);
ASSERT_NE(g2, nullptr);
Triangle *t1 = (Triangle *)(*g1)[0];
Triangle *t2 = (Triangle *)(*g2)[0];
@@ -151,7 +154,7 @@ TEST(OBJFileTest, Faces_with_normal)
OBJFile parser = OBJFile();
parser.parseOBJFile(file);
Group *g0 = parser.groups(0);
Group *g0 = parser.groups(OBJ_DEFAULT_GROUP);
SmoothTriangle *t1 = (SmoothTriangle *)(*g0)[0];
SmoothTriangle *t2 = (SmoothTriangle *)(*g0)[1];