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的主要内容,如果未能解决你的问题,请参考以下文章

前端框架vue中的keep-alive总结实践

keep open a channel for barges的语法结构如何分析,特别是keep和open.

Vue之keep-alive灵活清除页面缓存

Vue keep-alive防止重复渲染DOM总结

利用Vue中keep-alive,快速实现页面缓存

keep-alive