豆类是一年生植物吗?的英文翻译一年生植物吗?英语-广州出国留学
2023年3月31日发(作者:爱咋咋的)
Unity3D关于模型变形技术代码实现
也欢迎⼤家转载本篇⽂章。分享知识,造福⼈民,实现我们中华民族伟⼤复兴!
本篇博客给读者介绍关于如何实现模型的变形,在项⽬开发中经常会涉及到模型的变形操作,⽐如如下效果图:
第⼀部分准备⼯作
⾸先在Unity中建⽴⼀个场景,在场景中放置⼀个球体,这个球体可以使⽤Max⼯具建⽴,在球体上放⼏张Materials,效果如下所⽰:
下⾯开始具体实现,创建⼀个新的MeshDeformer脚本来处理变形,就像⽴⽅体球体组件⼀样,它需要⼀个⽹格过滤器来处理。
usingUnityEngine;[RequireComponent(typeof(MeshFilter))]publicclassMeshDeformer:MonoBehaviour{}
将新组件脚本添加到球体上
接下来要读取⽹格数据,要进⾏任何变形,我们需要访问⽹格。⼀旦我们有了⽹格,我们可以提取原始的顶点位置,我们还必须在变形期
间跟踪位移的顶点。
MeshdeformingMe彼岸花的图片 sh;Vector3[]originalVertices,displacedVertices;
实现⽅式,在Start⽅法中获取⽹格及其顶点,并将原始顶点复制到移动的顶点。
voidStart(){deformingMesh=GetComponent
];for(inti=0;i<;i++){displacedVertices[i]=originalVertices[i];}}
我们使⽤的是Start,因此也可以在Awake中⽣成过程⽹格,这⾸先被调⽤,这种⽅法依赖于其他组件在Awake中的执⾏顺序,您还可以
调整脚本执⾏顺序,以强制执⾏谁是第⼀个和最后⼀个。
另外,顶点随着⽹格变形⽽移动,所以我们也要存储每个顶点的速度。
Vector3[]vertexVelocities;voidStart(){…vertexVelocities=newVector3[];}
第⼆部分⽹格变形输⼊
我们需要⼀些⽅法来控制⽹格如何变形,我们将使⽤⽤户输⼊,因此是交互式的,每当⽤户触摸我们的对象时,我们将在这⼀点施加⼒
量。
另外,MeshDeformer组件负责实际的变形,但不关⼼输⼊,我们应该创建⼀个单独的组件来处理⽤户输⼊,给它⼀个可配置的输⼊⼒。
usingUnityEngine;publicclassMeshDeformerInput:MonoBehaviour{publicfloatforce=10f;}
在这⾥要注意,将这个组件附加到相机是最有意义的,我们不应该将其附加到变形⽹格物体,因为场景中可能有多个。
具体操作时,当按住默认⿏标按钮时,我们将处理⽤户的输⼊,所以每当有点击或拖动时,只要⽤户按住。
voidUpdate(){if(seButton(0)){HandleInput();}}
现在我们必须弄清楚⽤户指向的位置,我们通过将相机的光线投射到场景来做到这⼀点,我们将抓住场景的摄像头,
并使⽤它将光标位置转换为光线。
voidHandleInput(){RayinputRay=PointToRay(osition);}
我们使⽤物理引擎投射射线并存储关于它所击中的信息,如果射线与某物相撞,我们可以从被击中的对象中检索出MeshDeformer组件。
RayinputRay=PointToRay(osition);RaycastHithit;if(t(inputRay,outhit)){MeshDeformerdefor
mer=ponent
如果我们射线击中了⼀些东西,那东西有⼀个MeshD七律长征的意思诗意 eformer组件,那么我们可以改变⼀些东西!所以继续在接触点增加变形⼒。
MeshDeformerdeformer=ponent
oint,force);}
当然,假设我们的MeshDeformer组件具有AddDeformingForce⽅法。所以添加这个⽅法。不过,我们还没有做任何变形。⾸先,
只需从主摄像头画⼀个调试线就可以看出光线。
publicvoidAddDeformingForce(Vector3point,floatforce){ne(on,point);}
当⽹状物体被⽤户戳戳和凹陷。这要求接触点附近的顶点被推⼊表⾯。然⽽,变形⼒没有固有的⽅向。它将在各个⽅向均匀地应⽤。这
将导致平坦表⾯上的顶点被推开,⽽不是向内推。
我们可以通过将⼒点拉离表⾯来增加⽅向,稍微偏移已经确保顶点总是被推⼊表⾯,接触点的法线可以⽤作偏移⽅向。
publicfloatforceOffset=0.1f;voidHandleInput(){RayinputRay=PointToRay(osition);RaycastHithit;if(Physics.
Raycast(inputRay,outhit)){MeshDeformerdeformer=ponent
nt+=*forceOffset;ormingForce(point,force);}}}
第三部分基本变形
接下来,ormingForce必须循环遍历所有当前位移的顶点,并将变形⼒单独应⽤于每个顶点。
publicvoidAddDeformingForce(Vector3point,floatforce){for(inti=0;i<;i++){AddForceToVertex(i,point,force);}}voi
dAddForceToVertex(inti,Vector3point,floatforce){}
⽹格因为向每个顶点施加⼒⽽变形,当顶点被推动时,它们获得速度,随着时间的推移,顶点都改变了它们的位置。如果所有顶点都会遇
到完全相同的⼒,整个物体将会移动⽽不改变其形状,但他们没有。
我们需要知道每个顶点的变形⼒的⽅向和距离,两者都可以从从⼒点指向顶点位置的向量导出。
voidAddForceToVertex(inti,Vector3point,floatforce){Vecto江南无所有聊赠一枝春全诗 r3pointToVertex=displacedVertices[i]-point;}
现在可以使⽤反平⽅律找到衰减⼒,将原始⼒除以距离平⽅:
Fv=Fd2Fv=Fd2.
其实,我除以⼀加⼀个平⽅的距离:
Fv=F1+d2Fv=F1+d2.
这保证当距离为零时,⼒处于全强度。否则,⼒将在⼀个距离处的全强度,并且朝着⽆限远射击越接近点。
Vector3pointToVertex=displacedVertices[i]-point;floatattenuatedForce=force/(1f+nitude);
实际上,⼒⾸先被转换为加速度通道:
a=Fma=Fm.然后发现速度的变化:v=atv=at.为了保持简单,我们将忽略质量,就好像它是每个顶点⼀样
v=Ftv=Ft.
Vector3pointToVertex=displacedVertices[i]-point;floatattenuatedForce=force/(1f+nitude);floatvelocity=attenuatedForce
*ime;
那么在这⼀点上,我们有⼀个速度,但还没有⼀个⽅向。我们发现通过归⼀化我们开始的向量,然后我们可以将结果添加到顶点速度。
Vector3po嫁给屠夫夫君(重生) intToVertex=displacedVertices[i]-point;floatattenuatedForce=force/(1f+nitude);floatvelocity=attenuatedForce
*感慨时光流逝的唯美句子 ime;vertexVelocities[i]+=ized*velocity;
现在顶点有速度,我们可以移动它们,添加更新⽅法来处理每个顶点,然后,将替换顶点分配给⽹格,使其实际上发⽣变化。因为⽹格的
形状不再是常数,所以我们也必须重新计算其法线。
voidUpdate(){for(inti=0;i<;i++){UpdateVertex(i);}es=displacedVertices;
calculateNormals();}
另外,更新顶点是调整其位置的问题:
p=vtp=vt.
voidUpdateVertex(inti){Vector3velocity=vertexVelocities[i];displacedVertices[i]+=velocity*ime;}
⼀旦我们向他们施加⼀些⼒量,顶点现在开始移动。但他们不停⽌。它们保持移动,物体的原始形状将丢失。现在让对象反弹回原来的形
状。
真实物体是坚实的,并在变形时被压缩和拉伸。他们抵制这种变形。他们也可以在不受⼲扰的情况下恢复原状。
它们只是⼀个描述表⾯的顶点的集合,我们不能⽤这个进⾏现实的物理模拟。但这不是问题,我们真正需要的是⼀些看起来很可信的东
西。
我们跟踪每个顶点的原始位置和变形位置,想象⼀下,我们在每个顶点的两个版本之间连接弹簧。每当变形的顶点离开原稿时,弹簧就会
拉回来。变形顶点越远,弹簧的拉⼒越强。
我们可以直接使⽤位移⽮量作为速度调节,乘以可配置的弹簧⼒。这很简单,看起来不错。每次顶点更新时,我们都会这样做。
publicfloatspringForce=20f;voidUpdateVertex(inti){Vector3velocity=vertexVelocities[i];Vector3displacement=displacedVertices[i]-originalVer
tices[i];velocity-=displacement*springForce*ime;vertexVelocities[i]=velocity;displacedVertices[i]+=velocity*ime;}
我们的顶点现在可以抵抗变形并跳回到原来的位置。但是他们超越并保持反弹,没有结束。发⽣这种情况是因为弹簧
在顶点⾃⾝修正时保持拉动,从⽽提⾼其速度,它回落太远后才减速。
我们可以通过不断降低顶点来防⽌这种永恒的振荡,这种阻尼效果是电阻,阻⼒,惯性等的替代。这是⼀个随着时间
的推移降低速度的简单因素:
vd=v(1−dt)vd=v(1-dt).
它的压⼒越⾼,物品的弹性越少,物体的出现越慢。
publicfloatdamping=5f;voidUpdateVertex(inti){Vector3velocity=vertexVelocities[i];Vector3displacement=displacedVertices[i]-originalVertices
[i];velocity-=displacement*springForce*ime;velocity*=1f-damping*ime;vertexVelocities[i]=velocity;displacedVertices[i
]+=velocity*ime;}
我们的⽹格变形现在完全正常,除⾮我们转换对象。我们的所有计算都在本地执⾏。继续前进,移动或旋转我们的球体。您将看到变形⼒
将不正确地应⽤。
我们必须补偿对象的转换,我们通过将变形⼒从世界空间的位置转换为局部空间来实现。
publicvoidAddDeformingForce(Vector3point,floatforce){point=eTransformPoi汉字偏旁部首大全 nt(point);for(inti=0;i<;
i++){AddForceToVertex(i,point,force);}}
⼒量现在应⽤在正确的地⽅,均匀地将球体向上或向下缩放,你会注意到变形量相同的量,这不正确。⼩⽽⼤的物体应该接受相同的物
理学。
floatuniformScale=1f;voidUpdate(){uniformScale=cale.x;…}
现在通过使⽤统⼀⽐例缩放pointToVertex向量来修复AddForceToVertex,这确保我们使⽤正确的距离。
voidAddForceToVertex(inti,Vector3point,floatforce){Vector3pointToVertex=displacedVertices[i]-point;pointToVertex*=uniformScale;floatatt
enuatedForce=force/(1f+nitude);floatvelocity=attenuatedForce*ime;vertexVelocities[i]+=
alized*velocity;}
另外,对UpdateVertex中的位移执⾏相同操作,现在我们的速度是正确的。
voidUpdateVertex(inti){Vector3velocity=vertexVelocities[i];Vector3displacement=displacedVertices[i]-originalVertices[i];displacement*=unifor
mScale;velocity-=displacement*springForce*ime;velocity*=1f-damping*ime;vertexVelocities[i]=velocity;displacedVer
tices[i]+=velocity*ime;}
然⽽,我们的速度现在对于没有缩放的对象是正确的,由于我们的对象实际上是缩放的,所以我们也必须调整顶点运动。这次我们必须分
⽽不是乘。
displacedVertices[i]+=velocity*(ime/uniformScale);
最后,在任何位置,旋转和均匀刻度上⼯作的变形⽹格,请记住,这是⼀个简单⽽相对便宜的视觉效果。它不是⼀个软体物理模拟。物体
的碰撞物不改变,所以物理引擎不知道对象的感知形状。
给我⽼师的⼈⼯智能教程打call!
更多推荐
vertices是什么意思tices在线翻译读音例
发布评论