Non-sopsolver keep camera's geometry
Posted gearslogy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Non-sopsolver keep camera's geometry相关的知识,希望对你有一定的参考价值。
这幅图可以清楚的看到摄像机运动的轨迹,产生的能量,一看都是向左旋转,并且带有一些位移。
一:非sopsolver法
经常遇到做特效只想留摄像机看到的部分,但是摄像机一直会运动。一般做法就是用sopsolver来记录摄像机运动看到的区域,删除看不到的区域。
但是还有一种方法直接从原理入手。
1,先记录摄像机的worldtransform在每一个帧上。此时成为了一个python的列表
2,记录的camera matrix list应该放入点属性,刚好创建你摄像机key动画的范围点数。摄像机运动100帧,就把这100帧的camera matrices记录到每个点上。每个点带一个4*4 矩阵。
3,开始用for循环获取这些记录点的矩阵。
4,在你的要剔除几何体开始操作,用for循环首先获取每一个点矩阵数据,然后当前几何体的位置转换到摄像机空间。最后转到NDC空间。
初始化:accum 变量
for循环{
4,NDC space应该先将point position转换到摄像机空间,此时已经可以用这个转换后空间来留下摄像机区域。但是这个不太灵活,数据太大。
5,接着转换到摄像机空间,然后再做pespective projection矩阵。
6,做透视除法。转换到ndc space。
7,用ndc space
8,满足ndc剔除条件
accum+=1
or: accum+=0
}
9,accum/= 记录了多少帧。
10,根据accum来删除几何体操作。
python的代码主要获取摄像机所有运动的矩阵,并且 放到 一个点数 刚好等于摄像机运动了多少帧的几何体上。
node = hou.pwd() geo = node.geometry() # Add code to modify contents of geo. # Use drop down menu to select examples. frameStart = node.parm("start").eval() frameEnd = node.parm("end").eval() fps = 24.0 # add detail attribute to save our frame range that is camera key range geo.addAttrib(hou.attribType.Global, "startFrame", frameStart) geo.addAttrib(hou.attribType.Global, "endFrame", frameEnd) # get camera node: camNode = hou.node("/obj/cam1") matrix_list = [] # this is our camera matrix here for frame in range(frameStart,frameEnd+1,1): time = float(frame)/ fps camWorldMatrix = camNode.worldTransformAtTime(time).inverted() # get camera at time! camWorldMatrix = camWorldMatrix.asTuple() matrix_list.append(camWorldMatrix) # add a array attrib in every point, our point is our frame geo.addArrayAttrib(hou.attribType.Point, "mats", hou.attribData.Float, 1) for it in geo.iterPoints(): ptnum = it.number() # get point number , start with 0 it.setAttribValue("mats", matrix_list[ptnum])
attrib_to_hitour_accumulate节点就创建个accum属性:
f@accum = 0;
range_delete节点执行剔除:
// accum the frame range int sf = detail(1, "startFrame"); int ef = detail(1, "endFrame"); int npts = npoints(1); // range loop our points , cal the weight of there camera matrices! for(int i=0; i< npts ; i++) { float mat[]; mat = point(1,"mats", i); matrix mat44 = set(mat); vector camP = @P * mat44; camP = normalize(camP); int condition1 = camP.x < -0.5 || camP.x > 0.5; int condition2 = camP.y < -0.4 || camP.y > 0.3; int condition3 = camP.z > 0; int condition = condition1 || condition2 || condition3 ; if(condition ) { @accum += 0; } else{ @accum += 1; } } @accum = @accum / npts; @Cd = @accum; if(@accum <= 0) { removepoint(geoself(),@ptnum); }
事实上你可以看到我为了简单起见,上面的条件只是用的摄像机空间的位置(normalized),并没有要做ndc。
正常应该按照我上面要转换ndc,再来剔除好点:
snippt代码:
float focal = 50; float aperture = 35.9999; float zoom = focal / aperture; float image_aspect = 1280.0 / 720.0f; float near = 1.0f; float far = 10000.0f; matrix proj = perspective(zoom,image_aspect,1, near,far) ; mat = proj;
二:简单剔除法,以下可以使用sopsolver来做:
houdini也提供了一个直接转换ndc的节点:toNDC(camera, P)但是这个没办法在我们这里面用,因为必须手动实现透视除法:如下。如果你不想直接算出来摄像机区域的话:
v@uv = toNDC("/obj/cam1",@P); if(@uv[0] < -0.1 || @uv[0] > 1.2) { removepoint(geoself(),@ptnum); } if(@uv[1] < -0.1 || @uv[1] > 1.2) { removepoint(geoself(),@ptnum); }
不直接算出来区域,当然也可以用投射这个方法:
if(@uv[0] < -0.1 || @uv[0] > 1.2) { removepoint(geoself(),@ptnum); } if(@uv[1] < -0.1 || @uv[1] > 1.2) { removepoint(geoself(),@ptnum); } if(@uv[2] < 0.3 ) { removepoint(geoself(),@ptnum); }
还有一种简单的方法用vdb生成体积,拿体积判断删除。
以上是关于Non-sopsolver keep camera's geometry的主要内容,如果未能解决你的问题,请参考以下文章