头文件 sop_mycone.h
///*这个例子创建一个简单的圆锥形状*/
#ifndef __sop_mycone_h__
#define __sop_mycone_h__
#include
class SOP_MyCone : public SOP_Node
{
public:
static OP_Node *myConstructor(OP_Network *, const char *, OP_Operator *);//创建sop节点
static PRM_Template myTemplateList[];//节点参数面板需要的参数
protected:
SOP_MyCone(OP_Network *net, const char *name, OP_Operator *op);//构造
virtual ~SOP_MyCone();//虚析构
virtual OP_ERROR cookMySop(OP_Context &context);//sop核心计算
private:
//参数面板的参数属于该节点私有
fpreal CENTERX(fpreal t) { return evalFloat("t", 0, t); }
fpreal CENTERY(fpreal t) { return evalFloat("t", 1, t); }
fpreal CENTERZ(fpreal t) { return evalFloat("t", 2, t); }
fpreal HEIGHT(fpreal t) { return evalFloat("height", 0, t); }
fpreal RADIUS(fpreal t) { return evalFloat("rad", 0, t); }
fpreal SCALE(fpreal t) { return evalFloat("s", 0, t); }
int DIVSION(fpreal t) { return evalInt("divs", 0, t); }
};
#endif
源文件 sop_mycone.cpp
#include"sop_mycone.h"
#include
#include
#include//PRM相关的头文件貌似都包含在这里了
#include//有这个houdini里面才能找到你编译好的东西
#include
#include//这里主要是是取了个圆周率M_PI
#include//创建poly多边形
#include//对象指针gdp在这里
//newSopOperator是Houdini从这个DLL抓取并调用注册SOP的钩子。在这种情况下,我们将自己添加到指定的OperatorTable中
void newSopOperator(OP_OperatorTable *table)
{
table->addOperator(new OP_Operator("mycone", "Cone",
SOP_MyCone::myConstructor,//创建新的对象
SOP_MyCone::myTemplateList,//参数模板列表
0, 0,//最小最大输入端口数
nullptr,//本地变量
OP_FLAG_GENERATOR//标识为常规
));
}
//创建锥形对象
OP_Node *SOP_MyCone::myConstructor(OP_Network *net, const char *name, OP_Operator *op)
{
return new SOP_MyCone(net, name, op);
}
//参数模板
PRM_Template SOP_MyCone::myTemplateList[] = {
PRM_Template(PRM_XYZ, PRM_Template::PRM_EXPORT_TBX, 3, &PRMcenterName),
PRM_Template(PRM_FLT, 1, &PRMheightName, PRMoneDefaults),
PRM_Template(PRM_FLT, 1, &PRMradiusName, PRMoneDefaults),
PRM_Template(PRM_FLT, 1, &PRMscaleName, PRMoneDefaults),
PRM_Template(PRM_INT, 1, &PRMdivName, PRMthreeDefaults, 0, &PRMdivision2Range),
PRM_Template()
};
//构造
SOP_MyCone::SOP_MyCone(OP_Network *net, const char *name, OP_Operator *op) :SOP_Node(net, name, op)
{
mySopFlags.setManagesDataIDs(true);
}
//析构,啥都不干
SOP_MyCone::~SOP_MyCone() {};
//如何创建一个3边形polygon
void addPolygon(GU_Detail* gdp, exint v1, exint v2, exint v3)
{
//追加一个新的多边形primitive,原始类型在GEO_PrimType.h中定义
GEO_PrimPoly *prim_poly_ptr = (GEO_PrimPoly *)gdp->appendPrimitive(GA_PRIMPOLY);
//追加形成这个primitive的vertices,点偏移
prim_poly_ptr->appendVertex(v1);
prim_poly_ptr->appendVertex(v2);
prim_poly_ptr->appendVertex(v3);
prim_poly_ptr->close();//最后封闭primitive使其成为多边形而不是多段线。
}
//锥形的底部需要封闭起来,函数重载(跟上面的创建3变形函数名相同,但是参数不同)
void addPolygon(GU_Detail* gdp, exint vstart, exint nv)
{
GEO_PrimPoly *prim_poly_ptr = (GEO_PrimPoly *)gdp->appendPrimitive(GA_PRIMPOLY);
//追加形成这个primitive的vertices,我们利用索引图的单调性保证来避免保留单独的添加点偏移数组
for (vstart; vstart <= nv; ++vstart)
{
prim_poly_ptr->appendVertex(vstart);
}
prim_poly_ptr->close();//封闭primitive使其成为多边形而不是多段线。
}
//sop 锥形形状核心计算
OP_ERROR SOP_MyCone::cookMySop(OP_Context &context)
{
fpreal now = context.getTime();
UT_Vector3 center(CENTERX(now), CENTERY(now), CENTERZ(now));
fpreal height = HEIGHT(now);
fpreal rad = RADIUS(now);
fpreal scale = SCALE(now);
int divsion = DIVSION(now);
//这里例子是生产一个锥形的节点,没有任何输入端,所以需要销毁所有可能的数据
gdp->clearAndDestroy();
//形成锥形的点位置
for (exint i = 0; i < divsion + 1; i++)
{
GA_Offset ptoff = gdp->appendPoint();
UT_Vector3 pos;
if (i == 0)//锥形的顶部点,我把它作为起始点
{
pos(0) = 0; pos(1) = height * scale; pos(2) = 0;
}
else {
pos(0) = SYScos((float)(i - 1) * 2 * M_PI / (float)divsion) * rad * scale;
pos(1) = 0;
pos(2) = SYSsin((float)(i - 1) * 2 * M_PI / (float)divsion) * rad * scale;
}
pos += center;
gdp->setPos3(ptoff, pos);
}
//形成一个多边形至少需要3个点,所以i初始为2
for (exint i = 2; i < divsion + 1; i++)
{
addPolygon(gdp, 0, i, i-1);
if(i>2)
addPolygon(gdp, 0, 1, divsion);
if(i>2 && i==divsion)
addPolygon(gdp, 1, divsion);
}
return error();
}
这个HDK太TM难学了,就做这么一个简单的锥形废了老多精力,还要继续更加努力...掌握更好的学习方法