【开发日志】2022.10.07 ZENO No More Quads

 SimpleGeometry.cpp

#include <zeno/zeno.h>
#include <zeno/types/PrimitiveObject.h>
#include <zeno/types/DictObject.h>
#include <zeno/types/StringObject.h>
#include <zeno/types/PrimitiveTools.h>
#include <zeno/types/NumericObject.h>
#include <zeno/types/UserData.h>
#include <zeno/utils/string.h>
#include <zeno/utils/logger.h>
#include <zeno/utils/vec.h>
#include <cmath>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
//#include <spdlog/spdlog.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>

#define ROTATE_COMPUTE                          \
    auto gp = glm::vec3(p[0], p[1], p[2]);      \
    gp = mz * my * mx * gp;                     \
    p = zeno::vec3f(gp.x, gp.y, gp.z);

#define ROTATE_PARM                             \
    {"vec3f", "rotate", "0, 0, 0"},

#define ROTATE_MATRIX                           \
    auto rotate = get_input2<zeno::vec3f>("rotate"); \
    float ax = rotate[0] * (M_PI / 180.0);      \
    float ay = rotate[1] * (M_PI / 180.0);      \
    float az = rotate[2] * (M_PI / 180.0);      \
    glm::mat3 mx = glm::mat3(                   \
        1, 0, 0,                                \
        0, cos(ax), -sin(ax),                   \
        0, sin(ax), cos(ax));                   \
    glm::mat3 my = glm::mat3(                   \
        cos(ay), 0, sin(ay),                    \
        0, 1, 0,                                \
        -sin(ay), 0, cos(ay));                  \
    glm::mat3 mz = glm::mat3(                   \
        cos(az), -sin(az), 0,                   \
        sin(az), cos(az), 0,                    \
        0, 0, 1);

#define NORMUV_PARM                             \
    {"bool", "hasNormal", "0"},                 \
    {"bool", "hasVertUV", "0"},                 \
    {"bool", "isFlipFace", "0"},

#define NORMUV_CIHOU                            \
    if (!get_input2<bool>("isFlipFace"))        \
        cc4::flipPrimFaceOrder(prim.get());     \
    if (!get_input2<bool>("hasNormal"))         \
        prim->verts.attrs.erase("nrm");         \
    if (!get_input2<bool>("hasVertUV"))         \
        prim->verts.attrs.erase("uv");

namespace zeno {
namespace {
namespace cc4{
    static void flipPrimFaceOrder(PrimitiveObject *prim) {
        for (auto &ind: prim->tris) {
            std::swap(ind[1], ind[2]);
        }
    }
}
}
}

namespace zeno {
namespace {

struct CreateCube : zeno::INode {
    virtual void apply() override {
        auto prim = std::make_shared<zeno::PrimitiveObject>();
        auto size = get_input2<float>("size");
        auto div_w = get_input2<int>("div_w");
        auto div_h = get_input2<int>("div_h");
        auto div_d = get_input2<int>("div_d");
        auto quad = get_input2<bool>("quads");
        auto position = get_input2<zeno::vec3f>("position");
        auto scale = get_input2<zeno::vec3f>("scaleSize");
        ROTATE_MATRIX

        auto &verts = prim->verts;
        auto &indis = prim->tris;
        auto &quads = prim->quads;
        auto &nors = prim->verts.add_attr<zeno::vec3f>("nrm");
        auto &poly = prim->polys;
        auto &loops = prim->loops;

        std::vector<zeno::vec3f> dummy;
        auto &uv1 = !quad ?  prim->tris.add_attr<vec3f>("uv0") : dummy;
        auto &uv2 = !quad ?  prim->tris.add_attr<vec3f>("uv1") : dummy;
        auto &uv3 = !quad ?  prim->tris.add_attr<vec3f>("uv2") : dummy;

        if(div_w <= 2)
            div_w = 2;
        if(div_h <= 2)
            div_h = 2;
        if(div_d <= 2)
            div_d = 2;

        float sw = 1.0f / (div_w-1);
        float sh = 1.0f / (div_h-1);
        float sd = 1.0f / (div_d-1);
        float sc=0.25f;

        for (int i = 0; i < div_w; i++)
        {
            for (int j = 0; j < div_h; j++)
            {
                for (int k = 0; k < div_d; k++)
                {
                    auto p = zeno::vec3f(
                        0.5f-i*sw, -0.5f+j*sh, 0.5f-k*sd);

                    if(j == 0 || j == div_h-1 || i == 0 || i == div_w-1 || k == 0 || k == div_d-1){
                        verts.push_back(p);
                        nors.emplace_back(0.0f,0.0f,0.0f);
                    }
                }
            }
        }

        int le =div_h*div_d;
        int rls=verts.size()-div_d;
        int pp=(div_h-1)*div_d;
        int pcircle=le-(div_h-2)*(div_d-2);
        int inc=verts.size()-div_h*div_d;

        int ss=0;
        for (int j = 0; j < div_h-1; j++)
        {
            for (int k = 0; k < div_d-1; k++)
            {
                int a =j*div_h+k*div_d;

                int i1,i2,i3,i4;
                i1=k+j*(div_d);
                i2=i1+1;
                i3=i2+(div_d-1);
                i4=i3+1;

                float u1,v1,u2,v2,u3,v3,u4,v4;
                zeno::vec3f uvw1,uvw2,uvw3,uvw4;

                v1=1.0f-k*sd;
                u1=1.0f-sh*j;
                u2=u1;
                v2=v1-sd;
                u3=u1-sh;
                v3=v1;
                u4=u3;
                v4=v2;

                uvw1=zeno::vec3f(0.125+u1*sc,v1*sc,0);
                uvw2=zeno::vec3f(0.125+u2*sc,v2*sc,0);
                uvw3=zeno::vec3f(0.125+u3*sc,v3*sc,0);
                uvw4=zeno::vec3f(0.125+u4*sc,v4*sc,0);

                // Left
                if(quad){
                    prim->loops.push_back(i1);
                    prim->loops.push_back(i2);
                    prim->loops.push_back(i4);
                    prim->loops.push_back(i3);
                    prim->polys.push_back({ss * 4, 4});
                }else{
                    indis.emplace_back(i1,i3,i2);
                    indis.emplace_back(i4,i2,i3);
                    uv1.push_back(uvw1);uv2.push_back(uvw3);uv3.push_back(uvw2);
                    uv1.push_back(uvw4);uv2.push_back(uvw2);uv3.push_back(uvw3);
                }
                ss++;

                uvw1=zeno::vec3f((1.0f-u1)*sc+0.625f,v1*sc,0);
                uvw2=zeno::vec3f((1.0f-u2)*sc+0.625f,v2*sc,0);
                uvw3=zeno::vec3f((1.0f-u3)*sc+0.625f,v3*sc,0);
                uvw4=zeno::vec3f((1.0f-u4)*sc+0.625f,v4*sc,0);

                int i1_=i1+inc,i2_=i2+inc,i3_=i3+inc,i4_=i4+inc;

                if(k!=div_d-2&&j!=div_h-2){
                    nors[i4]=zeno::vec3f(1,0,0);
                    nors[i4_]=zeno::vec3f(-1,0,0);
                }

                // Right
                if(quad){
                    prim->loops.push_back(i3_);
                    prim->loops.push_back(i4_);
                    prim->loops.push_back(i2_);
                    prim->loops.push_back(i1_);
                    prim->polys.push_back({ss * 4, 4});
                }else{
                    indis.emplace_back(i1_,i2_,i3_);
                    indis.emplace_back(i4_,i3_,i2_);
                    uv1.push_back(uvw1);uv2.push_back(uvw2);uv3.push_back(uvw3);
                    uv1.push_back(uvw4);uv2.push_back(uvw3);uv3.push_back(uvw2);
                }
                ss++;
            }
        }

        for (int j = -1; j < div_w-2; j++)
        {
            for (int i = 0; i < div_d-1; i++)
            {
                int i1,i2,i3,i4;
                i1=i+le+j*pcircle;
                i2=i1+pcircle;
                if(j==-1)
                    i1=i;
                i3=i1+1;
                i4=i2+1;

                float u1,v1,u2,v2,u3,v3,u4,v4;
                zeno::vec3f uvw1,uvw2,uvw3,uvw4;

                u1=sw*(j+1);
                v1=1.0f-i*sd;
                u2=u1+sw;
                v2=v1;
                u3=u1;
                v3=v1-sd;
                u4=u2;
                v4=v3;

                uvw1=zeno::vec3f(0.375f+u1*sc,v1*sc,0);
                uvw2=zeno::vec3f(0.375f+u2*sc,v2*sc,0);
                uvw3=zeno::vec3f(0.375f+u3*sc,v3*sc,0);
                uvw4=zeno::vec3f(0.375f+u4*sc,v4*sc,0);

                // Bottom
                if(quad){
                    prim->loops.push_back(i1);
                    prim->loops.push_back(i2);
                    prim->loops.push_back(i4);
                    prim->loops.push_back(i3);
                    prim->polys.push_back({ss * 4, 4});
                }else{
                    indis.emplace_back(i1,i3,i2);
                    indis.emplace_back(i4,i2,i3);
                    uv1.push_back(uvw1);uv2.push_back(uvw3);uv3.push_back(uvw2);
                    uv1.push_back(uvw4);uv2.push_back(uvw2);uv3.push_back(uvw3);
                }
                ss++;

                int i1_,i2_,i3_,i4_;
                i1_=pp+i+(j+1)*pcircle;
                i2_=i1_+pcircle;
                if(j==div_w-3)
                    i2_=rls+i;
                i3_=i1_+1;
                i4_=i2_+1;

                uvw1=zeno::vec3f(0.375f+u1*sc,0.5f+(1.0f-v1)*sc,0);
                uvw2=zeno::vec3f(0.375f+u2*sc,0.5f+(1.0f-v2)*sc,0);
                uvw3=zeno::vec3f(0.375f+u3*sc,0.5f+(1.0f-v3)*sc,0);
                uvw4=zeno::vec3f(0.375f+u4*sc,0.5f+(1.0f-v4)*sc,0);

                if(j!=div_w-3&&i!=div_d-2){
                    nors[i4]=zeno::vec3f(0,-1,0);
                    nors[i4_]=zeno::vec3f(0,1,0);
                }

                // Top
                if(quad){
                    prim->loops.push_back(i3_);
                    prim->loops.push_back(i4_);
                    prim->loops.push_back(i2_);
                    prim->loops.push_back(i1_);
                    prim->polys.push_back({ss * 4, 4});
                }else{
                    indis.emplace_back(i1_,i2_,i3_);
                    indis.emplace_back(i4_,i3_,i2_);
                    uv1.push_back(uvw1);uv2.push_back(uvw2);uv3.push_back(uvw3);
                    uv1.push_back(uvw4);uv2.push_back(uvw3);uv3.push_back(uvw2);
                }
                ss++;
            }
        }


        for (int j = 0; j < div_w-1; j++)
        {
            for (int i = 0; i < div_h-1; i++)
            {
                int i1,i2,i3,i4,i1_,i2_,i3_,i4_;

                int tc=le+div_d+j*pcircle;
                int ci1=tc+i*2; // front and back point increase

                if(j==div_w-2 && i!=0){
                    i1=tc+i*div_d;  // depth increase
                    i2=i1-div_d;
                    i3=ci1-pcircle;
                }else{
                    i1=ci1;
                    i2=i1-2;
                    i3=i1-pcircle;
                }
                if(j==0){
                    i3=div_d*(i+1);
                    i4=i3-div_d;
                }else{
                    i4=i3-2;
                }

                if(i==0){
                    i2=i1-div_d;
                    i4=i3-div_d;
                }

                i1_=i1+1;
                i2_=i2+1;
                i3_=i3+1;
                i4_=i4+1;
                if(i==div_h-2 || j==div_w-2&&i!=div_h-2)
                    i1_=i1+(div_d-1);
                if(i==0 || j==div_w-2)
                    i2_=i2+(div_d-1);
                if(j!=0&&i==div_h-2)
                    i3_=i3+(div_d-1);
                if(i==0||j==0)
                    i4_=i4+(div_d-1);
                if(j==0)
                    i3_=i3+(div_d-1);

                float u1,v1,u2,v2,u3,v3,u4,v4;
                zeno::vec3f uvw1,uvw2,uvw3,uvw4;

                u4=j*sw;
                v4=i*sh;
                u3=u4;
                v3=v4+sh;
                u1=u4+sw;
                v1=v3;
                u2=u1;
                v2=v4;

                uvw1=zeno::vec3f(0.375f+u1*sc,0.25f+v1*sc,0);
                uvw2=zeno::vec3f(0.375f+u2*sc,0.25f+v2*sc,0);
                uvw3=zeno::vec3f(0.375f+u3*sc,0.25f+v3*sc,0);
                uvw4=zeno::vec3f(0.375f+u4*sc,0.25f+v4*sc,0);

                // Back
                if(quad){
                    prim->loops.push_back(i1);
                    prim->loops.push_back(i2);
                    prim->loops.push_back(i4);
                    prim->loops.push_back(i3);
                    prim->polys.push_back({ss * 4, 4});
                }else{
                    indis.emplace_back(i1,i3,i2);
                    indis.emplace_back(i4,i2,i3);
                    uv1.push_back(uvw1);uv2.push_back(uvw3);uv3.push_back(uvw2);
                    uv1.push_back(uvw4);uv2.push_back(uvw2);uv3.push_back(uvw3);
                }
                ss++;

                uvw1=zeno::vec3f(0.375f+u1*sc,0.75f+(1.0f-v1)*sc,0);
                uvw2=zeno::vec3f(0.375f+u2*sc,0.75f+(1.0f-v2)*sc,0);
                uvw3=zeno::vec3f(0.375f+u3*sc,0.75f+(1.0f-v3)*sc,0);
                uvw4=zeno::vec3f(0.375f+u4*sc,0.75f+(1.0f-v4)*sc,0);

                if(j!=div_w-2&&i!=div_h-2){
                    nors[i1]=zeno::vec3f(0,0,1);
                    nors[i1_]=zeno::vec3f(0,0,-1);
                }

                // Front
                if(quad){
                    prim->loops.push_back(i3_);
                    prim->loops.push_back(i4_);
                    prim->loops.push_back(i2_);
                    prim->loops.push_back(i1_);
                    prim->polys.push_back({ss * 4, 4});
                }else{
                    indis.emplace_back(i1_,i2_,i3_);
                    indis.emplace_back(i4_,i3_,i2_);
                    uv1.push_back(uvw1);uv2.push_back(uvw2);uv3.push_back(uvw3);
                    uv1.push_back(uvw4);uv2.push_back(uvw3);uv3.push_back(uvw2);
                }
                ss++;
            }
        }

        for (int i = 0; i < div_d; i++)
        {
            if(i==0){
                nors[i]=normalize(zeno::vec3f(0.3,-0.3,0.3));
                nors[i+inc]=normalize(zeno::vec3f(-0.3,-0.3,0.3));
                nors[i+rls]=normalize(zeno::vec3f(-0.3,0.3,0.3));
                nors[i+pp]=normalize(zeno::vec3f(0.3,0.3,0.3));
            }
            else if(i==div_d-1){
                nors[i]=normalize(zeno::vec3f(0.3,-0.3,-0.3));
                nors[i+inc]=normalize(zeno::vec3f(-0.3,-0.3,-0.3));
                nors[i+rls]=normalize(zeno::vec3f(-0.3,0.3,-0.3));
                nors[i+pp]=normalize(zeno::vec3f(0.3,0.3,-0.3));
            }
            else{
                nors[i]=normalize(zeno::vec3f(0.5,-0.5,0));
                nors[i+inc]=normalize(zeno::vec3f(-0.5,-0.5,0));
                nors[i+rls]=normalize(zeno::vec3f(-0.5,0.5,0));
                nors[i+pp]=normalize(zeno::vec3f(0.5,0.5,0));
            }
        }

        for (int i = 1; i < div_h-1; i++)
        {
            int i1=i*(div_d);
            int i2=i1+(div_d-1);
            int i3=inc+(i+1)*(div_d)-1;
            int i4=i3-(div_d-1);

            nors[i1]=normalize(zeno::vec3f(0.5,0,0.5));
            nors[i2]=normalize(zeno::vec3f(0.5,0,-0.5));
            nors[i3]=normalize(zeno::vec3f(-0.5,0,-0.5));
            nors[i4]=normalize(zeno::vec3f(-0.5,0,0.5));
        }

        for (int i = 0; i < div_w-2; i++)
        {
            int i1=le+i*pcircle;
            int i2=i1+(div_d-1);
            int i3=pcircle+pp+i*pcircle;
            int i4=i3+(div_d-1);

            nors[i1]=normalize(zeno::vec3f(0,-0.5,0.5));
            nors[i2]=normalize(zeno::vec3f(0,-0.5,-0.5));
            nors[i3]=normalize(zeno::vec3f(0,0.5,0.5));
            nors[i4]=normalize(zeno::vec3f(0,0.5,-0.5));
        }

        for (int i = 0; i < verts->size(); i++)
        {
            auto p = verts[i];
            auto n = nors[i];

            p = p * scale * size;

            ROTATE_COMPUTE
                p+= position;

            auto gn = glm::vec3(n[0], n[1], n[2]);
            gn = mz * my * mx * gn;
            n = zeno::vec3f(gn.x, gn.y, gn.z);

            verts[i] = p;
            nors[i] = n;
        }

        NORMUV_CIHOU
        set_output("prim", std::move(prim));
    }
};

ZENDEFNODE(CreateCube, {
    {
        {"vec3f", "position", "0, 0, 0"},
        {"vec3f", "scaleSize", "1, 1, 1"},
        ROTATE_PARM
        NORMUV_PARM
        {"int", "div_w", "2"},
        {"int", "div_h", "2"},
        {"int", "div_d", "2"},
        {"float", "size", "1"},
        {"bool", "quads", "0"},
    },
    {"prim"},
    {},
    {"create"},
});

struct CreateDisk : zeno::INode {
    virtual void apply() override {
        auto prim = std::make_shared<zeno::PrimitiveObject>();
        auto position = get_input2<zeno::vec3f>("position");
        auto scaleSize = get_input2<zeno::vec3f>("scaleSize");
        auto radius = get_input2<float>("radius");
        auto divisions = get_input2<int>("divisions");

        ROTATE_MATRIX

        auto &verts = prim->verts;
        auto &tris = prim->tris;
        auto &uv = prim->verts.add_attr<zeno::vec3f>("uv");
        auto &norm = prim->verts.add_attr<zeno::vec3f>("nrm");

        if(divisions <= 3){
            divisions = 3;
        }

        verts.emplace_back(zeno::vec3f(0, 0, 0)+position);
        uv.emplace_back(0.5, 0.5, 0);
        norm.emplace_back(0, 1, 0);

        for (int i = 0; i < divisions; i++) {
            float rad = 2 * M_PI * i / divisions;
            auto p = zeno::vec3f(cos(rad) * radius, 0,
                           -sin(rad) * radius);
            auto p4uv = p * scaleSize;
            p = p4uv;

            ROTATE_COMPUTE
                p+= position;

            verts.emplace_back(p);
            tris.emplace_back(i+1, 0, i+2);
            uv.emplace_back(p4uv[0]/2.0+0.5,
                            p4uv[2]/2.0+0.5, 0);
            norm.emplace_back(0, 1, 0);
        }

        // Update last
        tris[tris.size()-1] = zeno::vec3i(divisions, 0, 1);

        NORMUV_CIHOU
        set_output("prim", std::move(prim));
    }
};

ZENDEFNODE(CreateDisk, {
    {
        {"vec3f", "position", "0, 0, 0"},
        {"vec3f", "scaleSize", "1, 1, 1"},
        ROTATE_PARM
        NORMUV_PARM
        {"float", "radius", "1"},
        {"int", "divisions", "32"},
    },
    {"prim"},
    {},
    {"create"},
});

struct CreatePlane : zeno::INode {
    virtual void apply() override {
        auto prim = std::make_shared<zeno::PrimitiveObject>();
        auto position = get_input2<zeno::vec3f>("position");
        auto scale = get_input2<zeno::vec3f>("scaleSize");
        auto size = get_input2<float>("size");
        auto rows = get_input2<int>("rows");
        auto columns = get_input2<int>("columns");
        auto quad = get_input2<bool>("quads");

        ROTATE_MATRIX

        auto &verts = prim->verts;
        auto &quads = prim->quads;
        auto &tris = prim->tris;
        auto &poly = prim->polys;
        auto &loops = prim->loops;

        std::vector<zeno::vec3f> uvs;
        std::vector<zeno::vec3f> nors;

        if(rows <= 1)
            rows = 1;
        if(columns <= 1)
            columns = 1;

        auto start_point = zeno::vec3f(0.5, 0, 0.5);
        auto gscale = glm::vec3(scale[0], scale[1], scale[2]);
        auto gposition = glm::vec3(position[0], position[1], position[2]);
        zeno::vec3f normal(0.0f);
        float rm = 1.0f / rows;
        float cm = 1.0f / columns;
        int fi = 0;

        // Vertices & UV
        for(int i=0; i<=rows; i++){

            auto rp = start_point - zeno::vec3f(i*rm, 0, 0);

            for(int j=0; j<=columns; j++){
                auto p = rp - zeno::vec3f(0, 0, j*cm);
                p = p * scale * size;

                ROTATE_COMPUTE
                    p +=position;

                auto zcp = zeno::vec3f(p[0], p[1], p[2]);
                verts.push_back(zcp);
                uvs.emplace_back(i*rm, j*cm*-1+1, 0);
            }
        }

        // Indices
        int ss = 0;
        for(int i=0; i<rows; i++){
            for(int j=0; j<columns; j++){
                int i1 = fi;
                int i2 = i1+1;
                int i3 = fi+(columns+1);
                int i4 = i3+1;

                if(quad){
                    prim->loops.push_back(i1);
                    prim->loops.push_back(i2);
                    prim->loops.push_back(i4);
                    prim->loops.push_back(i3);
                    prim->polys.push_back({ss * 4, 4});
                }
                else{
                    tris.emplace_back(i1, i4, i2);
                    tris.emplace_back(i3, i4, i1);
                }
                ss++;
                fi += 1;
            }
            fi += 1;
        }

        // Normal
        for(int i=0; i<1; i++){
            vec3i ind;
            if(quad){
                ind = vec3i(loops[4*i],loops[4*i+1],loops[4*i+2]);
            }
            else{
                ind = tris[i];
            }
            // 0,3,1
            auto pos1 = verts[int(ind[0])];
            auto pos2 = verts[int(ind[1])];
            auto pos3 = verts[int(ind[2])];

            auto uv1 = uvs[int(ind[0])];
            auto uv2 = uvs[int(ind[1])];
            auto uv3 = uvs[int(ind[2])];

            auto edge1 = pos2 - pos1;
            auto edge2 = pos3 - pos1;
            auto deltaUV1 = uv2 - uv1;
            auto deltaUV2 = uv3 - uv1;

            zeno::vec3f tangent1, bitangent1;

            float f = 1.0f / (deltaUV1[0] * deltaUV2[1] - deltaUV2[0] * deltaUV1[1]);

            tangent1[0] = f * (deltaUV2[1] * edge1[0] - deltaUV1[1] * edge2[0]);
            tangent1[1] = f * (deltaUV2[1] * edge1[1] - deltaUV1[1] * edge2[1]);
            tangent1[2] = f * (deltaUV2[1] * edge1[2] - deltaUV1[1] * edge2[2]);

            bitangent1[0] = f * (-deltaUV2[0] * edge1[0] + deltaUV1[0] * edge2[0]);
            bitangent1[1] = f * (-deltaUV2[0] * edge1[1] + deltaUV1[0] * edge2[1]);
            bitangent1[2] = f * (-deltaUV2[0] * edge1[2] + deltaUV1[0] * edge2[2]);

            normal = cross(tangent1, bitangent1);
            //normal = normalize(cross(edge2, edge1));
        }

        // Assign uv & normal
        auto &uv = prim->verts.add_attr<zeno::vec3f>("uv");
        auto &norm = prim->verts.add_attr<zeno::vec3f>("nrm");
        for(int i=0; i<verts.size(); i++){
            uv[i] = zeno::vec3f(1 - uvs[i][0], 1 - uvs[i][1], 0);
            norm[i] = normal;
        }

        for (int i = 0; i < uvs.size(); i++) {
            prim->uvs.emplace_back(uvs[i][0], uvs[i][1]);
        }

        if(prim->loops.size()!= 0 ){
            prim->loop_uvs.resize(prim->loops.size());
            for (auto i = 0; i < prim->loops.size(); i++) {
                auto lo = prim->loops[i];
                prim->loop_uvs[i] = lo;
            }
        }

        prim->userData().setLiterial("pos", std::move(position));
        prim->userData().setLiterial("scale", std::move(scale));
        prim->userData().setLiterial("rotate", std::move(rotate));

        NORMUV_CIHOU
        set_output("prim", std::move(prim));
    }
};

ZENDEFNODE(CreatePlane, {
    {
        {"vec3f", "position", "0, 0, 0"},
        {"vec3f", "scaleSize", "1, 1, 1"},
        ROTATE_PARM
        NORMUV_PARM
        {"float", "size", "1"},
        {"int", "rows", "1"},
        {"int", "columns", "1"},
        {"bool", "quads", "0"},
    },
    {"prim"},
    {},
    {"create"},
});

struct CreateTube : zeno::INode {
    virtual void apply() override {
        auto prim = std::make_shared<zeno::PrimitiveObject>();
        auto position = get_input2<zeno::vec3f>("position");
        auto scale = get_input2<zeno::vec3f>("scaleSize");
        auto radius1 = get_input2<float>("radius1");
        auto radius2 = get_input2<float>("radius2");
        auto height = get_input2<float>("height");
        auto rows = get_input2<int>("rows");
        auto columns = get_input2<int>("columns");

        ROTATE_MATRIX

        auto &verts = prim->verts;
        auto &indis = prim->tris;
        auto &uvs = prim->verts.add_attr<zeno::vec3f>("uv");
        auto &nors = prim->verts.add_attr<zeno::vec3f>("nrm");
        auto &uv1 = prim->tris.add_attr<zeno::vec3f>("uv0");
        auto &uv2 = prim->tris.add_attr<zeno::vec3f>("uv1");
        auto &uv3 = prim->tris.add_attr<zeno::vec3f>("uv2");

        if(rows <= 3)
            rows = 3;
        if(columns <= 3)
            columns = 3;

        std::vector<zeno::vec3f> mverts;

        float hs = height/2.0;

        verts.emplace_back(0,hs,0);
        nors.emplace_back(0,1,0);
        for (int i = 0; i < columns; i++) {
            uv1.emplace_back(0.5, 0.85, 0);
        }
        for (int i = 0; i < columns; i++) {
            float rad = 2.0f * M_PI * i / columns;
            float x = cos(rad);
            float z = -sin(rad);
            auto p1 = zeno::vec3f(x*radius1, hs, z*radius1);

            verts.push_back(p1);
            nors.emplace_back(0,1,0);
        }
        for (int i = 0; i < columns; i++) {
            float rad = 2.0f * M_PI * i / columns;
            float x = cos(rad);
            float z = -sin(rad);
            float of = 0.125;
            auto p1 = zeno::vec3f(x*radius2, -hs, z*radius2);

            verts.push_back(p1);
            nors.emplace_back(0,-1,0);
        }
        verts.emplace_back(0,-hs,0);
        nors.emplace_back(0,-1,0);
        for (int i = 0; i < columns; i++) {
            uv1.emplace_back(0.5, 0.15, 0);
        }

        for (int i = 1; i < columns+1; i++) {
            float rad = 2.0f * M_PI * (i) / columns;
            float x = cos(rad);
            float z = -sin(rad);
            float radn = 2.0f * M_PI * (i-1) / columns;
            float xn = cos(radn);
            float zn = -sin(radn);

            int i1,i2,i3;
            i1 = 0;
            i2 = i;
            i3 = i2+1;
            if(i == columns)
                i3 = 1;
            indis.emplace_back(i1, i3, i2);

            float u1=x*0.5*3/10+0.5;
            float v1=z*0.5*3/10+0.85;
            float u1n=xn*0.5*3/10+0.5;
            float v1n=zn*0.5*3/10+0.85;

            uv2.emplace_back(u1, v1, 0);
            uv3.emplace_back(u1n, v1n, 0);
        }

        for (int i = 1; i < columns+1; i++) {
            float rad = 2.0f * M_PI * (i-1) / columns;
            float x = cos(rad);
            float z = -sin(rad);
            float radn = 2.0f * M_PI * (i) / columns;
            float xn = cos(radn);
            float zn = -sin(radn);

            float b1,b2,b3;
            b1 = verts->size()-1;
            b2 = b1-columns+i-1;
            b3 = b2+1;
            if(i == columns)
                b3 -= columns;
            indis.emplace_back(b1, b2, b3);

            float u1=x*0.5*3/10+0.5;
            float v1=z*0.5*3/10+0.85;
            float u1n=xn*0.5*3/10+0.5;
            float v1n=zn*0.5*3/10+0.85;

            uv2.emplace_back(u1, v1-0.7, 0);
            uv3.emplace_back(u1n, v1n-0.7, 0);
        }

        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < columns; j++)
            {
                float f = float(i)/(rows-1);
                int ti = j+1;
                int bi = verts->size()-1-columns+j;
                auto pu = verts[ti];
                auto pd = verts[bi];
                auto np = (1-f)*pu+(f)*pd;

                if(i!=0 && i!=(rows-1)){
                    mverts.push_back(np);
                    nors.emplace_back(0,0,0);
                }
            }
        }

        for (int i = 0; i < mverts.size(); i++)
        {
            verts.push_back(mverts[i]);
        }

        for (int i = 1; i < rows; i++)
        {
            for (int j = 0; j < columns; j++)
            {
                int i1, i2, i3, i4;
                i1 = j+i*(columns)+2; //Two points at the top and bottom
                if(i==1)
                    i1-=columns+1;
                i2 = i1+1;
                i3 = i1+columns;
                if(i==1)
                    i3+=columns+1;
                i4 = i3+1;
                if(j == columns-1){
                    i2 -=columns;
                    i4 -=columns;
                }
                if(i==rows-1){
                    i3 -=i1-1-j;
                    i4 =i3+1;
                    if(j==columns-1)
                        i4-=columns;
                }

                float u1,v1,u2,v2,u3,v3,u4,v4;
                float sf = 4.0/10;
                float uf = 0.3;

                u1=float(j)/columns     *sf+uf;
                u2=float(j+1)/columns   *sf+uf;
                v1=float(i-1)/(rows-1)  *sf+uf;
                v2=v1;
                u3=u1;
                u4=u2;
                v3=float(i)/(rows-1)    *sf+uf;
                v4=v3;

                uv1.emplace_back(u1,v1,0);uv2.emplace_back(u2,v2,0);uv3.emplace_back(u4,v4,0);
                uv1.emplace_back(u1,v1,0);uv2.emplace_back(u4,v4,0);uv3.emplace_back(u3,v3,0);
                indis.emplace_back(i1, i2, i4);
                indis.emplace_back(i1, i4, i3);

                int b4=i1-1;
                if(j==0)
                    b4+=columns;
                auto p1 = verts[i1]*scale;
                auto p2 = verts[i2]*scale;
                auto p3 = verts[i3]*scale;
                auto p4 = verts[b4]*scale;
                auto n1 = normalize(cross(p2-p1, p1-p3));
                auto n2 = normalize(cross(p4-p1, p3-p1));

                zeno::vec3f n;
                n = normalize((n1+n2)/2.0);
                if(i==1){
                    auto up=zeno::vec3f(0,1,0);
                    nors[i1] = normalize((n1+n2+up)*scale/3.0);
                }
                if(i==rows-1){
                    auto down=zeno::vec3f(0,-1,0);
                    nors[i3] = normalize((n1+n2+down)*scale/3.0);
                    continue;
                }
                nors[i3] = n;
            }
        }

        for (int i = 0; i < verts->size(); i++)
        {
            auto p = verts[i];
            auto n = nors[i];


            p = p * scale ;

            ROTATE_COMPUTE
                p+=position;

            auto gn = glm::vec3(n[0], n[1], n[2]);
            gn = mz * my * mx * gn;
            n = zeno::vec3f(gn.x, gn.y, gn.z);

            verts[i] = p;
            nors[i] = n;
        }

        NORMUV_CIHOU
        set_output("prim", std::move(prim));
    }
};

ZENDEFNODE(CreateTube, {
    {
        {"vec3f", "position", "0, 0, 0"},
        {"vec3f", "scaleSize", "1, 1, 1"},
        ROTATE_PARM
        NORMUV_PARM
        {"float", "radius1", "1"},
        {"float", "radius2", "1"},
        {"float", "height", "2"},
        {"int", "rows", "3"},
        {"int", "columns", "12"}
    },
    {"prim"},
    {},
    {"create"},
});

struct CreateSphere : zeno::INode {
    virtual void apply() override {
        auto prim = std::make_shared<zeno::PrimitiveObject>();
        auto position = get_input2<zeno::vec3f>("position");
        auto scale = get_input2<zeno::vec3f>("scaleSize");
        auto rows = get_input2<int>("rows");
        auto columns = get_input2<int>("columns");
        auto radius = get_input2<float>("radius");
        auto quad = get_input2<bool>("quads");

        ROTATE_MATRIX

        if(rows <= 3)
            rows = 3;
        if(columns <= 3)
            columns = 3;

        //auto &uv = prim->add_attr<zeno::vec3f>("uv");
        //auto &nrm = prim->add_attr<zeno::vec3f>("nrm");
        auto &uv = prim->verts.add_attr<zeno::vec3f>("uv");
        auto &nors = prim->verts.add_attr<zeno::vec3f>("nrm");
        auto &verts = prim->verts;
        auto &tris = prim->tris;
        auto &quads = prim->quads;
        auto &uv1 = prim->tris.add_attr<zeno::vec3f>("uv0");
        auto &uv2 = prim->tris.add_attr<zeno::vec3f>("uv1");
        auto &uv3 = prim->tris.add_attr<zeno::vec3f>("uv2");
        auto &poly = prim->polys;
        auto &loops = prim->loops;

        if(rows <= 3)
            rows = 3;
        if(columns <= 3)
            columns = 3;

        int fi=0;
        float row_sep = 180.0 / (rows - 1);
        float uoff = 1.0/columns/2;
        float vinc = 1.0/(rows-1);

        // verts
        for (int i = 0; i<rows; i++) {
            float ic = -90.0 + i*row_sep;
            float r = cos(ic / 180.0 * M_PI);
            float h = sin(ic / 180.0 * M_PI);

            for (int j = 0; j < columns; j++) {
                float rad = 2 * M_PI * j / columns;
                // position
                auto p = zeno::vec3f(cos(rad) * r, h, sin(rad) * r);

                auto op = p;
                verts.push_back(op);
                auto n = op - zeno::vec3f(0,0,0);
                nors.push_back(zeno::normalize(n));
                if(i == 0 || i == (rows-1))
                    break;
            }
        }

        int li=verts.size()-1;

        // head tris & head uv
        for (int i = 1; i < columns+1; i++)
        {
            int i0,i1;
            i0=i;
            i1=i0+1;
            if(i==columns){
                i1-=columns;
            }

            float u1,v1,u2,v2,u3,v3;
            float u_ = float(i0-1)/(columns);
            v1=0; v2=vinc; v3=vinc;
            u1=u_+uoff;
            u2=float(i1-1)/(columns);
            u3=u_;
            if(i==columns){
                u2=1.0;
            }
            auto uvw1 = zeno::vec3f(u1,v1,0);
            auto uvw2 = zeno::vec3f(u2,v2,0);
            auto uvw3 = zeno::vec3f(u3,v3,0);

            tris.emplace_back(fi,i1,i0);
            uv1.push_back(uvw1);uv2.push_back(uvw2);uv3.push_back(uvw3);
        }

        // body tris
        int ss = 0;
        for (int i = 0; i<rows-3; i++) {
            for (int j = 1; j < columns+1; j++) {
                int i0,i1,i2,i3;

                i0=(i*columns)+j;
                i1=i0+1;
                i2=i0+columns;
                i3=i2+1;

                if(j==columns){
                    i1-=columns;
                    i3-=columns;
                }

                float u1,v1,u2,v2,u3,v3,u4,v4;
                zeno::vec3f uvw1,uvw2,uvw3,uvw4;
                v1=v2=(i+1.0f)*vinc;
                u1 = float(i0-1)/(columns)-i;
                u2=float(i1-1)/(columns)-i;
                if(j==columns){
                    u2=1.0;
                }
                u3=u1;
                u4=u2;
                v3=v4=(i+2.0f)*vinc;

                uvw1=zeno::vec3f(u1,v1,0);uvw2=zeno::vec3f(u2,v2,0);uvw3=zeno::vec3f(u3,v3,0);uvw4=zeno::vec3f(u4,v4,0);

                if(quad){
                    prim->loops.push_back(i0);
                    prim->loops.push_back(i1);
                    prim->loops.push_back(i3);
                    prim->loops.push_back(i2);
                    prim->polys.push_back({ss * 4, 4});
                }else{
                    uv1.push_back(uvw1);uv2.push_back(uvw4);uv3.push_back(uvw3);
                    uv1.push_back(uvw4);uv2.push_back(uvw1);uv3.push_back(uvw2);
                    tris.emplace_back(i0,i3,i2);
                    tris.emplace_back(i3,i0,i1);
                }
                ss++;
            }
        }

        // bottom tris
        for (int i = columns,j=0; i > 0; i--,j++)
        {
            int i2,i3;
            i2=li-i+1;
            i3=li-i;
            if(i2==li){
                i2-=columns;
            }

            float u1,v1,u2,v2,u3,v3;
            v1=1.0; v2=1.0-vinc; v3=1.0-vinc;
            float u_=float(j+1)/(columns);
            u1=u_-uoff;
            u2=float(j)/(columns);
            u3=u_;
            if(i==0){
                u2=1.0;
            }
            auto uvw1 = zeno::vec3f(u1,v1,0);
            auto uvw2 = zeno::vec3f(u2,v2,0);
            auto uvw3 = zeno::vec3f(u3,v3,0);

            uv1.push_back(uvw1);uv2.push_back(uvw2);uv3.push_back(uvw3);
            tris.emplace_back(li,i3,i2);
        }

        for (int i = 0; i < verts->size(); i++)
        {
            auto p = verts[i];
            auto n = nors[i];

            p = p * scale * radius ;

            ROTATE_COMPUTE

                p+= position;

            auto gn = glm::vec3(n[0], n[1], n[2]);
            gn = mz * my * mx * gn;
            n = zeno::vec3f(gn.x, gn.y, gn.z);

            verts[i] = p;
            nors[i] = n;
        }

        NORMUV_CIHOU
        set_output("prim", std::move(prim));
    }
};

ZENDEFNODE(CreateSphere, {
    {
        {"vec3f", "position", "0, 0, 0"},
        {"vec3f", "scaleSize", "1, 1, 1"},
        {"float", "radius", "1"},
        ROTATE_PARM
        NORMUV_PARM
        {"int", "rows", "13"},
        {"int", "columns", "24"},
        {"bool", "quads", "0"},
    },
    {"prim"},
    {},
    {"create"},
});

struct CreateCone : zeno::INode {
    virtual void apply() override {
        auto prim = std::make_shared<zeno::PrimitiveObject>();
        auto position = get_input2<zeno::vec3f>("position");
        auto scaleSize = get_input2<zeno::vec3f>("scaleSize");
        auto radius = get_input2<float>("radius");
        auto height = get_input2<float>("height");
        auto lons = get_input2<int>("lons");

        auto &pos = prim->verts;
        for (size_t i = 0; i < lons; i++) {
            float rad = 2 * M_PI * i / lons;
            pos.push_back(vec3f(cos(rad) * radius, -0.5 * height, -sin(rad) * radius) * scaleSize + position);
        }
        // top
        pos.push_back(vec3f(0, 0.5 * height, 0) * scaleSize + position);
        // bottom
        pos.push_back(vec3f(0, -0.5 * height, 0) * scaleSize + position);

        auto &tris = prim->tris;
        for (size_t i = 0; i < lons; i++) {
            tris.push_back(vec3i(lons, i, (i + 1) % lons));
            tris.push_back(vec3i(i, lons + 1, (i + 1) % lons));
        }
        set_output("prim", std::move(prim));
    }
};

ZENDEFNODE(CreateCone, {
    {
        {"vec3f", "position", "0, 0, 0"},
        {"vec3f", "scaleSize", "1, 1, 1"},
        {"float", "radius", "1"},
        {"float", "height", "2"},
        {"int", "lons", "32"},
    },
    {"prim"},
    {},
    {"create"},
});

struct CreateCylinder : zeno::INode {
    virtual void apply() override {
        auto prim = std::make_shared<zeno::PrimitiveObject>();

        auto position = get_input2<zeno::vec3f>("position");
        auto scaleSize = get_input2<zeno::vec3f>("scaleSize");
        auto radius = get_input2<float>("radius");
        auto height = get_input2<float>("height");
        auto lons = get_input2<int>("lons");

        auto &pos = prim->verts;
        for (size_t i = 0; i < lons; i++) {
            float rad = 2 * M_PI * i / lons;
            pos.push_back(vec3f(cos(rad) * radius, 0.5 * height, -sin(rad) * radius) * scaleSize + position);
        }
        for (size_t i = 0; i < lons; i++) {
            float rad = 2 * M_PI * i / lons;
            pos.push_back(vec3f(cos(rad) * radius, -0.5 * height, -sin(rad) * radius) * scaleSize + position);
        }
        pos.push_back(vec3f(0, 0.5 * height, 0) * scaleSize + position);
        pos.push_back(vec3f(0, -0.5 * height, 0) * scaleSize + position);

        auto &tris = prim->tris;
        // Top
        for (size_t i = 0; i < lons; i++) {
            tris.push_back(vec3i(lons * 2, i, (i + 1) % lons));
        }
        // Bottom
        for (size_t i = 0; i < lons; i++) {
            tris.push_back(vec3i(i + lons, lons * 2 + 1, (i + 1) % lons + lons));
        }
        // Side
        for (size_t i = 0; i < lons; i++) {
            size_t _0 = i;
            size_t _1 = (i + 1) % lons;
            size_t _2 = (i + 1) % lons + lons;
            size_t _3 = i + lons;
            tris.push_back(vec3i(_1, _0, _2));
            tris.push_back(vec3i(_2, _0, _3));
        }
        set_output("prim", std::move(prim));
    }
};

ZENDEFNODE(CreateCylinder, {
    {
        {"vec3f", "position", "0, 0, 0"},
        {"vec3f", "scaleSize", "1, 1, 1"},
        {"float", "radius", "1"},
        {"float", "height", "2"},
        {"int", "lons", "32"},
    },
    {"prim"},
    {},
    {"create"},
});
}
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值