【ZENO】Primitive Triangulate----Quads-to-Tris--Poly&Loops-to-Tris

PrimitiveTriangulate.cpp

#include <zeno/zeno.h>
#include <zeno/types/PrimitiveObject.h>
#include <zeno/funcs/PrimitiveUtils.h>
#include <zeno/para/parallel_for.h>
#include <zeno/para/parallel_scan.h>
#include <zeno/utils/variantswitch.h>

namespace zeno {

ZENO_API void primTriangulateQuads(PrimitiveObject *prim) {
    auto base = prim->tris.size();
    prim->tris.resize(base + prim->quads.size() * 2);

    for (size_t i = 0; i < prim->quads.size(); i++) {
        auto quad = prim->quads[i];
        prim->tris[base+i*2+0] = vec3f(quad[0], quad[1], quad[2]);
        prim->tris[base+i*2+1] = vec3f(quad[0], quad[2], quad[3]);
    }
    prim->quads.clear();
}

ZENO_API void primTriangulate(PrimitiveObject *prim, bool with_uv, bool has_lines) {
    //prim->tris.reserve(prim->tris.size() + prim->polys.size());

  boolean_switch(has_lines, [&] (auto has_lines) {
    std::vector<std::conditional_t<has_lines.value, vec2i, int>> scansum(prim->polys.size());
    auto redsum = parallel_exclusive_scan_sum(prim->polys.begin(), prim->polys.end(),
                                           scansum.begin(), [&] (auto &ind) {
                                               if constexpr (has_lines.value) {
                                                   return vec2i(ind[1] >= 3 ? ind[1] - 2 : 0, ind[1] == 2 ? 1 : 0);
                                               } else {
                                                   return ind[1] >= 3 ? ind[1] - 2 : 0;
                                               }
                                           });
    int tribase = prim->tris.size();
    int linebase = prim->lines.size();
    if constexpr (has_lines.value) {
        prim->tris.resize(tribase + redsum[0]);
        prim->lines.resize(linebase + redsum[1]);
    } else {
        prim->tris.resize(tribase + redsum);
    }

    if (!(prim->loop_uvs.size() && with_uv)) {
        parallel_for(prim->polys.size(), [&] (size_t i) {
            auto [start, len] = prim->polys[i];
            if (len >= 3) {
                int scanbase;
                if constexpr (has_lines.value) {
                    scanbase = scansum[i][0] + tribase;
                } else {
                    scanbase = scansum[i] + tribase;
                }
                prim->tris[scanbase++] = vec3f(
                    prim->loops[start],
                    prim->loops[start + 1],
                    prim->loops[start + 2]);
                for (int j = 3; j < len; j++) {
                    prim->tris[scanbase++] = vec3f(
                        prim->loops[start],
                        prim->loops[start + j - 1],
                        prim->loops[start + j]);
                }
            }
            if constexpr (has_lines.value) {
                if (len == 2) {
                    int scanbase = scansum[i][1] + linebase;
                    prim->lines[scanbase] = vec2f(
                        prim->loops[start],
                        prim->loops[start + 1]);
                }
            }
        });

    } else {
        auto &loop_uv = prim->loop_uvs;
        auto &uvs = prim->uvs;
        auto &uv0 = prim->tris.add_attr<vec3f>("uv0");
        auto &uv1 = prim->tris.add_attr<vec3f>("uv1");
        auto &uv2 = prim->tris.add_attr<vec3f>("uv2");

        parallel_for(prim->polys.size(), [&] (size_t i) {
            auto [start, len] = prim->polys[i];
            if (len >= 3) {
                int scanbase;
                if constexpr (has_lines.value) {
                    scanbase = scansum[i][0] + tribase;
                } else {
                    scanbase = scansum[i] + tribase;
                }
                uv0[scanbase] = {uvs[loop_uv[start]][0], uvs[loop_uv[start]][1], 0};
                uv1[scanbase] = {uvs[loop_uv[start + 1]][0], uvs[loop_uv[start + 1]][1], 0};
                uv2[scanbase] = {uvs[loop_uv[start + 2]][0], uvs[loop_uv[start + 2]][1], 0};
                prim->tris[scanbase++] = vec3f(
                        prim->loops[start],
                        prim->loops[start + 1],
                        prim->loops[start + 2]);
                for (int j = 3; j < len; j++) {
                    uv0[scanbase] = {uvs[loop_uv[start]][0], uvs[loop_uv[start]][1], 0};
                    uv1[scanbase] = {uvs[loop_uv[start + j - 1]][0], uvs[loop_uv[start + j - 1]][1], 0};
                    uv2[scanbase] = {uvs[loop_uv[start + j]][0], uvs[loop_uv[start + j]][1], 0};
                    prim->tris[scanbase++] = vec3f(
                            prim->loops[start],
                            prim->loops[start + j - 1],
                            prim->loops[start + j]);
                }
            }
            if constexpr (has_lines.value) {
                if (len == 2) {
                    int scanbase = scansum[i][1] + linebase;
                    prim->lines[scanbase] = vec2f(
                        prim->loops[start],
                        prim->loops[start + 1]);
                }
            }
        });

    }
    prim->loops.clear();
    prim->polys.clear();
    prim->loop_uvs.clear();
    prim->uvs.clear();
  });
}

namespace {

struct PrimitiveTriangulate : INode {
    virtual void apply() override {
        auto prim = get_input<PrimitiveObject>("prim");
        if (get_param<bool>("from_poly")) {
            primTriangulate(prim.get(), get_param<bool>("with_uv"), get_param<bool>("has_lines"));
        }
        if (get_param<bool>("from_quads")) {
            primTriangulateQuads(prim.get());
        }
        set_output("prim", std::move(prim));
    }
};

ZENDEFNODE(PrimitiveTriangulate,
        { /* inputs: */ {
        {"primitive", "prim"},
        }, /* outputs: */ {
        {"primitive", "prim"},
        }, /* params: */ {
        {"bool", "from_poly", "1"},
        {"bool", "with_uv", "1"},
        {"bool", "from_quads", "1"},
        {"bool", "has_lines", "1"},
        }, /* category: */ {
        "primitive",
        }});

}
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值