| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 |
- #include "thekla_atlas.h"
- #include <cfloat>
- #include <cstdio>
- #include <vector>
- #include <map>
- #include "nvmesh/halfedge/Edge.h"
- #include "nvmesh/halfedge/Mesh.h"
- #include "nvmesh/halfedge/Face.h"
- #include "nvmesh/halfedge/Vertex.h"
- #include "nvmesh/param/Atlas.h"
- #include "nvmesh/raster/Raster.h"
- #include "nvmath/Vector.inl"
- #include "nvmath/ftoi.h"
- #include "nvcore/Array.inl"
- #define STBI_IMAGE_NO_ATOMIC
- #include "../../STB/stb_image_write.h"
- using namespace Thekla;
- using namespace nv;
- inline Atlas_Output_Mesh * set_error(Atlas_Error * error, Atlas_Error code) {
- if (error) *error = code;
- return NULL;
- }
- static void input_to_mesh(const Atlas_Input_Mesh * input, HalfEdge::Mesh * mesh, Atlas_Error * error) {
- Array<uint> canonicalMap;
- canonicalMap.reserve(input->vertex_count);
- for (int i = 0; i < input->vertex_count; i++) {
- const Atlas_Input_Vertex & input_vertex = input->vertex_array[i];
- const float * pos = input_vertex.position;
- const float * nor = input_vertex.normal;
- const float * tex = input_vertex.uv;
- HalfEdge::Vertex * vertex = mesh->addVertex(Vector3(pos[0], pos[1], pos[2]));
- vertex->nor.set(nor[0], nor[1], nor[2]);
- vertex->tex.set(tex[0], tex[1]);
- canonicalMap.append(input_vertex.first_colocal);
- }
- mesh->linkColocalsWithCanonicalMap(canonicalMap);
- const int face_count = input->face_count;
- int non_manifold_faces = 0;
- for (int i = 0; i < face_count; i++) {
- const Atlas_Input_Face & input_face = input->face_array[i];
- int v0 = input_face.vertex_index[0];
- int v1 = input_face.vertex_index[1];
- int v2 = input_face.vertex_index[2];
- HalfEdge::Face * face = mesh->addFace(v0, v1, v2);
- if (face != NULL) {
- face->material = input_face.material_index;
- }
- else {
- non_manifold_faces++;
- }
- }
- mesh->linkBoundary();
- if (non_manifold_faces != 0 && error != NULL) {
- *error = Atlas_Error_Invalid_Mesh_Non_Manifold;
- }
- }
- static Atlas_Output_Mesh * mesh_atlas_to_output(const HalfEdge::Mesh * mesh, const Atlas & atlas, Atlas_Error * error) {
- Atlas_Output_Mesh * output = new Atlas_Output_Mesh;
- const MeshCharts * charts = atlas.meshAt(0);
- // Allocate vertices.
- const int vertex_count = charts->vertexCount();
- output->vertex_count = vertex_count;
- output->vertex_array = new Atlas_Output_Vertex[vertex_count];
- int w = 0;
- int h = 0;
- // Output vertices.
- const int chart_count = charts->chartCount();
- for (int i = 0; i < chart_count; i++) {
- const Chart * chart = charts->chartAt(i);
- uint vertexOffset = charts->vertexCountBeforeChartAt(i);
- const uint chart_vertex_count = chart->vertexCount();
- for (uint v = 0; v < chart_vertex_count; v++) {
- Atlas_Output_Vertex & output_vertex = output->vertex_array[vertexOffset + v];
- uint original_vertex = chart->mapChartVertexToOriginalVertex(v);
- output_vertex.xref = original_vertex;
- Vector2 uv = chart->chartMesh()->vertexAt(v)->tex;
- output_vertex.uv[0] = uv.x;
- output_vertex.uv[1] = uv.y;
- w = max(w, ftoi_ceil(uv.x));
- h = max(h, ftoi_ceil(uv.y));
- }
- }
- const int face_count = mesh->faceCount();
- output->index_count = face_count * 3;
- output->index_array = new int[face_count * 3];
- // Set face indices.
- for (int f = 0; f < face_count; f++) {
- uint c = charts->faceChartAt(f);
- uint i = charts->faceIndexWithinChartAt(f);
- uint vertexOffset = charts->vertexCountBeforeChartAt(c);
- const Chart * chart = charts->chartAt(c);
- nvDebugCheck(chart->faceAt(i) == f);
- const HalfEdge::Face * face = chart->chartMesh()->faceAt(i);
- const HalfEdge::Edge * edge = face->edge;
- output->index_array[3*f+0] = vertexOffset + edge->vertex->id;
- output->index_array[3*f+1] = vertexOffset + edge->next->vertex->id;
- output->index_array[3*f+2] = vertexOffset + edge->next->next->vertex->id;
- }
- *error = Atlas_Error_Success;
- output->atlas_width = w;
- output->atlas_height = h;
- return output;
- }
- void Thekla::atlas_set_default_options(Atlas_Options * options) {
- if (options != NULL) {
- // These are the default values we use on The Witness.
- options->charter = Atlas_Charter_Default;
- options->charter_options.witness.proxy_fit_metric_weight = 2.0f;
- options->charter_options.witness.roundness_metric_weight = 0.01f;
- options->charter_options.witness.straightness_metric_weight = 6.0f;
- options->charter_options.witness.normal_seam_metric_weight = 4.0f;
- options->charter_options.witness.texture_seam_metric_weight = 0.5f;
- options->charter_options.witness.max_chart_area = FLT_MAX;
- options->charter_options.witness.max_boundary_length = FLT_MAX;
- options->mapper = Atlas_Mapper_Default;
- options->packer = Atlas_Packer_Default;
- options->packer_options.witness.packing_quality = 0;
- options->packer_options.witness.texel_area = 8;
- options->packer_options.witness.block_align = true;
- options->packer_options.witness.conservative = false;
- }
- }
- Atlas_Output_Mesh * Thekla::atlas_generate(const Atlas_Input_Mesh * input, const Atlas_Options * options, Atlas_Error * error) {
- // Validate args.
- if (input == NULL || options == NULL || error == NULL) return set_error(error, Atlas_Error_Invalid_Args);
- // Validate options.
- if (options->charter != Atlas_Charter_Witness) {
- return set_error(error, Atlas_Error_Invalid_Options);
- }
- if (options->charter == Atlas_Charter_Witness) {
- // @@ Validate input options!
- }
- if (options->mapper != Atlas_Mapper_LSCM) {
- return set_error(error, Atlas_Error_Invalid_Options);
- }
- if (options->mapper == Atlas_Mapper_LSCM) {
- // No options.
- }
- if (options->packer != Atlas_Packer_Witness) {
- return set_error(error, Atlas_Error_Invalid_Options);
- }
- if (options->packer == Atlas_Packer_Witness) {
- // @@ Validate input options!
- }
- // Validate input mesh.
- for (int i = 0; i < input->face_count; i++) {
- int v0 = input->face_array[i].vertex_index[0];
- int v1 = input->face_array[i].vertex_index[1];
- int v2 = input->face_array[i].vertex_index[2];
- if (v0 < 0 || v0 >= input->vertex_count ||
- v1 < 0 || v1 >= input->vertex_count ||
- v2 < 0 || v2 >= input->vertex_count)
- {
- return set_error(error, Atlas_Error_Invalid_Mesh);
- }
- }
- // Build half edge mesh.
- AutoPtr<HalfEdge::Mesh> mesh(new HalfEdge::Mesh);
- input_to_mesh(input, mesh.ptr(), error);
- if (*error == Atlas_Error_Invalid_Mesh) {
- return NULL;
- }
- Atlas atlas;
- // Charter.
- if (options->charter == Atlas_Charter_Extract) {
- return set_error(error, Atlas_Error_Not_Implemented);
- }
- else if (options->charter == Atlas_Charter_Witness) {
- SegmentationSettings segmentation_settings;
- segmentation_settings.proxyFitMetricWeight = options->charter_options.witness.proxy_fit_metric_weight;
- segmentation_settings.roundnessMetricWeight = options->charter_options.witness.roundness_metric_weight;
- segmentation_settings.straightnessMetricWeight = options->charter_options.witness.straightness_metric_weight;
- segmentation_settings.normalSeamMetricWeight = options->charter_options.witness.normal_seam_metric_weight;
- segmentation_settings.textureSeamMetricWeight = options->charter_options.witness.texture_seam_metric_weight;
- segmentation_settings.maxChartArea = options->charter_options.witness.max_chart_area;
- segmentation_settings.maxBoundaryLength = options->charter_options.witness.max_boundary_length;
- Array<uint> uncharted_materials;
- atlas.computeCharts(mesh.ptr(), segmentation_settings, uncharted_materials);
- }
- // Mapper.
- if (options->mapper == Atlas_Mapper_LSCM) {
- atlas.parameterizeCharts();
- }
- // Packer.
- if (options->packer == Atlas_Packer_Witness) {
- int packing_quality = options->packer_options.witness.packing_quality;
- float texel_area = options->packer_options.witness.texel_area;
- int block_align = options->packer_options.witness.block_align;
- int conservative = options->packer_options.witness.conservative;
- /*float utilization =*/ atlas.packCharts(packing_quality, texel_area, block_align, conservative);
- }
- // Build output mesh.
- return mesh_atlas_to_output(mesh.ptr(), atlas, error);
- }
- void Thekla::atlas_free(Atlas_Output_Mesh * output) {
- if (output != NULL) {
- delete [] output->vertex_array;
- delete [] output->index_array;
- delete output;
- }
- }
- // ATOMIC BEGIN
- struct ShaderData {
- int width;
- Vector3 objspace[3];
- float* floats;
- uint8_t* chartids;
- uint8_t chartid;
- unsigned char* data;
- unsigned char color[4];
- float fpcolor[4];
- };
- static bool pngAtlasCallback(
- void * param, int x, int y, Vector3::Arg tex,
- Vector3::Arg b, Vector3::Arg c, float area)
- {
- unsigned char* colors = ((ShaderData*) param)->data;
- Vector3* objspace = ((ShaderData*) param)->objspace;
- int width = ((ShaderData*) param)->width;
- int loc = x * 3 + y * 3 * width;
- Vector3 color = objspace[0] * tex.x +
- objspace[1] * tex.y +
- objspace[2] * tex.z;
- colors[loc++] = color.x * 255;
- colors[loc++] = color.y * 255;
- colors[loc++] = color.z * 255;
- return true;
- }
- static bool floatAtlasCallback(
- void * param, int x, int y, Vector3::Arg tex,
- Vector3::Arg b, Vector3::Arg c, float area)
- {
- float* floats = ((ShaderData*) param)->floats;
- Vector3* objspace = ((ShaderData*) param)->objspace;
- int width = ((ShaderData*) param)->width;
- int loc = x * 3 + y * 3 * width;
- Vector3 color = objspace[0] * tex.x +
- objspace[1] * tex.y +
- objspace[2] * tex.z;
- floats[loc++] = color.x;
- floats[loc++] = color.y;
- floats[loc++] = color.z;
- return true;
- }
- static bool pngSolidCallback(
- void * param, int x, int y, Vector3::Arg tex,
- Vector3::Arg b, Vector3::Arg c, float area)
- {
- unsigned char* colors = ((ShaderData*) param)->data;
- unsigned char* color = ((ShaderData*) param)->color;
- int width = ((ShaderData*) param)->width;
- int loc = x * 3 + y * 3 * width;
- colors[loc++] = color[0];
- colors[loc++] = color[1];
- colors[loc++] = color[2];
- return true;
- }
- static bool floatSolidCallback(
- void * param, int x, int y, Vector3::Arg tex,
- Vector3::Arg b, Vector3::Arg c, float area)
- {
- float* floats = ((ShaderData*) param)->floats;
- float* fpcolor = ((ShaderData*) param)->fpcolor;
- int width = ((ShaderData*) param)->width;
- int loc = x * 3 + y * 3 * width;
- floats[loc++] = fpcolor[0];
- floats[loc++] = fpcolor[1];
- floats[loc++] = fpcolor[2];
- return true;
- }
- static bool idSolidCallback(
- void * param, int x, int y, Vector3::Arg tex,
- Vector3::Arg b, Vector3::Arg c, float area)
- {
- uint8_t* ids = ((ShaderData*) param)->chartids;
- uint8_t id = ((ShaderData*) param)->chartid;
- int width = ((ShaderData*) param)->width;
- ids[x + y * width] = id;
- return true;
- }
- static Raster::Mode sRasterMode = Raster::Mode_Antialiased;
- void Thekla::atlas_write_debug_textures(const Atlas_Output_Mesh * atlas_mesh,
- const Atlas_Input_Mesh * obj_mesh,
- const char* worldSpaceTexturePath,
- const char* normalTexturePath,
- uint8_t** pchartids)
- {
- Vector3 minp(FLT_MAX);
- Vector3 maxp(FLT_MIN);
- for (int nvert = 0; nvert < atlas_mesh->vertex_count; nvert++) {
- const Atlas_Output_Vertex& overt = atlas_mesh->vertex_array[nvert];
- const Atlas_Input_Vertex& ivert = obj_mesh->vertex_array[overt.xref];
- minp.x = nv::min(ivert.position[0], minp.x);
- minp.y = nv::min(ivert.position[1], minp.y);
- minp.z = nv::min(ivert.position[2], minp.z);
- maxp.x = nv::max(ivert.position[0], maxp.x);
- maxp.y = nv::max(ivert.position[1], maxp.y);
- maxp.z = nv::max(ivert.position[2], maxp.z);
- }
- // Create an image representing the charts, with color representing the
- // approximate world-space position of each source vertex.
- int width = atlas_mesh->atlas_width;
- int height = atlas_mesh->atlas_height;
- const Vector2 extents(width, height);
- unsigned char* colors = (unsigned char*) calloc(width * height * 3, 1);
- uint8_t* chartids = pchartids ? (uint8_t*) calloc(width * height, 1) : 0;
- float* floats = (float*) calloc(width * height * sizeof(float) * 3, 1);
- const int* patlasIndex = atlas_mesh->index_array;
- Vector2 triverts[3];
- ShaderData shaderdata;
- shaderdata.width = width;
- shaderdata.data = colors;
- shaderdata.floats = floats;
- shaderdata.chartids = chartids;
- Vector3 objextent = maxp - minp;
- Vector3 offset = -minp;
- float objmextent = nv::max(nv::max(objextent.x, objextent.y), objextent.z);
- float scale = 1.0f / objmextent;
- for (int nface = 0; nface < atlas_mesh->index_count / 3; nface++) {
- Atlas_Output_Vertex& a = atlas_mesh->vertex_array[*patlasIndex++];
- Atlas_Output_Vertex& b = atlas_mesh->vertex_array[*patlasIndex++];
- Atlas_Output_Vertex& c = atlas_mesh->vertex_array[*patlasIndex++];
- Atlas_Input_Vertex& i = obj_mesh->vertex_array[a.xref];
- Atlas_Input_Vertex& j = obj_mesh->vertex_array[b.xref];
- Atlas_Input_Vertex& k = obj_mesh->vertex_array[c.xref];
- triverts[0].x = a.uv[0];
- triverts[0].y = a.uv[1];
- triverts[1].x = b.uv[0];
- triverts[1].y = b.uv[1];
- triverts[2].x = c.uv[0];
- triverts[2].y = c.uv[1];
- if (pchartids) {
- //shaderdata.chartid = a.chart_index + 1;
- //Raster::drawTriangle(sRasterMode, extents, true, triverts, idSolidCallback, &shaderdata);
- }
- shaderdata.objspace[0].x = (i.position[0] + offset.x) * scale;
- shaderdata.objspace[0].y = (i.position[1] + offset.y) * scale;
- shaderdata.objspace[0].z = (i.position[2] + offset.z) * scale;
- shaderdata.objspace[1].x = (j.position[0] + offset.x) * scale;
- shaderdata.objspace[1].y = (j.position[1] + offset.y) * scale;
- shaderdata.objspace[1].z = (j.position[2] + offset.z) * scale;
- shaderdata.objspace[2].x = (k.position[0] + offset.x) * scale;
- shaderdata.objspace[2].y = (k.position[1] + offset.y) * scale;
- shaderdata.objspace[2].z = (k.position[2] + offset.z) * scale;
- Raster::drawTriangle(sRasterMode, extents, true, triverts, pngAtlasCallback, &shaderdata);
- shaderdata.objspace[0].x = i.position[0];
- shaderdata.objspace[0].y = i.position[1];
- shaderdata.objspace[0].z = i.position[2];
- shaderdata.objspace[1].x = j.position[0];
- shaderdata.objspace[1].y = j.position[1];
- shaderdata.objspace[1].z = j.position[2];
- shaderdata.objspace[2].x = k.position[0];
- shaderdata.objspace[2].y = k.position[1];
- shaderdata.objspace[2].z = k.position[2];
- Raster::drawTriangle(sRasterMode, extents, true, triverts, floatAtlasCallback, &shaderdata);
- }
- stbi_write_png(worldSpaceTexturePath, width, height, 3, colors, 0);
- // Create an image representing facet normals.
- shaderdata.floats = floats = (float*) calloc(width * height * sizeof(float) * 3, 1);
- patlasIndex = atlas_mesh->index_array;
- for (int nface = 0; nface < atlas_mesh->index_count / 3; nface++) {
- Atlas_Output_Vertex& a = atlas_mesh->vertex_array[*patlasIndex++];
- Atlas_Output_Vertex& b = atlas_mesh->vertex_array[*patlasIndex++];
- Atlas_Output_Vertex& c = atlas_mesh->vertex_array[*patlasIndex++];
- Atlas_Input_Vertex& i = obj_mesh->vertex_array[a.xref];
- Atlas_Input_Vertex& j = obj_mesh->vertex_array[b.xref];
- Atlas_Input_Vertex& k = obj_mesh->vertex_array[c.xref];
- triverts[0].x = a.uv[0];
- triverts[0].y = a.uv[1];
- triverts[1].x = b.uv[0];
- triverts[1].y = b.uv[1];
- triverts[2].x = c.uv[0];
- triverts[2].y = c.uv[1];
- shaderdata.objspace[0].x = i.position[0];
- shaderdata.objspace[0].y = i.position[1];
- shaderdata.objspace[0].z = i.position[2];
- shaderdata.objspace[1].x = j.position[0];
- shaderdata.objspace[1].y = j.position[1];
- shaderdata.objspace[1].z = j.position[2];
- shaderdata.objspace[2].x = k.position[0];
- shaderdata.objspace[2].y = k.position[1];
- shaderdata.objspace[2].z = k.position[2];
- Vector3 A = shaderdata.objspace[1] - shaderdata.objspace[0];
- Vector3 B = shaderdata.objspace[2] - shaderdata.objspace[0];
- Vector3 N1 = normalize(cross(A, B));
- Vector3 N2 = 0.5f * (N1 + Vector3(1, 1, 1));
- shaderdata.color[0] = N2.x * 255;
- shaderdata.color[1] = N2.y * 255;
- shaderdata.color[2] = N2.z * 255;
- Raster::drawTriangle(sRasterMode, extents, true, triverts, pngSolidCallback, &shaderdata);
- shaderdata.fpcolor[0] = N1.x;
- shaderdata.fpcolor[1] = N1.y;
- shaderdata.fpcolor[2] = N1.z;
- Raster::drawTriangle(sRasterMode, extents, true, triverts, floatSolidCallback, &shaderdata);
- }
- stbi_write_png(normalTexturePath, width, height, 3, colors, 0);
- }
- void atlas_dump(
- const Atlas_Output_Mesh * atlas_mesh,
- const Atlas_Input_Mesh * obj_mesh,
- const char* oobjmesh,
- bool gbuffer,
- float** pcoordsdata,
- float** pnormsdata,
- uint8_t** pchartids,
- int size[2])
- {
- // Dump out the mutated mesh in simplified form and compute the AABB.
- printf("Writing %s...\n", oobjmesh);
- FILE* outobj = fopen(oobjmesh, "wt");
- float uscale = 1.f / atlas_mesh->atlas_width;
- float vscale = 1.f / atlas_mesh->atlas_height;
- Vector3 minp(FLT_MAX);
- Vector3 maxp(FLT_MIN);
- for (int nvert = 0; nvert < atlas_mesh->vertex_count; nvert++) {
- const Atlas_Output_Vertex& overt = atlas_mesh->vertex_array[nvert];
- const Atlas_Input_Vertex& ivert = obj_mesh->vertex_array[overt.xref];
- minp.x = nv::min(ivert.position[0], minp.x);
- minp.y = nv::min(ivert.position[1], minp.y);
- minp.z = nv::min(ivert.position[2], minp.z);
- maxp.x = nv::max(ivert.position[0], maxp.x);
- maxp.y = nv::max(ivert.position[1], maxp.y);
- maxp.z = nv::max(ivert.position[2], maxp.z);
- fprintf(outobj, "v %f %f %f\n", ivert.position[0], ivert.position[1], ivert.position[2]);
- fprintf(outobj, "vt %f %f\n", overt.uv[0] * uscale, 1 - overt.uv[1] * vscale);
- }
- for (int nface = 0; nface < atlas_mesh->index_count / 3; nface++) {
- int a = atlas_mesh->index_array[nface * 3] + 1;
- int b = atlas_mesh->index_array[nface * 3 + 1] + 1;
- int c = atlas_mesh->index_array[nface * 3 + 2] + 1;
- fprintf(outobj, "f %d/%d %d/%d %d/%d\n", a, a, b, b, c, c);
- }
- fclose(outobj);
- // Create an image representing the charts, with color representing the
- // approximate world-space position of each source vertex.
- int width = atlas_mesh->atlas_width;
- int height = atlas_mesh->atlas_height;
- const Vector2 extents(width, height);
- unsigned char* colors = (unsigned char*) calloc(width * height * 3, 1);
- uint8_t* chartids = pchartids ? (uint8_t*) calloc(width * height, 1) : 0;
- float* floats = (float*) calloc(width * height * sizeof(float) * 3, 1);
- const int* patlasIndex = atlas_mesh->index_array;
- Vector2 triverts[3];
- ShaderData shaderdata;
- shaderdata.width = width;
- shaderdata.data = colors;
- shaderdata.floats = floats;
- shaderdata.chartids = chartids;
- Vector3 objextent = maxp - minp;
- Vector3 offset = -minp;
- float objmextent = nv::max(nv::max(objextent.x, objextent.y), objextent.z);
- float scale = 1.0f / objmextent;
- for (int nface = 0; nface < atlas_mesh->index_count / 3; nface++) {
- Atlas_Output_Vertex& a = atlas_mesh->vertex_array[*patlasIndex++];
- Atlas_Output_Vertex& b = atlas_mesh->vertex_array[*patlasIndex++];
- Atlas_Output_Vertex& c = atlas_mesh->vertex_array[*patlasIndex++];
- Atlas_Input_Vertex& i = obj_mesh->vertex_array[a.xref];
- Atlas_Input_Vertex& j = obj_mesh->vertex_array[b.xref];
- Atlas_Input_Vertex& k = obj_mesh->vertex_array[c.xref];
- triverts[0].x = a.uv[0];
- triverts[0].y = a.uv[1];
- triverts[1].x = b.uv[0];
- triverts[1].y = b.uv[1];
- triverts[2].x = c.uv[0];
- triverts[2].y = c.uv[1];
- if (pchartids) {
- //shaderdata.chartid = a.chart_index + 1;
- //Raster::drawTriangle(sRasterMode, extents, true, triverts, idSolidCallback, &shaderdata);
- }
- shaderdata.objspace[0].x = (i.position[0] + offset.x) * scale;
- shaderdata.objspace[0].y = (i.position[1] + offset.y) * scale;
- shaderdata.objspace[0].z = (i.position[2] + offset.z) * scale;
- shaderdata.objspace[1].x = (j.position[0] + offset.x) * scale;
- shaderdata.objspace[1].y = (j.position[1] + offset.y) * scale;
- shaderdata.objspace[1].z = (j.position[2] + offset.z) * scale;
- shaderdata.objspace[2].x = (k.position[0] + offset.x) * scale;
- shaderdata.objspace[2].y = (k.position[1] + offset.y) * scale;
- shaderdata.objspace[2].z = (k.position[2] + offset.z) * scale;
- Raster::drawTriangle(sRasterMode, extents, true, triverts, pngAtlasCallback, &shaderdata);
- shaderdata.objspace[0].x = i.position[0];
- shaderdata.objspace[0].y = i.position[1];
- shaderdata.objspace[0].z = i.position[2];
- shaderdata.objspace[1].x = j.position[0];
- shaderdata.objspace[1].y = j.position[1];
- shaderdata.objspace[1].z = j.position[2];
- shaderdata.objspace[2].x = k.position[0];
- shaderdata.objspace[2].y = k.position[1];
- shaderdata.objspace[2].z = k.position[2];
- Raster::drawTriangle(sRasterMode, extents, true, triverts, floatAtlasCallback, &shaderdata);
- }
- if (gbuffer) {
- printf("Writing object_coords.png...\n");
- stbi_write_png("object_coords.png", width, height, 3, colors, 0);
- }
- *pcoordsdata = floats;
- // Create an image representing facet normals.
- shaderdata.floats = floats = (float*) calloc(width * height * sizeof(float) * 3, 1);
- patlasIndex = atlas_mesh->index_array;
- for (int nface = 0; nface < atlas_mesh->index_count / 3; nface++) {
- Atlas_Output_Vertex& a = atlas_mesh->vertex_array[*patlasIndex++];
- Atlas_Output_Vertex& b = atlas_mesh->vertex_array[*patlasIndex++];
- Atlas_Output_Vertex& c = atlas_mesh->vertex_array[*patlasIndex++];
- Atlas_Input_Vertex& i = obj_mesh->vertex_array[a.xref];
- Atlas_Input_Vertex& j = obj_mesh->vertex_array[b.xref];
- Atlas_Input_Vertex& k = obj_mesh->vertex_array[c.xref];
- triverts[0].x = a.uv[0];
- triverts[0].y = a.uv[1];
- triverts[1].x = b.uv[0];
- triverts[1].y = b.uv[1];
- triverts[2].x = c.uv[0];
- triverts[2].y = c.uv[1];
- shaderdata.objspace[0].x = i.position[0];
- shaderdata.objspace[0].y = i.position[1];
- shaderdata.objspace[0].z = i.position[2];
- shaderdata.objspace[1].x = j.position[0];
- shaderdata.objspace[1].y = j.position[1];
- shaderdata.objspace[1].z = j.position[2];
- shaderdata.objspace[2].x = k.position[0];
- shaderdata.objspace[2].y = k.position[1];
- shaderdata.objspace[2].z = k.position[2];
- Vector3 A = shaderdata.objspace[1] - shaderdata.objspace[0];
- Vector3 B = shaderdata.objspace[2] - shaderdata.objspace[0];
- Vector3 N1 = normalize(cross(A, B));
- Vector3 N2 = 0.5f * (N1 + Vector3(1, 1, 1));
- shaderdata.color[0] = N2.x * 255;
- shaderdata.color[1] = N2.y * 255;
- shaderdata.color[2] = N2.z * 255;
- Raster::drawTriangle(sRasterMode, extents, true, triverts, pngSolidCallback, &shaderdata);
- shaderdata.fpcolor[0] = N1.x;
- shaderdata.fpcolor[1] = N1.y;
- shaderdata.fpcolor[2] = N1.z;
- Raster::drawTriangle(sRasterMode, extents, true, triverts, floatSolidCallback, &shaderdata);
- }
- if (gbuffer) {
- printf("Writing facet_normals.png...\n");
- stbi_write_png("facet_normals.png", width, height, 3, colors, 0);
- }
- size[0] = width;
- size[1] = height;
- *pnormsdata = floats;
- if (pchartids) {
- *pchartids = chartids;
- }
- free(colors);
- }
- // ATOMIC END
|