The project is for the Computational Geometry/Computer Graphics graduate course. This is a 3D mesh viewer with support for parsing and serializing OBJ meshes. Implements loop subdivision using the Winged Edge data structure. Implements proper vertex normal / face normal calculation to support smooth/flat shading modes.
Preferred compiler is GNU C++ compiler. Tested with GNU C++ compiler on Linux and Visual C++ compiler on Windows.
- For Linux users
- Run
git submodule update --init --recursive
. - Compile and run the code as follows.
mkdir build cd build cmake ../ make ./subd
- Run
- For Windows users
- Run
git submodule update --init --recursive
. - Compile and run the code as follows.
Note: If you encouter render issues, copy the StandardShading.fragmentshader file and the StandardShading.vertexshader file to the target directory.
mkdir build cd build # In the next command, specify the version string according to your visual studio version. Win64 is necessary for nanogui. cmake -G "Visual Studio 15 2017 Win64" .. cmake --build . --config Debug Debug\subd.exe
- Run
- To perform subdivision, choose level of subdivision using the Subdivision count slider and click "Loop".
- To perform only tessellation used by Loop Subdivision (no vertex or edge rule applied), select appropriate subdivision count from slider and click "Tessellate". Switch to wireframe view to view the tessellation.
- Click "Reset" to reload the original mesh.
- Loop subdivision is implemented in
Subdivision/loopsubd.cpp
file.
- Whenever a mesh is loaded, it is automatically converted to a WingedEdge mesh. Upon saving, its converted back to an OBJ mesh.
- Rotation, zooming and translation was implemented using mouse controls and Model View Projection matrices. The model matrix is always identity. The view matrix changes as the user orbits / moves around an object. The projection matrix is an Orthogonal Projection, which changes its width and height based on zoom level.
- The camera is design to orbit around a target position, based on the rotation vector. The target position can be changed relative to the current view of camera by clicking and dragging the scene.
- In the example on Wireframe shading provided in assignment, back-sides are culled off. Thus, backsides are culled off in rendering.
- The WingedEdge structure is implemented in the directory WingedEdge. It uses classes Vertex, Edge and Face. The class WEMesh uses aforementioned classes to hold a mesh. It also implements following methods.
- The method
ComputeSmoothShadingMatrices
ofWEMesh
is used to populateposition
,normall
andindices
matrices for smooth shading. Vertex normals are calculated as the average of adjacent face's normals. - The method
ComputeFlatShadingMatrices
ofWEMesh
is used to populateposition
,normall
andindices
matrices for flat shading. New vertices are introduces such that unique normals can be defined for triangle faces. - The method
populateExpandedVertexMatrix
ofWEMesh
is used to populateexpandedPositions
used to render wireframe on top of shaded mesh. - The method
loadModel
ofWEMesh
is used to develop a WingedEdge mesh using two matricespositions
andindices
retrieved from an obj file. - The method
fillOBJMesh
ofWEMesh
is used to fill aOBJMesh
structure which can then be parsed as an OBJ file and save to disk.
- The method
- The OBJ parser is implemented by
WingedEdge/OBJMesh
class. It has methodsparseFile
andsaveFile
to load and save OBJ files. - For rendering WireFrame on top of shaded mesh, the mesh is expanded by
0.01
ormaximum distance between two vertices divided by 100
units, whichever is smallest. - Upon loading a new mesh, projection matrix is re-calculated to have left, bottom, top and right bounds be
maximum distance between two vertices divided by zoom
. Far plane is set to be2 * maximum distance between two vertices + 400
.