Houdini开发:打开HDK的大门

这篇文章的目标是

        1、编译跑通第一个HDK程序

        2、以最少的代码量编译跑通一个HDK

————————————————————

————————————————————

        HDK(Houdini Development Kit)是Houdini的开发者工具包,我们可以利用它实现一些Houdini功能的拓展,接下来进入正题一,编译并运行第一个HDK程序——SOP_PointWave。

       

我们来到这个目录,找到官方示例SOP_PointWave。

        1、核心文件只有以下两个, 有了他俩我们就能构建一个HDK节点在Houdini里使用。

                SOP_PointWave.h

                SOP_PointWave.C

        2、部分官方示例可以使用Cmake构建文件,博主将不会使用Cmake构建程序,而是使用Houdini Command Line的hcustom命令编译HDK程序,hcustom指令是编译HDK程序的一种方法,详见参考HDK的官方文档:https://www.sidefx.com/docs/hdk/_h_d_k__intro__tools.html

        接下来打开开始菜单找到Houdini Command Line,也就是Houdini内置的命令行窗口。

        

        

        默认工作目录是C盘下,我们通过cd指令来到SOP_PointWave程序的目录下 ,之后输入hcustom指令编译HDK程序(hcustom会自动找到当前目录下对应名称的.h文件)。

        

        完成了上述hcustom命令之后之后,我们可以发现Houdini的document路径下多了一个dso文件夹并且文件夹内多了一个dll文件。

 

 

        博主认为dso表示是.dll文件/.so文件,专门用来放置动态库文件,houdini自身在启动时也会访问这个文件夹的信息,就像otls一样。而中间文件将会在源代码文件的目录下生成,可以删掉。

至此,我们已经完成了我们第一个HDK文件的创建!

我们重启houdini看看到底发生了什么吧,来到sop层级下,发现节点菜单多了一个Point Wave。

 我们试试看把他用到平面上。

        它的所有功能包括参数面板都由SOP_PointWave的h文件和C文件实现。

————————————————————

————————————————————

        接下来我们进入今天的第二阶段,用最少的代码量实现一个控制geometry移动的hdk吧。

        

        首先创建一个空的VS工程,创建一个名为SOP_TestXform的类,并且包含HDK工具包的include路径。

        

准备工作完成,现在,我们来编写.h文件。

        我们想要创建的是一个类似于transform功能的节点,需要继承于SOP_Node,一个最简单的HDK程序由以下5个部分构成:

        1、构造函数(默认规则)

        2、析构函数(默认规则)

        3、myConstructor函数(HDK默认规则)

        4、参数列表成员(HDK默认规则,也就是节点的参数面板)

        5、cookMySop函数(HDK默认规则,也是核心逻辑实现部分)

#include <SOP/SOP_Node.h>

class SOP_TestXform : public SOP_Node
{
public:
	SOP_TestXform(OP_Network* net, const char* name, OP_Operator* op);
	~SOP_TestXform() override;

    //参数列表
	static PRM_Template sTemplateList[];

    //HDK默认规则
	static OP_Node* constructor(OP_Network*, const char*, OP_Operator*);

protected:
    //核心逻辑实现部分
	OP_ERROR cookMySop(OP_Context& context) override;
};

        上述就是一个完整的HDK头文件的表述,OP_前缀表示houdini的operator,还有以后将会接触到的各种前缀类似GA_(Houdini的底层几何库,自houdini12.0取代旧的GB库)、UT_(也就是Util),详见可参考官方文档。

        有参数面板就有参数,我们希望控制geometry上下移动的距离大小,我们为其添加一个成员函数用来获取参数数值。


#include <SOP/SOP_Node.h>

class SOP_TestXform : public SOP_Node
{
public:
	SOP_TestXform(OP_Network* net, const char* name, OP_Operator* op);
	~SOP_TestXform() override;

    //参数列表
	static PRM_Template myTemplateList[];

    //HDK默认规则
	static OP_Node* constructor(OP_Network*, const char*, OP_Operator*);

protected:
    //核心逻辑实现部分
	OP_ERROR cookMySop(OP_Context& context) override;

private:
    //控制移动距离大小
    //fpreal等价于float
    fpreal DISTANCE(fpreal t) { return evalFloat("distance", 0, t); }
};

注意:fpreal等价于float,而它接受的参数t表示当前的帧数。

我们的头文件编写完了,接下来开始编写cpp文件。

首先包含每个HDK都必要的3个头文件以及自身的头文件

#include "SOP_TestXform.h"

#include <OP/OP_AutoLockInputs.h> //必要
#include <OP/OP_OperatorTable.h>  //必要
#include <UT/UT_DSOVersion.h>     //必要

#include <UT/UT_Vector3.h> //我们需要用到点的位置属性,需要包含此头文件

接着是void newSopOperator(OP_OperatorTable* table) 函数,它被声明于SOP_Node,表示我们要开始new一个SOP的节点了哦~

void newSopOperator(OP_OperatorTable* table)
{
	table->addOperator(new OP_Operator(
		"hdk_testxform",				//真正的operator name
		"HDK Test Transform",			//operator label
		SOP_TestXform::constructor,		//HDK的规则
		SOP_TestXform::myTemplateList,	//参数列表
		1,								//最小输入数量
		1,								//最大输入数量
		0));							//CH_LocalVariable 我暂时也没用上
}

接下来定义参数distance

static PRM_Name names[] = {
    //         name            label
    //          ↓                ↓
  	PRM_Name("distance", "Transform Distance"), //PRM表示parameter
};

参数定义好了,接下来当然是参数列表啦

PRM_Template SOP_TestXform::myTemplateList[] = {
    //参数类型是float,参数个数为1个(如果是3则表示向量vector),名字为我们刚刚定义的PRM_Name
	PRM_Template(PRM_FLT_J, 1, &names[0]),
	PRM_Template(), //默认规则,缺少这行空构造直接报错
};

接下来是HDK默认写法,遵守就好,如果有需要可以自行拓展。

OP_Node* SOP_TestXform::constructor(OP_Network* net, const char* name, OP_Operator* op)
{
	return new SOP_TestXform(net, name, op);
}

SOP_TestXform::SOP_TestXform(OP_Network* net, const char* name, OP_Operator* op)
	:SOP_Node(net, name, op)
{
	mySopFlags.setManagesDataIDs(true);
}

SOP_TestXform::~SOP_TestXform() {};

最后是重头戏,cookMySop核心逻辑实现

OP_ERROR SOP_TestXform::cookMySop(OP_Context& context)
{
	//默认锁定我们的输入端信息。
	//---------------------
	OP_AutoLockInputs inputs(this);
	if (inputs.lock(context) >= UT_ERROR_ABORT)
		return error();
	duplicatePointSource(0, context);
	//---------------------


	//用t接收当前的帧数,disntance接收参数值
	//---------------------
	fpreal t = context.getTime();	
	float distance = DISTANCE(t);
	//-----------------------------

	//表示element在attribute array中的偏移量,相当于索引
	GA_Offset ptoff;

	//相当于vex的point层级操作
	//gdp表示geometry detail pointer,也就是当前节点所拥有的几何体信息的指针
	//通过gdp指针我们可以得到所有当前节点的几何体信息,包括point, prim, vertex的位置,法线等
	GA_FOR_ALL_PTOFF(gdp, ptoff)
	{
		//得到每一个点的当前位置
		UT_Vector3 pos = gdp->getPos3(ptoff);
		
		//每个点的y轴加上参数distance的值
		pos.y() += distance;

		//最后通过gdp指针修改点的位置
		gdp->setPos3(ptoff, pos);
	}

	//通过gdp指针绑定所有修改的信息,这一步必不可少
	gdp->bumpAllDataIds();

	return error();
}

至此,头文件和cpp文件都写好了,我们使用houdini命令行编译该文件

果然,dso文件夹中也生成了dll文件 

 接下来重启houdini试试我们的hdk吧!

不出所料,达到了我们想要的效果,那么至此本片文章的目的已经达到,感谢观看! 

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值