diff --git a/projects/CalcGeometryUV/PrimitivePlyIO.cpp b/projects/CalcGeometryUV/PrimitivePlyIO.cpp index 26c94a90cf..08d3427b38 100644 --- a/projects/CalcGeometryUV/PrimitivePlyIO.cpp +++ b/projects/CalcGeometryUV/PrimitivePlyIO.cpp @@ -18,6 +18,7 @@ static void readply( std::vector &verts, + std::vector &color, std::vector &zfaces, const std::string & filepath ) { @@ -36,11 +37,20 @@ static void readply( tinyply::PlyFile file; file.parse_header(*file_stream); - std::shared_ptr vertices, faces; + std::shared_ptr vertices, r,g,b, faces; try { vertices = file.request_properties_from_element("vertex", { "x", "y", "z" }); } catch (const std::exception & e) { std::cerr << "tinyply exception: " << e.what() << std::endl; } + try { r = file.request_properties_from_element("vertex", {"red"}); } + catch (const std::exception & e) { std::cerr << "tinyply exception: " << e.what() << std::endl; } + + try { g = file.request_properties_from_element("vertex", {"green"}); } + catch (const std::exception & e) { std::cerr << "tinyply exception: " << e.what() << std::endl; } + + try { b = file.request_properties_from_element("vertex", {"blue"}); } + catch (const std::exception & e) { std::cerr << "tinyply exception: " << e.what() << std::endl; } + try { faces = file.request_properties_from_element("face", { "vertex_indices" }, 3); } catch (const std::exception & e) { std::cerr << "tinyply exception: " << e.what() << std::endl; } @@ -59,6 +69,30 @@ static void readply( verts.emplace_back(v[0], v[1], v[2]); } } + + if(r->count>0) + { + color.resize(verts.size()); + if(r->t == tinyply::Type::UINT8 || r->t == tinyply::Type::INT8) + { + std::vector rr; + std::vector gg; + std::vector bb; + rr.resize(r->count); + gg.resize(g->count); + bb.resize(b->count); + std::memcpy(rr.data(), r->buffer.get(), r->count ); + std::memcpy(gg.data(), g->buffer.get(), g->count ); + std::memcpy(bb.data(), b->buffer.get(), b->count ); + + for(size_t i=0;ibuffer.size_bytes(); if (faces->t == tinyply::Type::INT32 || faces->t == tinyply::Type::UINT32) { zfaces.resize(faces->count); @@ -89,8 +123,9 @@ struct ReadPlyPrimitive : zeno::INode { auto path = get_input("path")->get(); auto prim = std::make_shared(); auto &pos = prim->verts; + auto &clr = prim->add_attr("clr"); auto &tris = prim->tris; - readply(pos, tris, path); + readply(pos, clr, tris, path); prim->resize(pos.size()); set_output("prim", std::move(prim)); } diff --git a/zeno/src/nodes/neo/PrimUnmerge.cpp b/zeno/src/nodes/neo/PrimUnmerge.cpp index 1f547ef195..8d906dc216 100644 --- a/zeno/src/nodes/neo/PrimUnmerge.cpp +++ b/zeno/src/nodes/neo/PrimUnmerge.cpp @@ -352,5 +352,286 @@ ZENDEFNODE(PrimUnmerge, { {"primitive"}, }); +void cleanMesh(std::shared_ptr prim, + std::vector &verts, + std::vector &nrm, + std::vector &clr, + std::vector &tang, + std::vector &uv, + std::vector &idxBuffer) +{ + //first pass, scan the prim to see if verts require duplication + std::vector> vert_uv; + std::vector> idx_mapping; + vert_uv.resize(prim->verts.size()); + idx_mapping.resize(prim->verts.size()); + int count = 0; + for(int i=0;itris.size();i++) + { + //so far, all value has already averaged on verts, except uv + zeno::vec3i idx = prim->tris[i]; + for(int j=0;j<3;j++) + { + std::string uv_name; + uv_name = "uv" + std::to_string(j); + auto vid = idx[j]; + if(vert_uv[vid].size()==0) + { + vert_uv[vid].push_back(prim->tris.attr(uv_name)[i]); + //idx_mapping[vid].push_back(zeno::vec2i(vid,count)); + //count++; + } + else + { + zeno::vec3f uv = prim->tris.attr(uv_name)[i]; + bool have = false; + for(int k=0;ktris.attr(uv_name)[i]); + //idx_mapping[vid].push_back(zeno::vec2i(vid,count)); + //count++; + } + } + } + } + count = 0; + for(int i=0;iverts[vid]; + auto n = prim->verts.attr("nrm")[vid]; + auto c = prim->verts.attr("clr")[vid]; + auto t = prim->verts.attr("atang")[vid]; + verts.push_back(v); + nrm.push_back(n); + clr.push_back(c); + tang.push_back(t); + uv.push_back(uvt); + } + } + + idxBuffer.resize(prim->tris.size()); + //third pass: assemble new idx map + for(int i=0;itris.size();i++) + { + zeno::vec3i idx = prim->tris[i]; + for(int j=0;j<3;j++) { + + auto old_vid = idx[j]; + if(idx_mapping[old_vid].size()==1) + { + idxBuffer[i][j] = idx_mapping[old_vid][0][1]; + } + else + { + std::string uv_name = "uv" + std::to_string(j); + auto &tuv = prim->tris.attr(uv_name)[i]; + for(int k=0;kadd_attr("atang"); + auto &tang = prim->tris.attr("tang"); + atang.assign(atang.size(), zeno::vec3f(0)); + const auto &pos = prim->attr("pos"); + for(size_t i=0;itris.size();++i) + { + + auto vidx = prim->tris[i]; + zeno::vec3f v0 = pos[vidx[0]]; + zeno::vec3f v1 = pos[vidx[1]]; + zeno::vec3f v2 = pos[vidx[2]]; + auto e1 = v1-v0, e2=v2-v0; + float area = zeno::length(zeno::cross(e1, e2)) * 0.5; + atang[vidx[0]] += area * tang[i]; + atang[vidx[1]] += area * tang[i]; + atang[vidx[2]] += area * tang[i]; + } +#pragma omp parallel for + for(auto i=0;itris; + const auto &pos = prim->attr("pos"); + auto const &nrm = prim->add_attr("nrm"); + auto &tang = prim->tris.add_attr("tang"); + bool has_uv = tris.has_attr("uv0")&&tris.has_attr("uv1")&&tris.has_attr("uv2"); + //printf("!!has_uv = %d\n", has_uv); + if(has_uv) { + const auto &uv0data = tris.attr("uv0"); + const auto &uv1data = tris.attr("uv1"); + const auto &uv2data = tris.attr("uv2"); +#pragma omp parallel for + for (auto i = 0; i < prim->tris.size(); ++i) { + const auto &pos0 = pos[tris[i][0]]; + const auto &pos1 = pos[tris[i][1]]; + const auto &pos2 = pos[tris[i][2]]; + zeno::vec3f uv0; + zeno::vec3f uv1; + zeno::vec3f uv2; + + uv0 = uv0data[i]; + uv1 = uv1data[i]; + uv2 = uv2data[i]; + + auto edge0 = pos1 - pos0; + auto edge1 = pos2 - pos0; + auto deltaUV0 = uv1 - uv0; + auto deltaUV1 = uv2 - uv0; + + auto f = 1.0f / (deltaUV0[0] * deltaUV1[1] - deltaUV1[0] * deltaUV0[1] + 1e-5); + + zeno::vec3f tangent; + tangent[0] = f * (deltaUV1[1] * edge0[0] - deltaUV0[1] * edge1[0]); + tangent[1] = f * (deltaUV1[1] * edge0[1] - deltaUV0[1] * edge1[1]); + tangent[2] = f * (deltaUV1[1] * edge0[2] - deltaUV0[1] * edge1[2]); + //printf("tangent:%f %f %f\n", tangent[0], tangent[1], tangent[2]); + //zeno::log_info("tangent {} {} {}",tangent[0], tangent[1], tangent[2]); + auto tanlen = zeno::length(tangent); + tangent *(1.f / (tanlen + 1e-8)); + /*if (std::abs(tanlen) < 1e-8) {//fix by BATE + zeno::vec3f n = nrm[tris[i][0]], unused; + zeno::pixarONB(n, tang[i], unused);//TODO calc this in shader? + } else { + tang[i] = tangent * (1.f / tanlen); + }*/ + tang[i] = tangent; + } + } else { + const auto &uvarray = prim->attr("uv"); +#pragma omp parallel for + for (auto i = 0; i < prim->tris.size(); ++i) { + const auto &pos0 = pos[tris[i][0]]; + const auto &pos1 = pos[tris[i][1]]; + const auto &pos2 = pos[tris[i][2]]; + zeno::vec3f uv0; + zeno::vec3f uv1; + zeno::vec3f uv2; + + uv0 = uvarray[tris[i][0]]; + uv1 = uvarray[tris[i][1]]; + uv2 = uvarray[tris[i][2]]; + + auto edge0 = pos1 - pos0; + auto edge1 = pos2 - pos0; + auto deltaUV0 = uv1 - uv0; + auto deltaUV1 = uv2 - uv0; + + auto f = 1.0f / (deltaUV0[0] * deltaUV1[1] - deltaUV1[0] * deltaUV0[1] + 1e-5); + + zeno::vec3f tangent; + tangent[0] = f * (deltaUV1[1] * edge0[0] - deltaUV0[1] * edge1[0]); + tangent[1] = f * (deltaUV1[1] * edge0[1] - deltaUV0[1] * edge1[1]); + tangent[2] = f * (deltaUV1[1] * edge0[2] - deltaUV0[1] * edge1[2]); + //printf("tangent:%f %f %f\n", tangent[0], tangent[1], tangent[2]); + //zeno::log_info("tangent {} {} {}",tangent[0], tangent[1], tangent[2]); + auto tanlen = zeno::length(tangent); + tangent *(1.f / (tanlen + 1e-8)); + /*if (std::abs(tanlen) < 1e-8) {//fix by BATE + zeno::vec3f n = nrm[tris[i][0]], unused; + zeno::pixarONB(n, tang[i], unused);//TODO calc this in shader? + } else { + tang[i] = tangent * (1.f / tanlen); + }*/ + tang[i] = tangent; + } + } +} +struct primClean : INode { + virtual void apply() override { + auto prim = get_input("prim"); + std::vector verts; + std::vector nrm; + std::vector clr; + std::vector tang; + std::vector uv; + std::vector idxBuffer; + computeTrianglesTangent(prim.get()); + computeVertexTangent(prim.get()); + cleanMesh(prim, verts, nrm, clr, tang, uv, idxBuffer); + auto oPrim = std::make_shared(); + oPrim->verts.resize(verts.size()); + oPrim->add_attr("nrm"); + oPrim->add_attr("clr"); + oPrim->add_attr("uv"); + oPrim->add_attr("atang"); + oPrim->tris.resize(idxBuffer.size()); + + + oPrim->verts.attr("pos") = verts; + oPrim->verts.attr("nrm") = nrm; + oPrim->verts.attr("clr") = clr; + oPrim->verts.attr("uv") = uv; + oPrim->verts.attr("atang") = tang; + + + oPrim->tris = idxBuffer; + + + set_output("prim", std::move(oPrim)); + } +}; + +ZENDEFNODE(primClean, { + { + {"primitive", "prim"} + }, + { + {"primitive", "prim"}, + }, + { + }, + {"primitive"}, + }); + + } } diff --git a/zenovis/src/optx/RenderEngineOptx.cpp b/zenovis/src/optx/RenderEngineOptx.cpp index a511fb76d1..5effeb93ac 100644 --- a/zenovis/src/optx/RenderEngineOptx.cpp +++ b/zenovis/src/optx/RenderEngineOptx.cpp @@ -66,7 +66,125 @@ struct CppTimer { }; static CppTimer timer, localTimer; - +void cleanMesh(std::shared_ptr prim, + std::vector &verts, + std::vector &nrm, + std::vector &clr, + std::vector &tang, + std::vector &uv, + std::vector &idxBuffer) +{ + //first pass, scan the prim to see if verts require duplication + std::vector> vert_uv; + std::vector> idx_mapping; + vert_uv.resize(prim->verts.size()); + idx_mapping.resize(prim->verts.size()); + int count = 0; + for(int i=0;itris.size();i++) + { + //so far, all value has already averaged on verts, except uv + zeno::vec3i idx = prim->tris[i]; + for(int j=0;j<3;j++) + { + std::string uv_name; + uv_name = "uv" + std::to_string(j); + auto vid = idx[j]; + if(vert_uv[vid].size()==0) + { + vert_uv[vid].push_back(prim->tris.attr(uv_name)[i]); + //idx_mapping[vid].push_back(zeno::vec2i(vid,count)); + //count++; + } + else + { + zeno::vec3f uv = prim->tris.attr(uv_name)[i]; + bool have = false; + for(int k=0;ktris.attr(uv_name)[i]); + //idx_mapping[vid].push_back(zeno::vec2i(vid,count)); + //count++; + } + } + } + } + count = 0; + for(int i=0;iverts[vid]; + auto n = prim->verts.attr("nrm")[vid]; + auto c = prim->verts.attr("clr")[vid]; + auto t = prim->verts.attr("atang")[vid]; + verts.push_back(v); + nrm.push_back(n); + clr.push_back(c); + tang.push_back(t); + uv.push_back(uvt); + } + } + + idxBuffer.resize(prim->tris.size()); + //third pass: assemble new idx map + for(int i=0;itris.size();i++) + { + zeno::vec3i idx = prim->tris[i]; + for(int j=0;j<3;j++) { + + auto old_vid = idx[j]; + if(idx_mapping[old_vid].size()==1) + { + idxBuffer[i][j] = idx_mapping[old_vid][0][1]; + } + else + { + std::string uv_name = "uv" + std::to_string(j); + auto &tuv = prim->tris.attr(uv_name)[i]; + for(int k=0;k