3D折纸效果怎么实现?
Cocos Creator 3.0 演示与实现。
效果
效果预览:
视频预览(视频号[白玉无冰]):
https://www.bilibili.com/video/BV11U4y157cz
前言
开始讲解前,先扯些其他的,如果大伙想看原理讲解,可跳过这一节,直奔原理。
首先,感谢大家的观看,感谢大家的点赞支持,感谢老板们的赞赏支持,非常感谢。
写了这么多年的文章了,很多时候都是单向在写东西。白玉无冰更希望的是多向的交流,碰撞出更多的火花。
就像3D挖洞效果那样,qq群内集体讨论出一个3D挖洞效果 像 Cocos Star Meeting
广州场那样,每个人都上台分享自己的故事亦像水排序的实现那样,有人在群中指出动画方案,也有人在评论讨论实现中的问题 。。。
我经常不善言表,但大家一起讨论的时候,心中会荡起一点澎湃,一点激动,一点感动。
虽然很多问题我答不上,各类平台的sdk
,native
等我都不熟悉,但群里时常有人能答上。
不过,还是希望大家能多思考,利用好搜索引擎,能解决部分问题。
打印日志,断点调试,也能解答一些疑惑。
目前来说,白玉无冰对数学和渲染相关的比较感兴趣,3D相关的也在起步研究阶段,欢迎一起探讨。
数学真的很重要,以向量为例,点乘判断前后,叉乘判断左右。
顺便整理一些有关向量的实例,希望对大家有所帮助。
2D折纸
四元数与旋转
使用 mesh 实现多边形裁剪图片
反复横跳的瞄准线!
浅析射线检测
可能上面的文章较对应的引擎版本比较老,但重要的是思路思想,希望大家融会贯通,不限于引擎,能实现自己想要的效果。
接下来进入本篇的主题吧。
实现
总体思路,细分化网格,旋转网格点。
接下来分以下几步走讲解。
初始化平铺网格 射线检测确定触摸点,触摸轴 向量叉乘确定要旋转的网格点 旋转网格点
平铺网格
只要网格点足够细化,对网格点操作后,折痕就越光滑。
遨游引擎源码(或d.ts
)后,找到了可以细分化平面的方法。
// 创建网格点
this._gemotry = primitives.plane({ width: 10, length: 10, widthSegments: 99, lengthSegments: 99 });
// 创建mesh,并转给渲染器
this.meshRenderer.mesh = utils.createMesh(this._gemotry, this._mesh);
射线检测
从摄像机发出一条射线,检测mesh
,返回距离,再根据射线检测起点和方向求出触摸点。
private onTouchStart(touch: Touch, event: EventTouch) {
//todo 坐标转换,目前 meshRenderer 在原点
const point = touch.getLocation();
// 从摄像机发起射线
this.cameraCom.screenPointToRay(point.x, point.y, this._ray);
// 获取射线距离
const minDis = geometry.intersect.rayMesh(this._ray, this._mesh, deOpt)
if (minDis) {
// 求得射线的终点
const pos = Vec3.add(_temp_v3, this._ray.o, Vec3.multiplyScalar(_temp_v3, this._ray.d, minDis));
if (event.type === SystemEventType.TOUCH_START) {
this._axiStart = v3(pos);
} else if (event.type === SystemEventType.TOUCH_END) {
this._axiEnd = v3(pos);
// 计算需要旋转的点
this.calculateSelected();
}
}
}
网格点分类
使用向量叉乘判断网格点在触摸轴的左边还是右边。
private calculateSelected() {
const axiStart = this._axiStart;
const axiEnd = this._axiEnd;
this._selectedPos.clear();
this._gemotry.positions.forEach((v, i, arr) => {
if (i % 3 === 0) {
//网格点
const target = _temp_v3_1.set(arr[i], arr[i + 1], arr[i + 2]);
//触摸向量
const axi = Vec3.subtract(_temp_v3, axiEnd, axiStart).normalize();
//待判断向量
const targetVector = Vec3.subtract(_temp_v3_2, target, axiStart);
if (Vec3.cross(_temp_v3_3, axi, targetVector).y > 0) {
//取其中一边
this._selectedPos.set(i, [arr[i], arr[i + 1], arr[i + 2]]);
}
}
})
}
旋转网格点
是四元数与旋转中绕轴旋转的一个实例。
// 单个点处理
private rotatePos(target: Vec3, axiStart: Vec3, axiEnd: Vec3, rad: number) {
// 旋转轴
const axi = Vec3.subtract(_temp_v3, axiEnd, axiStart).normalize();
// 构造起始向量
const targetVector = Vec3.subtract(_temp_v3_2, target, axiStart);
// 构造四元数
Quat.fromAxisAngle(_temp_quat, axi, rad);
// 旋转向量
Vec3.transformQuat(targetVector, targetVector, _temp_quat);
// 计算旋转点
Vec3.add(target, axiStart, targetVector);
return target;
}
视频整合详解
视频讲解(视频号白玉无冰
,各位老板们走过路过点个关注
,后续会录些视频讲讲一些技术点的理解):
https://www.bilibili.com/video/BV1jw411o7bL
大家帮忙在视频号点个关注,白玉无冰想试试500个关注后,加个认证标志✅。
小结
完整代码工程:https://store.cocos.com/app/detail/2844
以上为白玉无冰使用 Cocos Creator 3.0.0
实现 "折纸3D效果!"
的技术分享。
希望大家多多讨论,碰撞出新思想!
更多
点击“阅读原文”查看精选导航
“点赞“ ”在看” 鼓励一下