Page's Personal Website

Apex nvparameterized

2019-09-29

[TOC]

疑问

在看Apex的时候会给破碎模型设置参数,形式如下:

	NvParameterized::setParamBool(*actorDesc, "dynamic", false);
	NvParameterized::setParamBool(*actorDesc, "formExtendedStructures", true);
	NvParameterized::setParamF32(*actorDesc, "supportStrength", 1.9f);
	
	NvParameterized::setParamF32(*actorDesc, "defaultBehaviorGroup.damageThreshold", 5.0f);

很疑惑,为什么要这么做,以及怎么做的?

结构

怎么做到的呢?根据变量的结构,构建一个简单的树形结构Lookup Tree,在此基础上,构建一个字符串对应的树形结构Definition Tree。两颗树形结构的关系一致,根据这个在Definition Tree中找到某个变量的偏移值,就可以在Lookup Tree上找到真正的地址,然后根据类型操作这个地址即可。

Lookup Tree

变量本身的一个树形结构,主要是记录一下某个变量是某个结构体的成员这样的父子关系。这个关系给Definition Tree提供了基础。如下图所示: variable-tree

Definition Tree

用变量的结构构造一个字符串对应的树形结构,如下图所示:

string-tree

小结

  • 两棵树的匹配关键是:定义的Children的关系树结构需要完全一样,主要是通过字符串在ParamDefTable中找到offset,然后用这个offset到ParamLookupTable中找到变量的地址以及类型,然后读写这个变量
  • 拿到了指针和类型之后,就把指针强制转换为指定类型,然后设置值了
	Type *Var = (Type *)((char *)ptr);
	*Var = val;
  • 两棵树最大的不同是,Lookup Tree不需要parent的指针关系

创建和使用

创建-构建树

参考存储结构,创建树的时候其实是比较硬核的代码,手K!

  • buildTree
	void DestructibleActorParam::buildTree(void)
	// 定义父节点
	NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[184];
	ParamDef->init("simulationFilterData", TYPE_STRUCT, "P3FilterData", true);
	// 定义子节点
	NvParameterized::DefinitionImpl* ParamDef = &ParamDefTable[185];
	ParamDef->init("word0", TYPE_U32, NULL, true);
	// 设置父子关系
	static Definition* Children[4];
	Children[0] = PDEF_PTR(185);
	Children[1] = PDEF_PTR(186);
	Children[2] = PDEF_PTR(187);
	Children[3] = PDEF_PTR(188);
	
	ParamDefTable[184].setChildren(Children, 4);

使用-查找树

  • 查找 findParam 查找的时候会根据longName找到子节点的地址,最主要是拿到offset,因为这个offset是变量树找指针位置用的,为关键点!

  • handle.index 这个接口是在findParam的时候算出来节点关系,某个子节点在父节点中children数组里面的索引。这个就是用到树的结构,然后查找

总结

  • 这个方式通用性我觉得并不是很强,因为树都是硬编码的。对于用户只是读写来说还好,就只有这么多参数,你就用吧;但是对于其他程序员来使用这个系统的话会很受束缚
  • 树的查找,这里并没有用到二叉树或者BT之类的查找,就把所有的children遍历一遍,应该是量不大,所以随便

Similar Posts

Comments