diff --git a/projects/MeshSubdiv/OSDPrimSubdiv.cpp b/projects/MeshSubdiv/OSDPrimSubdiv.cpp index d0eb47c08f..1a4f88268d 100644 --- a/projects/MeshSubdiv/OSDPrimSubdiv.cpp +++ b/projects/MeshSubdiv/OSDPrimSubdiv.cpp @@ -132,7 +132,7 @@ static void osdPrimSubdiv(PrimitiveObject *prim, int levels, std::string edgeCre const int maxlevel=levels; if (maxlevel <= 0 || !prim->verts.size()) return; - if (prim->loops.size() && prim->loop_uvs.size() <= prim->loops.size()) + if (prim->loops.size() && prim->loop_uvs.size()) hasLoopUVs = false; //nCoarseVerts=0, diff --git a/zeno/include/zeno/types/PrimitiveObject.h b/zeno/include/zeno/types/PrimitiveObject.h index 5bbacc8ff5..b982ebc12a 100644 --- a/zeno/include/zeno/types/PrimitiveObject.h +++ b/zeno/include/zeno/types/PrimitiveObject.h @@ -27,8 +27,8 @@ struct PrimitiveObject : IObjectClone { AttrVector polys; AttrVector edges; - std::vector uvs; - std::vector loop_uvs; + AttrVector uvs; + AttrVector loop_uvs; std::shared_ptr mtl; std::shared_ptr inst; diff --git a/zeno/src/funcs/ObjectCodecPrimitive.cpp b/zeno/src/funcs/ObjectCodecPrimitive.cpp index e8049d9615..bd10affdd2 100644 --- a/zeno/src/funcs/ObjectCodecPrimitive.cpp +++ b/zeno/src/funcs/ObjectCodecPrimitive.cpp @@ -82,7 +82,9 @@ std::shared_ptr decodePrimitiveObject(const char *it) { decodeAttrVector(obj->quads, it); decodeAttrVector(obj->loops, it); decodeAttrVector(obj->polys, it); + decodeAttrVector(obj->edges, it); decodeAttrVector(obj->uvs, it); + decodeAttrVector(obj->loop_uvs, it); if (*it++ == '1') { obj->mtl = std::make_shared(); obj->mtl->deserialize(it); @@ -99,7 +101,9 @@ bool encodePrimitiveObject(PrimitiveObject const *obj, std::back_insert_iterator encodeAttrVector(obj->quads, it); encodeAttrVector(obj->loops, it); encodeAttrVector(obj->polys, it); + encodeAttrVector(obj->edges, it); encodeAttrVector(obj->uvs, it); + encodeAttrVector(obj->loop_uvs, it); if (obj->mtl) { *it++ = '1'; for (char c: obj->mtl->serialize()) diff --git a/zeno/src/nodes/neo/PrimCodecUVs.cpp b/zeno/src/nodes/neo/PrimCodecUVs.cpp index e836b9e374..01a142d83c 100644 --- a/zeno/src/nodes/neo/PrimCodecUVs.cpp +++ b/zeno/src/nodes/neo/PrimCodecUVs.cpp @@ -8,13 +8,13 @@ namespace zeno { // 'smart loop_uvs' to 'qianqiang loop.attr(uv)' ZENO_API void primDecodeUVs(PrimitiveObject *prim) { - if (prim->loops.size() && prim->loop_uvs.size() <= prim->loops.size()) { + if (prim->loops.size() && prim->loop_uvs.size()) { auto &loop_uvs = prim->loop_uvs; auto &attr_uv = prim->loops.add_attr("uv"); // todo: support vec2f in attr... /*attr_uv.resize(prim->loop_uvs.size());*/ size_t n = std::min(loop_uvs.size(), attr_uv.size()); if (n == 0) zeno::log_warn("primDecodeUVs: no loops but have loop_uvs"); - if (prim->uvs.size() == 0) zeno::log_error("primDecodeUVs: no uvs but have loop_uvs"); + else if (prim->uvs.size() == 0) zeno::log_error("primDecodeUVs: no uvs but have loop_uvs"); parallel_for(n, [&] (size_t i) { auto uv = prim->uvs[loop_uvs[i]]; attr_uv[i] = {uv[0], uv[1], 0}; @@ -27,7 +27,7 @@ ZENO_API void primDecodeUVs(PrimitiveObject *prim) { // 'smart loop_uvs' to 'veryqianqiang vert.attr(uv)' ZENO_API void primLoopUVsToVerts(PrimitiveObject *prim) { - if (prim->loops.size() && prim->loop_uvs.size() <= prim->loops.size()) { + if (prim->loops.size() && prim->loop_uvs.size()) { auto &loop_uvs = prim->loop_uvs; auto &vert_uv = prim->verts.add_attr("uv"); // todo: support vec2f in attr... /*attr_uv.resize(prim->loop_uvs.size());*/ diff --git a/zeno/src/nodes/neo/PrimExtrude.cpp b/zeno/src/nodes/neo/PrimExtrude.cpp index 3cd8121482..5509096f8c 100644 --- a/zeno/src/nodes/neo/PrimExtrude.cpp +++ b/zeno/src/nodes/neo/PrimExtrude.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include namespace zeno { @@ -24,9 +25,12 @@ struct PrimExtrude : INode { auto sourceMaskAttrO = get_input2("sourceMaskAttrO"); auto autoFlipFace = get_input2("autoFlipFace"); auto autoFindEdges = get_input2("autoFindEdges"); + auto averagedExtrude = get_input2("averagedExtrude"); auto prim2 = std::make_shared(*prim); + bool flipNewFace = autoFlipFace && extrude < 0; + bool flipOldFace = autoFlipFace && extrude > 0; if (autoFindEdges && !maskAttr.empty()) { AttrVector oldlines = std::move(prim2->lines); primWireframe(prim2.get(), false); @@ -64,6 +68,13 @@ struct PrimExtrude : INode { std::string tmpNormAttr = "%%extrude2"; primCalcNormal(prim2.get(), 1.0f, tmpNormAttr); p2norms = std::move(prim2->verts.attr(tmpNormAttr)); + if (averagedExtrude) { + auto avgdir = std::reduce(p2norms.begin(), p2norms.end(), vec3f(0)); + avgdir = normalizeSafe(avgdir); + offset += extrude * avgdir; + extrude = 0; + p2norms.clear(); + } prim2->verts.erase_attr(tmpNormAttr); } @@ -76,8 +87,6 @@ struct PrimExtrude : INode { //prim2->verts.erase_attr(tmpInsetAttr); } - bool flipNewFace = autoFlipFace && extrude < 0; - bool flipOldFace = autoFlipFace && extrude > 0; if (flipNewFace) { primFlipFaces(prim2.get()); } @@ -202,6 +211,7 @@ ZENDEFNODE(PrimExtrude, { {"string", "sourceMaskAttrO", ""}, {"bool", "autoFlipFace", "1"}, {"bool", "autoFindEdges", "1"}, + {"bool", "averagedExtrude", "0"}, }, { {"PrimitiveObject", "prim"}, diff --git a/zeno/src/nodes/neo/PrimSepTris.cpp b/zeno/src/nodes/neo/PrimSepTris.cpp index 4f1acc2f70..c311a94ee7 100644 --- a/zeno/src/nodes/neo/PrimSepTris.cpp +++ b/zeno/src/nodes/neo/PrimSepTris.cpp @@ -135,7 +135,7 @@ ZENO_API void primSepTriangles(PrimitiveObject *prim, bool smoothNormal, bool ke new_uv[b + i * 6 + 5] = uv3[i]; } } - if (prim->loops.size() && prim->loop_uvs.size() <= prim->loops.size()) { + if (prim->loops.size() && prim->loop_uvs.size()) { auto &loop_uvs = prim->loop_uvs; size_t b = 0; std::vector v(loopcount * 3); diff --git a/zeno/src/nodes/neo/WriteObjPrim.cpp b/zeno/src/nodes/neo/WriteObjPrim.cpp index ed78233091..251cfa8012 100644 --- a/zeno/src/nodes/neo/WriteObjPrim.cpp +++ b/zeno/src/nodes/neo/WriteObjPrim.cpp @@ -22,7 +22,7 @@ void dump_obj(PrimitiveObject *prim, std::ostream &fout) { for (auto const &[x, y, z]: prim->verts) { fout << "v " << x << ' ' << y << ' ' << z << '\n'; } - if (prim->loops.size() && prim->loop_uvs.size() <= prim->loops.size()) { + if (prim->loops.size() && prim->loop_uvs.size()) { auto &loop_uvs = prim->loop_uvs; for (auto const &[x, y]: prim->uvs) { fout << "vt " << x << ' ' << y << '\n'; diff --git a/zenovis/src/bate/GraphicPrimitive.cpp b/zenovis/src/bate/GraphicPrimitive.cpp index 59c144901a..e96c14d813 100644 --- a/zenovis/src/bate/GraphicPrimitive.cpp +++ b/zenovis/src/bate/GraphicPrimitive.cpp @@ -335,7 +335,7 @@ struct ZhxxGraphicPrimitive final : IGraphicDraw { } if (thePrmHasFaces) { zeno::log_trace("demoting faces"); - if (prim->loops.size() && prim->loop_uvs.size() <= prim->loops.size()) { + if (prim->loops.size() && prim->loop_uvs.size()) { zeno::primDecodeUVs(&*prim);//loop_uvs to loop.attr("uv") } zeno::primTriangulateQuads(&*prim);