Creator 3.0 折纸效果!超赞

2024-02-25 05:10
文章标签 效果 creator 3.0 超赞 折纸

本文主要是介绍Creator 3.0 折纸效果!超赞,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

效果

折纸效果

源码链接:http://store.cocos.com/app/detail/2844

实现

整体思路

思路遵循以下几步

  • 初始化一个多边形。

  • 折叠后分割成两个多边形。

  • 如果需要继续分割,对场上的所有多边形进行折叠,折叠出新的多边形的层级正好与原来的相反。

整体思路

所以,所有的计算和渲染都可以转换成对一个多边形的操作。

为了简化计算,我们约定初始化的多边形为凸多边形。这么做有几个好处。

  • 折叠后生成的仍是凸多边形,并且对于每个多边形只会折叠出两个凸多边形

  • 渲染时,分割凸多边形为三角形特别方便,即能快速计算出顶点索引

计算

主要分为三块

  • 多边形分割

  • 线线交点

  • 轴对称

分割

观察触摸方向和多边形各个点的关系。

可以发现,触摸方向触摸方向中点指向多边形顶点 的夹角决定了分割后的多边形的点。

分割
  • 当夹角大于90度时,该顶点正好是折叠多边形的顶点。

  • 当夹角等于90度时,该顶点是两个多边形的顶点。

  • 当夹角小于90度时,该顶点是底部多边形的顶点。

向量间的点积正好可以帮助我们判断夹角问题。

const dotValue = temp_v2_vector.dot(temp_v2_vector_3)
if (Math.abs(dotValue) === 0) {// 刚好在点上      
} else if (dotValue > 0) {// 在前面  
} else {// 在后面
}

交点

当被分割的多边形相邻两点与触摸方向的夹角不同时(属于两个多边形的点),需要计算触摸向量的垂直线与该线段的交点。

交点

直线上的一点可以用点和向量表示。

直线上的点

把两直线的点表达式结合,再运用克莱姆法则(Cramer's Rule)求出交点。

克莱姆法则
function linelinePoint(p1: Vec2, p1Dir: Vec2, p2: Vec2, p2Dir: Vec2) {const a1 = p1Dir.x, b1 = -p2Dir.x, c1 = p2.x - p1.xconst a2 = p1Dir.y, b2 = -p2Dir.y, c2 = p2.y - p1.yconst d = a1 * b2 - a2 * b1,d1 = c1 * b2 - c2 * b1,d2 = a1 * c2 - c1 * a2const t1 = d1 / d, t2 = d2 / dreturn [t1, t2]
}

这里计算的是比例t,这个t不仅可以用来求出顶点坐标,也可以求出相交的纹理坐标。

const posSpilt = Vec2(pos.x + dir.x * t1, pos.y + dir.y * t1)
const uvSpilt = Vec2(uv.x + uvdir.x * t1, uv.y + uvdir.y * t1)

对称点

折叠多边形的顶点正好是原多边形顶点关于触摸垂直轴对称的点。

折叠点

求对称点同样可以运用向量计算。

  1. 求出该顶点与中点的向量

  2. 求出该点在触摸方向的单位向量的投影(点乘),这正好是距离的一半

  3. 求出对称点坐标(距离乘方向向量+起始点坐标)

求对称点
Vec2.subtract(temp_v2_vector_4, temp_v2_pos, pos)
const dotLength = temp_v2_vector_4.dot(temp_v2_vector) * 2
temp_v2_pos_2.set((pos.x + temp_v2_vector.x * dotLength), pos.y + temp_v2_vector.y * dotLength)

渲染

渲染一个图形一般是由三角形组成。

对于凸多边形,分割三角形就比较简单。选取其中一个顶点,和其他顶点连接,就可以把多边形分割成三角形。

凸多边形分割

渲染一个凸多边形采用Assembler的方式组装顶点数据。

分为以下几步实现:

  1. 将引擎中的Sprite-simple组装器拷贝出来,作为自己的组装器模板。

  2. 新建一个类继承Sprite,并设置它的组装器到自己的组装器

  3. 创建变量顶点数组,纹理数组。

  4. 编写组装器逻辑

直接看看代码吧:D

凸多边形的类。

// 仅限凸多边形
@ccclass('PolygonSprite')
export class PolygonSprite extends Sprite {@property({ type: [Vec2] })protected _vertices: Vec2[] = [new Vec2(-100, -100), new Vec2(100, -100), new Vec2(100, 100), new Vec2(-100, 100)];// 省略部分代码@property({ type: [Vec2] })protected _uvs: Vec2[] = [new Vec2(0, 0), new Vec2(1, 0), new Vec2(1, 1), new Vec2(0, 1)];// 省略部分代码protected _flushAssembler() {//指向自定义的组装器let assembler = polygonAssembler;if (this._assembler !== assembler) {this.destroyRenderData();this._assembler = assembler;}// 省略部分代码}
}

接下来看组装器内修改部分。

处理顶点数据

// 保存顶点数据
updateVertexData(sprite: PolygonSprite) {//中间变量const renderData = sprite.renderData;if (!renderData) {return;}renderData.vertexCount = renderData.dataLength = sprite.vertices.length// 三角形数量 = 顶点数 - 2// 索引数量 = 三角形数量X3renderData.indicesCount = (renderData.vertexCount - 2) * 3renderData.vertDirty = false;for (let i = 0; i < sprite.vertices.length; ++i) {const xy = sprite.vertices[i];renderData.data[i].x = xy.xrenderData.data[i].y = xy.y}
},

缓存UV坐标,我们定义的纹理坐标是归一化到0-1,在更新数据时再根据实际的纹理坐标(合图)进行转换。

updateUvs(sprite: PolygonSprite) {const renderData = sprite.renderData!;//实际uvconst uv = sprite.spriteFrame!.uv;// 左 下 上 右 const l = uv[0], b = uv[1], t = uv[7], r = uv[6]for (let i = 0; i < sprite.uvs.length; ++i) {const uvs = sprite.uvs[i];renderData.data[i].u = l + (r - l) * uvs.xrenderData.data[i].v = b + (t - b) * uvs.y}renderData.uvDirty = false;
},

填充数据修改,顶点索引就从第一个点开始连接到各个顶点的三角形。

fillBuffers(sprite: PolygonSprite, renderer: any) {//省略代码// 填充顶点for (let i = 0; i < renderData.vertexCount; ++i) {const vert = renderData.data[i];// 计算世界坐标vBuf![vertexOffset++] = a * vert.x + c * vert.y + tx;vBuf![vertexOffset++] = b * vert.x + d * vert.y + ty;vBuf![vertexOffset++] = vert.z;// 填充uvvBuf![vertexOffset++] = vert.u;vBuf![vertexOffset++] = vert.v;Color.toArray(vBuf!, sprite.color, vertexOffset);vertexOffset += 4;}// 填充索引for (let i = 0; i < sprite.vertices.length - 2; ++i) {const start = i;iBuf![indicesOffset++] = vertexId;iBuf![indicesOffset++] = start + 1 + vertexId;iBuf![indicesOffset++] = start + 2 + vertexId;}
},

小结

实现折叠效果可以将问题分解成处理一个多边形的问题,并用assembler实现合批渲染。

以上为白玉无冰使用 Cocos Creator 3.0.0 实现 "折纸效果!" 的技术分享。欢迎三连(点赞/在看/留言/分享)支持!

告诉大家一个好消息,Cocos Store 五月挑战赛

只要报名上传作品

审核通过就有机会获得 Cocos 周边!

请注意!!!推荐好友上架成功,推荐者也可以获得的哦!而且520也要到了,后面的六一儿童节、端午节、618......各种题材的游戏DMEO、插件、资源都有机会获得官方推荐,机会难得,快来报名吧!

报名链接:https://www.cocos.com/store-activity

欢迎加晓衡微信,愿我们共同成长!

这篇关于Creator 3.0 折纸效果!超赞的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/744486

相关文章

4B参数秒杀GPT-3.5:MiniCPM 3.0惊艳登场!

​ 面壁智能 在 AI 的世界里,总有那么几个时刻让人惊叹不已。面壁智能推出的 MiniCPM 3.0,这个仅有4B参数的"小钢炮",正在以惊人的实力挑战着 GPT-3.5 这个曾经的AI巨人。 MiniCPM 3.0 MiniCPM 3.0 MiniCPM 3.0 目前的主要功能有: 长上下文功能:原生支持 32k 上下文长度,性能完美。我们引入了

防近视护眼台灯什么牌子好?五款防近视效果好的护眼台灯推荐

在家里,灯具是属于离不开的家具,每个大大小小的地方都需要的照亮,所以一盏好灯是必不可少的,每个发挥着作用。而护眼台灯就起了一个保护眼睛,预防近视的作用。可以保护我们在学习,阅读的时候提供一个合适的光线环境,保护我们的眼睛。防近视护眼台灯什么牌子好?那我们怎么选择一个优秀的护眼台灯也是很重要,才能起到最大的护眼效果。下面五款防近视效果好的护眼台灯推荐: 一:六个推荐防近视效果好的护眼台灯的

Cmake之3.0版本重要特性及用法实例(十三)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧

【Godot4.3】多边形的斜线填充效果基础实现

概述 图案(Pattern)填充是一个非常常见的效果。其中又以斜线填充最为简单。本篇就探讨在Godot4.3中如何使用Geometry2D和CanvasItem的绘图函数实现斜线填充效果。 基础思路 Geometry2D类提供了多边形和多边形以及多边形与折线的布尔运算。按照自然的思路,多边形的斜线填充应该属于“多边形与折线的布尔运算”范畴。 第一个问题是如何获得斜线,这条斜线应该满足什么样

在 Qt Creator 中,输入 /** 并按下Enter可以自动生成 Doxygen 风格的注释

在 Qt Creator 中,当你输入 /** 时,确实会自动补全标准的 Doxygen 风格注释。这是因为 Qt Creator 支持 Doxygen 以及类似的文档注释风格,并且提供了代码自动补全功能。 以下是如何在 Qt Creator 中使用和显示这些注释标记的步骤: 1. 自动补全 Doxygen 风格注释 在 Qt Creator 中,你可以这样操作: 在你的代码中,将光标放在

UniApp实现漂亮的音乐歌词滚动播放效果

在现代的音乐播放应用中,歌词的展示和滚动播放已经成为了一个非常常见的功能。今天,我们将通过UniApp来实现一个漂亮的歌词滚动播放功能。我们将使用UniApp提供的组件和API来完成这个任务。 页面结构 在页面的模板部分,我们需要创建一个音频播放器和歌词展示区域。使用<scroll-view>组件来实现歌词的滚动效果。 <template><view class="audio-co

Nuxt3入门:过渡效果(第5节)

你好同学,我是沐爸,欢迎点赞、收藏、评论和关注。 Nuxt 利用 Vue 的 <Transition> 组件在页面和布局之间应用过渡效果。 一、页面过渡效果 你可以启用页面过渡效果,以便对所有页面应用自动过渡效果。 nuxt.config.js export default defineNuxtConfig({app: {pageTransition: {name: 'fade',mode

Differential Diffusion,赋予每个像素它应有的力量,以及在comfyui中的测试效果

🥽原论文要点 首先是原论文地址:https://differential-diffusion.github.io/paper.pdf 其次是git介绍地址:GitHub - exx8/differential-diffusion 感兴趣的朋友们可以自行阅读。 首先,论文开篇就给了一个例子: 我们的方法根据给定的图片和文本提示,以不同的程度改变图像的不同区域。这种可控性允许我们再现

【Unity小技巧】URP管线遮挡高亮效果

前言 在URP渲染管线环境下实现物体遮挡高亮显示效果,效果如下: Unity URP遮挡高亮 实现步骤 创建层级,为需要显示高亮效果的物体添加层级,比如Player 创建一个材质球,也就是高亮效果显示的材质球找到Universal Renderer Data Assets 4.在Assets上添加两个Render Objects组件 第一个做如下三处设置 指定遮挡层级指