Houdini

「Houdini」湖边小屋part6 贴花贴花贴花

by Ayse, 2022-03-01


Houdini

headfile.png

最近很麻,图形学的codingdebug真的是让人无所适从,反倒是houdini感觉比那些要舒服很多,不知不觉模型的精细度就上去了。不过一开始打算在七天左右完成的湖边小屋制作和拆解居然拖到了一个月,虽然中途断断续续还搞了很多别的。本篇文章涉及到了很多很有意思的操作方法,同时也涉及到一些uv的处理


1.png 现在的模型真情实感让人身心愉悦。

本篇文章主要讲述

(1)塔、天窗模型的制作,以及塔的分配 (2)墙体横撑的建立分块 (3)墙体花纹的建立


(1)塔、天窗模型的制作

2.png

塔分为塔身和塔顶两个部分,塔身就是非常麻瓜的bevel然后extrude,然后选组再extrude,没什么技术含量,其他软件更快可以手动完成,在这里做的好处是高度更加方便更改,塔楼的形状也可以自定义(which我并没有做)。塔顶铺瓦片的部分可以跳转我的上一篇专栏文章 旋转。后续还加入了一个梁的结构和一个垫在下面的cone。 3.png 显然我的方法并不是很好,cone是原本的cone挤出形成的,不知道为什么加入了bevel之后布线就会乱七八糟,不过我目前并不打算解决这个问题,能看就行。至于这个提取结构线的部分涉及到了一个全新的操作方法,提取边缘形成新的polygon,这个之前并没有使用过。最后加上一个polywire就行,不过这个节点总是喜欢把正方形的管子偏转45度以至于很多时候不是特别实用,当然可以通过bevel增加面数实现类似的正方形,所以如果要制作正方形的管子,我之前的办法是用线内外偏移然后造两个面出来extrude,要是之后发现了更好的方法就贴到常更帖上。 4.png

选点方面作者是让塔可以在一层屋顶和二层的重合处以及二层屋顶的内部任意点上,但是凭借我的建筑学常识我觉得,二层屋顶加上这个真的难以言说,所以只用了一个老办法点云检测然后输入一个整体的bbox的YMAX控制一下塔楼高度就结束了。 5.png


(2)墙体分块

6.png

先复习一下之前的结果,以及看看最终的效果,对于普遍bodybase的处理办法节点图,分而治之 7.png

而进一步的,上次在介绍功能分配和装门窗的时候只提到了思路,其实就是这张图的右侧和上侧部分,完成了一个shut,窗的定位和布尔切割。后面的步骤开始于wallpattern的包, 8.png

这些节点里干了两件事儿, 1、找到中心点和木横梁 2、找到border 3、随机mark pattern

  • 首先是先撒了两个点,然后要是这两个点太高或者太低或者太近(其实有relax iteration,理论上不会太近)就删掉,然后这个随机拿到的点就是中间的木横梁的位置,作者是通过divide拆开墙面,找到这个体的bbox看看有没有把这个点包括进去,包括了就选出来peak当横梁。而面本身则从此切成两半,左边的循环就是通过左侧的in获取一个点作为clip的centroid,方便标记不同的pattern。
  • 然后是divide切横纵切出一定宽度的细分,挑出来边缘的,用sort和grouprange是最保险的方法选头和选尾。
  • 除了border自带pattern特性外,通过随机数给面赋予horizon 、 vertical 、scales三种花纹,后续备用。

很奇怪的是我的divide节点出现了一些bug,但是我在网上并没有搜到和我一样的情况 9.png 一旦我在divide中出现了高于原长度的情况,就会有一些面出现切割问题,并且看起来是倒数第二个面出现了一些错误,如果加一点点y轴的偏移似乎又好了(不在整数的时候)所以我选择了在y轴加入一点点的offset让上下边框窄一点然后后续选出两个面divide合并在一起。


(3)墙体花纹的建立

终于来到了本篇文章的重头戏,加上花纹。顺便提一嘴,我目前工程的状态在这里是循环套循环套循环,这样最大的缺点是不太好debug,每次都需要分层重新去开single pass才可以找到合适的debug过程,不过这也是push我一次性把代码写好吧

1、horizontal 和 vertical 的墙体花纹

首先把scale和非scale的分开处置。先讲非scale的, 10.png 把borde提取并无视之后,沿着切线方向(X或者Z)移动一个noise,然后通过uv在世界空间到uv空间的映射把uv贴上去,uv的映射是先加入一个vector的uv值,然后通过relbox的坐标去设定uv的值。下面是两次计算的核心代码

     if(abs(n.x)> abs(n.z))
        {
            float num = rint(pos.z*100);
            rand_offset = fit(rand(num+prim("../in","seed",0)),0,1,-max_offset,max_offset);
            new_pos = {0,0,1} * rand_offset;
        }
        else
        {
            float num = rint(pos.x*100);
            rand_offset = fit(rand(num+prim("../in","seed",0)),0,1,-max_offset,max_offset);
            new_pos = {1,0,0} * rand_offset;
        }
        setpointattrib(0, "P", i, new_pos, "add");
////////

    float uvs_height = ws_height / uvspace[1];
    float uvs_width = ws_width / uvspace[0];

    float free_uvs_height = 1 - uvs_height;
    float free_uvs_width = 1 - uvs_width;
    int primnum = vertexprim(0, @vtxnum);
    float rand_u = fit(rand(seed + primnum),0,1,0,free_uvs_width);
    float rand_v = fit(rand(seed+45 + primnum),0,1,0,free_uvs_height);
    vector rel_bbx = relbbox(0, @P);

    vector rel_bbx = relbbox(0, @P);
    vector2 p_relpos;
    if(@N.x!=0)
        p_relpos = set(rel_bbx.z, rel_bbx.y);
    else
        p_relpos = set(rel_bbx.x, rel_bbx.y);
    vector2 uv_pos = set(p_relpos.x*uvs_width + rand_u, p_relpos.y*uvs_height + rand_v);

    v@uv = uv_pos;

![11.png][14]

然后就是先细分然后前后随机凸起一下我们的面,然后把边缘点选出来,重新对内部点进行一些jitter操作(vop节点内部),右边的循环是重新做法线的,让点都在内部平面上乱动,两个transfer都把N和cutout(边缘点)选出来然后进行操作了。这一步参考的是冬青大佬的做法,原作者在这里的操作要麻烦很多。得到了一个不错的噪声结果后,extrude就可以。

2、scales 的墙体花纹 12.png

这个要更复杂一些,原作者不知道怎么样就把模型重新开整了,一切都处于归零状态,我的模型还是在原处的。所以处理起来要更加麻烦一些。总体的思路上是把烟来的面网格化然后做一点偏移然后再网格化。二者切开就是类似这样的效果了。

下面讲的是cutscales包里的节点,这个是基于冬青大佬的方法的改进版本,因为似乎用他那样的表格做法还是会遇到问题。 13.png

如果我们直接用中心点切割,在模型的这些地方会出现问题,因为没有办法对应到真正的单元格中心点,那么我们需要采用一种完全自己新做的更大的网格(或者是原有网格的完整部分),来对齐原有的网格(matchsize),上面的节点基本和冬青大佬的节点一致,然后我后续修改多了一版本。解决假如所有网格都不是完整的情况 14.png 基本就是自己去建立一个新网格,其中,网格的起始点要选在中心几个点的位置,所以center的坐标放在point("../find_snap_grid/",0,"P",0)+1/7*prim("../measure1/",0,"N",2),同时要旋转到现有平面,乘以一个n.x * 90就可以,然后polyexpand回收一点,用完全吻合原有方格的bbox去选中点就可以了。 15.png

在这之后就是加入一个顶点色把法线都指向中心来控制一个noise,然后根据法线旋转一下uv project的方向,自动layout一下然后挤出就可以了。 16.png


看起来还不错!本章节到此结束。

作者: Ayse

2024 © typecho & elise