diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..95c3150 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +build/* +*.swp +*.kdev4 +.kdev4/* + diff --git a/source/main.cpp b/source/main.cpp index db50373..0dbe6bc 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,182 +1,13 @@ -//Computational Fabrication Assignment #1 -// Created by David Levin 2014 -// Modified by Shinjiro Sueda 2016 +// Procedural City Generator +// Alex Huddleston +// 2016 #include +#include #include #include "../include/CompFab.h" #include "../include/Mesh.h" -//Triangle list (global) -typedef std::vector TriangleList; - -TriangleList g_triangleList; -CompFab::VoxelGrid *g_voxelGrid; - -bool loadMesh(char *filename, unsigned int num) -{ - g_triangleList.clear(); - - Mesh *tempMesh = new Mesh(filename, true); - - CompFab::Vec3 v1, v2, v3; - - //copy triangles to global list - for(unsigned int tri =0; trit.size(); ++tri) - { - v1 = tempMesh->v[tempMesh->t[tri][0]]; - v2 = tempMesh->v[tempMesh->t[tri][1]]; - v3 = tempMesh->v[tempMesh->t[tri][2]]; - g_triangleList.push_back(CompFab::Triangle(v1,v2,v3)); - } - - //Create Voxel Grid - CompFab::Vec3 bbMax, bbMin; - BBox(*tempMesh, bbMin, bbMax); - - //Build Voxel Grid - double bbX = bbMax[0] - bbMin[0]; - double bbY = bbMax[1] - bbMin[1]; - double bbZ = bbMax[2] - bbMin[2]; - double spacing; - - if(bbX > bbY && bbX > bbZ) - { - spacing = bbX/(num-1); - } else if(bbY > bbX && bbY > bbZ) { - spacing = bbY/(num-1); - } else { - spacing = bbZ/(num-1); - } - - g_voxelGrid = new CompFab::VoxelGrid(bbMin, num, num, num, spacing); - - delete tempMesh; - - return true; - -} - -void saveVoxelsToObj(const char * outfile) -{ - Mesh box; - Mesh mout; - int nx = g_voxelGrid->m_numX; - int ny = g_voxelGrid->m_numY; - int nz = g_voxelGrid->m_numZ; - double spacing = g_voxelGrid->m_spacing; - - CompFab::Vec3 hspacing(0.5*spacing, 0.5*spacing, 0.5*spacing); - - for (int ii = 0; ii < nx; ii++) { - for (int jj = 0; jj < ny; jj++) { - for (int kk = 0; kk < nz; kk++) { - if(!g_voxelGrid->isInside(ii,jj,kk)){ - continue; - } - CompFab::Vec3 coord(0.5f + ((double)ii)*spacing, 0.5f + ((double)jj)*spacing, 0.5f+((double)kk)*spacing); - CompFab::Vec3 box0 = coord - hspacing; - CompFab::Vec3 box1 = coord + hspacing; - makeCube(box, box0, box1); - mout.append(box); - } - } - } - - mout.save_obj(outfile); -} - -// Code referenced is sourced in README.txt -bool triangleIntersection(CompFab::Vec3 V1, CompFab::Vec3 V2, CompFab::Vec3 V3, CompFab::Vec3 O, CompFab::Vec3 D) -{ - CompFab::Vec3 e1, e2; //Edge1, Edge2 - CompFab::Vec3 P, Q, T; - double det, inv_det, u, v; - double t; - - //Find vectors for two edges sharing V1 - e1 = V2 - V1; - e2 = V3 - V1; - //Begin calculating determinant - also used to calculate u parameter - P = D % e2; - //if determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle - det = e1 * P; - //NOT CULLING - if (det > -EPSILON && det < EPSILON) return false; - inv_det = 1.f / det; - - //calculate distance from V1 to ray origin - T = O - V1; - - //Calculate u parameter and test bound - u = (T * P) * inv_det; - //The intersection lies outside of the triangle - if (u < 0.f || u > 1.f) return false; - - //Prepare to test v parameter - Q = T % e1; - - //Calculate V parameter and test bound - v = (D * Q) * inv_det; - //The intersection lies outside of the triangle - if (v < 0.f || u + v > 1.f) return false; - - t = (e2 * Q) * inv_det; - - if (t > EPSILON) { //ray intersection - return true; - } - - // No hit, no win - return false; -} - -int castRays(CompFab::Vec3 t_origin) -{ - - // 6 separate counter variables for the 6 raycasts. Additional coutner to count how many of them counted a voxel as being "inside" - int rc = 0, c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0; - - // Calculating triangle intersections for each triangle with all 6 raycasts. - for (int i = 0; i < g_triangleList.size(); i++) - { - if (triangleIntersection(g_triangleList.at(i).m_v1, g_triangleList.at(i).m_v2, g_triangleList.at(i).m_v3, t_origin, CompFab::Vec3(1, 0, 0))) - { - ++c1; - } - if (triangleIntersection(g_triangleList.at(i).m_v1, g_triangleList.at(i).m_v2, g_triangleList.at(i).m_v3, t_origin, CompFab::Vec3(-1, 0, 0))) - { - ++c2; - } - if (triangleIntersection(g_triangleList.at(i).m_v1, g_triangleList.at(i).m_v2, g_triangleList.at(i).m_v3, t_origin, CompFab::Vec3(0, 1, 0))) - { - ++c3; - } - if (triangleIntersection(g_triangleList.at(i).m_v1, g_triangleList.at(i).m_v2, g_triangleList.at(i).m_v3, t_origin, CompFab::Vec3(0, -1, 0))) - { - ++c4; - } - if (triangleIntersection(g_triangleList.at(i).m_v1, g_triangleList.at(i).m_v2, g_triangleList.at(i).m_v3, t_origin, CompFab::Vec3(0, 0, 1))) - { - ++c5; - } - if (triangleIntersection(g_triangleList.at(i).m_v1, g_triangleList.at(i).m_v2, g_triangleList.at(i).m_v3, t_origin, CompFab::Vec3(0, 0, -1))) - { - ++c6; - } - } - - // Determining which triangle intersections were valid. - if (c1 % 2 == 1) ++rc; - if (c2 % 2 == 1) ++rc; - if (c3 % 2 == 1) ++rc; - if (c4 % 2 == 1) ++rc; - if (c5 % 2 == 1) ++rc; - if (c6 % 2 == 1) ++rc; - - return rc; -} - void findLW(Mesh &m, double &l, double &w) { double minl, maxl, minw, maxw; @@ -207,86 +38,44 @@ int main(int argc, char **argv) { unsigned int num = 16; //number of voxels (e.g. 16x16x16) - if(argc < 4) + if(argc < 3) { - Mesh *test = new Mesh(argv[1], false); - Mesh *output = new Mesh(test->v, test->t); - double l = 0, w = 0; - double *length = &l, *width = &w; - findLW(*test, *length, *width); - for(int i = 0; i < test->v.size(); i++) - { - output->v.push_back(*new CompFab::Vec3(test->v[i].m_x + *length + 1, test->v[i].m_y, test->v[i].m_z)); - } - for(int k = 0; k < test->t.size(); k++) - { - output->t.push_back(*new CompFab::Vec3i(test->t[k].m_x + test->v.size(), test->t[k].m_y + test->v.size(), test->t[k].m_z + test->v.size())); - } - for(int j = 0; j < output->v.size(); j++) - { - std::cout << output->v[j].m_x << " " << output->v[j].m_y << " " << output->v[j].m_z << std::endl; - std::cout << output->t[j].m_x << " " << output->t[j].m_y << " " << output->t[j].m_z << std::endl; - std::cout << std::endl; - } - output->save(argv[2]); + std::cout << "Usage: [executable] [template].obj output.obj [optional: -d for debugging output]" << std::endl; + std::exit(1); } - else + Mesh *test = new Mesh(argv[1], false); + Mesh *output = new Mesh(test->v, test->t); + double l = 0, w = 0; + double *length = &l, *width = &w; + findLW(*test, *length, *width); + for(int i = 0; i < test->v.size(); i++) { - num = atoi(argv[3]); - - // The loadMesh() function loads the mesh and then creates: - // - g_triangleList: The list of triangles in the input OBJ mesh - // - g_voxelGrid: The VoxelGrid object, with all voxels marked as unoccupied - std::cout<<"Load Mesh : "<m_numX is the number of voxels in the X direction. - // g_voxelGrid->m_numY is the number of voxels in the Y direction. - // g_voxelGrid->m_numZ is the number of voxels in the Z direction. - // g_voxelGrid->m_spacing is the size of each voxel. - // - // Inside the triple for-loop, check if the voxel is inside or outside the - // mesh. Use the g_voxelGrid->isInside(...) method to set whether that voxel - // is inside or outside. E.g., - // g_voxelGrid->isInside(0,0,0) = false; - - // - - // Temp varaible for the current corner - CompFab::Vec3 t_corner = g_voxelGrid->m_corner; - - // Temp varaible for the current center - CompFab::Vec3 t_origin; - - for (unsigned int i_x = 0; i_x < g_voxelGrid->m_numX; i_x++) - { - for (unsigned int i_y = 0; i_y < g_voxelGrid->m_numY; i_y++) - { - for (unsigned int i_z = 0; i_z < g_voxelGrid->m_numZ; i_z++) - { - - // Finding the corner of the current voxel. - t_corner.m_x = g_voxelGrid->m_corner.m_x + i_x*g_voxelGrid->m_spacing; - t_corner.m_y = g_voxelGrid->m_corner.m_y + i_y*g_voxelGrid->m_spacing; - t_corner.m_z = g_voxelGrid->m_corner.m_z + i_z*g_voxelGrid->m_spacing; - - // Finding the origin of the current voxel. - t_origin.m_x = t_corner.m_x + 0.5*g_voxelGrid->m_spacing; - t_origin.m_y = t_corner.m_y + 0.5*g_voxelGrid->m_spacing; - t_origin.m_z = t_corner.m_z + 0.5*g_voxelGrid->m_spacing; - - // Will say "inside" if 4 or more of the raycasts determine a voxel to be inside. - g_voxelGrid->isInside(i_x, i_y, i_z) = (castRays(t_origin) >= 4); - } - } - } - - // Write out voxel data as obj - saveVoxelsToObj(argv[2]); + output->v.push_back(*new CompFab::Vec3(test->v[i].m_x + *length + 1, test->v[i].m_y, test->v[i].m_z)); + } + for(int k = 0; k < test->t.size(); k++) + { + output->t.push_back(*new CompFab::Vec3i(test->t[k].m_x + test->v.size(), test->t[k].m_y + test->v.size(), test->t[k].m_z + test->v.size())); } - delete g_voxelGrid; + // Debugging + if(argc > 3) + { + if(strcmp(argv[3], "-d") == 0) + { + for(int j = 0; j < output->v.size(); j++) + { + std::cout << output->v[j].m_x << " " << output->v[j].m_y << " " << output->v[j].m_z << std::endl; + std::cout << output->t[j].m_x << " " << output->t[j].m_y << " " << output->t[j].m_z << std::endl; + std::cout << std::endl; + } + } + else + { + std::cout << "Usage: [executable] [template].obj output.obj [optional: -d for debugging output]" << std::endl; + } + } + + output->save(argv[2]); + + std::cout << "Success." << std::endl; }