目录
想法
在三维开放世界里记笔记,你听说过吗?
我们记笔记有一维的记事本、typora等文本编辑器,Word 也算。我们只能像说话、如绳结记事一样记录。后来有了思维导图,让我们能在二维平面内记录笔记,给我们一个平面,我们能使用更加丰富的联系结构将笔记容纳其中,平铺来看,不仅在【单位注意力】里面能注意到更多信息,而且能让我们心里快速索引某区块的知识、更扎实的记住很多信息。
后来,我盯着我屋子里,那为了辅助记单词,而贴的满墙、满瓷砖的单词卡片,以及那些自己经常去走的地方的单词卡片,我在想,为什么不试试搞一个程序,在三维空间里写字呢?
↑ 其中一个笔记墙
在三维世界里记笔记。其实就是对我们日常生活中,想有更大的私人空间、更丰富的世界的愿望延伸,我们无法实现在更多的地方,贴上我们的笔记。我们每天即便三点一线,住处、食堂、办公桌/课桌,路线简单到极致,但我们经历的空间,如果全是我们私人的,我们使用大大小小又有创意的文字,将其按照我们喜欢的方式填满,人头到地方,直接可阅读,一万本红楼梦也填不满。而且我们还能随时"被反哺",享受知识的复利、亦或记牢我们的知识。
三维更符合我们亿万年来,进化的选择。我们大脑对三维更感兴趣,尤其是密密麻麻的商业小街、错综复杂的公园,看到那些构造复杂的建筑,我们也会心里萌生巨大的探索欲。即使我们将记忆放到想象中的三维世界里,也会将事物记的更牢、更快、更生动。比如人们发明的记忆法 ---- 记忆宫殿,比如我们大脑能在极短时间内,想象到某个小角落里,曾经目睹过某些事情。
然后,为了实现这个愿望,我就学习了 WebGL ,想创造一个属于自己的世界,然后构造自己的真正意义上更随心所欲的知识宫殿,于是研究了大半个月,我做出了一个粗糙的程序。它远远不是最终版,但它起码实现了一二点儿。
实现
就是《赛博城寨》。
地址在此:https://git.ccgxk.com/myWorkSpace/webgl_show/cyber_city/cbcity.html
我使用伪随机数(保证建筑每次运行都一样),生成了一个巨大的奇葩建筑,1000 米长,1000 米宽,50米高,外形借鉴了香港市的九龙城寨 😄 ,由 1 万个大小不一、颜色各异的方块儿组成,十分巨大,满足人们探索欲。私人空间巨大,远远超越人类史上所有的建筑大小。
它很像一个开放世界的探索游戏,但很遗憾,它是一个笔记工具,反正我是这么定义的。它的使用办法,就是使用鼠标左键单击某个方块的面,然后就可以在那个面上"刻上"自己的字。
当然最最重要的是,它可以下载存档,存档是 json 格式的,很容易提取自己的数据!程序里的笔记也是实时备份到浏览器里的,防止意外丢失的一个小保险。
它其实更适合写一个游戏对吧,局域网互联网联机一群小伙伴,在这个城市里面相互扔炸弹.....
它只是一个阶段性的实验产品,阴影、光照等更丰富的效果目前还在调试,而且说实话,我也觉得这个建筑,并不适合去做笔记,因为太太太太复杂了~
但它代表的是一种概念。未来,我会使用一些能让我们自己设计的建筑程序,就像《我的世界》一样,但是更丰富、细节更多、纹理更清晰。
简单的技术细节
下面是实现的一些技术:
它的大小,其实不小了,加起来代码有好几十 kb,大部分是一些没有被压缩过的代码,大头是一个物理引擎,cannon.js ,这个物理引擎是被我压缩过的,耗尽精力,成功将其压缩到 29kb,算是极限了,我自己写过三维物理引擎,但效果与这个专业的比较,还是差距蛮大。
三维渲染引擎,采用了一个迷你的只有两 kb 的三维渲染引擎 W.js ,不过我改造的很多,几乎全盘改造了一番。加上了实例化等功能。
这么多方块是怎么生成的呢?大小方位等,是随机数生成的,而渲染则是使用了实例化模型技术。下面的代码,这是我生成方块数据的代码。17 是一个种子,循环一万次,生成 xyz 坐标等。
javascript
const random = k.genPR(17, numCubes * numCubes * 5); // 伪随机数
for (let i = 0; i < numCubes; i++) {
for (let j = 0; j < numCubes; j++) {
var index = i * numCubes + j;
cubeInstances.push({
x: Math.floor(random[index] * 99 * areaSpace + 1 - 50 * areaSpace) * cubeTimes,
y: Math.floor(random[index + 1] * 50),
z: Math.floor(random[index + 2] * 99 * areaSpace + 1 - 50 * areaSpace) * cubeTimes,
w: 20,
d: 30,
h: Math.floor(random[index + 3] * 19 + 1),
b:`#${Math.floor(random[index + 4] * 16777216).toString(16).padStart(6, '0')}`,
});
}
}
物理效果方面,即便是 cannon.js 这种专业的物理引擎,也无法一次性容纳 1 万 个方块的计算,所以我使用了区块管理,按需计算物理引擎,那些大大小小的立方块,只有我们走近了才会被计算。
程序是完全开源的,具有超级丰富的注释,可以在 github 的 kohunglee/openworld-js 这个代码仓库的 demo/cbcity/lastpack 目录里找到。如果感兴趣,真心希望为这个仓库点个 star !感谢!祝好人天天都被幸运缠身!
https://github.com/kohunglee/openworld-js
https://github.com/kohunglee/openworld-js/tree/main/demo/cbcity/lastpack
比较有意思的是上方的城市名。这个是我为了方便区分不同的区位,进行的命名,采用了 2024 年度中国 GDP 排名前 100 个城市,按照 100 米 ✖ 100 米将整个《赛博城寨》瓜分成 100 份,按照这些城市在我国的区块位置进行了排列。形成了这个区位命名。
(其实应该按人口算更合理公平.... 很遗憾,按照 GDP ,我的家乡安阳并不在此列)
大家可以去自己的城市那边逛逛(如果有的话...)哈哈~
城市列表如下:
乌鲁木齐 鄂尔多斯 包头 呼和浩特 北京 廊坊 唐山 沈阳 长春 哈尔滨
榆林 太原 石家庄 保定 沧州 天津 东营 烟台 大连 威海
兰州 新乡 邯郸 德州 济宁 济南 泰安 淄博 潍坊 青岛
西安 洛阳 郑州 周口 菏泽 徐州 宿迁 临沂 淮安 连云港
襄阳 南阳 阜阳 滁州 南京 扬州 镇江 泰州 盐城 南通
绵阳 宜昌 合肥 芜湖 常州 湖州 无锡 苏州 嘉兴 上海
成都 重庆 常德 岳阳 武汉 九江 金华 杭州 绍兴 宁波
宜宾 遵义 衡阳 长沙 株洲 宜春 南昌 上饶 温州 台州
昆明 曲靖 贵阳 广州 赣州 漳州 厦门 泉州 福州 宁德
南宁 湛江 茂名 江门 佛山 中山 珠海 东莞 深圳 惠州
结语
不知道这个想法是否有前途。欢迎大家在博客园底部的评论区进行讨论。
webgl 在最近十年,发展的比较好。不过平时很少能见到相关的网页。我想可能是因为其他的前端技术更吃香吧,或者说大部分的三维网页,都需要加载很多的模型,导致网页体积太大,所以不流行。
如果有人能将三维网页的体积使用技术手段大大的打下来,那么 webgl 将会更加的繁荣吧。借助程序化生成,让更少的代码呈现更多的显示效果。
现在的 webgpu 在 2023 年也公开了,起码在 Chrome 上可以访问到。性能提升很多,主要能操控的细节也多了,比如说实例化可以支持光椎体了。
实在是厌倦了千篇一律的平面网站..... 这样是我现在业余研究的 openworld.js 的初衷。