基于HT的CSG功能构建HTML5的3D书架

2023-12-16 13:30

本文主要是介绍基于HT的CSG功能构建HTML5的3D书架,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

构造实体几何CSG全称Constructive solid geometry,是3D计算机图形学中构建模型的常用技术,可通过合并Union、相减Subtraction和相交Intersction的三种取集的逻辑运算,将立方体、圆柱体和棱柱等简单的基础模型,嵌套组合成更复杂三维模型。

CSG的算法这些年来已有各种语言平台版本实现,C++版主流的是 http://opencsg.org/ 已有众多基于该开源类库的应用案例,JavaScript语言较早版实现 http://evanw.github.io/csg.js/ 影响较广,很多其他js衍生版都是基于该版本进行改进完善,包括Java版的实现 https://github.com/miho/JCSG ,可参考基于JavaFX的3D打印IDE https://github.com/miho/JFXScad ,提起JavaFX视乎这些年完全消失在程序员视野毫无声息,但还是有一群拥护者持续在使用着如今地位有点尴尬的JavaFX。

Screen Shot 2014-12-25 at 12.19.17 AM

回到我们今天要搞的3D书架例子,我们将基于HT for Web的3D引擎来实现,HT已经内置了CSG功能的模型封装,我们通过构建CSGNode图元对象,该类型图元可对Host吸附的图元进行CSG技术的合集、并集和补集的三种操作,一般运用中裁剪的方式较为常用,因此CSGNode默认对Host图元的操作就是裁剪。

上图的例子效果可看出我们构建了一个DataModel数据模型,该模型绑定了一个TreeView树组件和两个Graph3dView的三维组件,上部分的Graph3dView组件添加了VisibleFunc的可见过滤器,隐藏了如下部分的Graph3dView中蓝色立方体图元,这些蓝色立方体图元就是CSGNode,其作用就是用来裁剪其吸附的书架Shelf对象,因此一般在3D编辑器状态下才需要出现,运行时科如上部分Graph3dView组件那样,通过添加可见过滤器将其隐藏,这样就实现了有凹槽可摆放书籍内容的3D书架效果,本例我们作为示例仅放了一本《CSS3  The Missing Manual》,这本书其实是由一个六面体,front面显示了书籍贴图,然后旋转一定角度进行摆放,btw《CSS3  The Missing Manual》第三版是本很不错的CSS书籍,强烈推荐!

Screen Shot 2014-12-25 at 12.22.57 AM

书架两边分别摆放了两个不同风格的小书台,通过上图我拖拽改变了蓝色CSGNode图元的位置,大家通过两张图的对比能更直观的体会到CSG的操作效果,玻璃门开关以及相册效果都是直接利用HT for Web的3D引擎提供的模型,通过设置透明度、相片贴图和旋转动画等呢只功能参数即可。

以下是该HT for Web的3D例子的所有JavaScript代码供参考:http://v.youku.com/v_show/id_XODU2MTQ4NjI4.html

ht.Default.setImage('ben12', {width: 100,height: 50,comps: [{type: 'image',name: 'ben1',rect: [0, 0, 50, 50]},{type: 'image',name: 'ben2',rect: [50, 0, 50, 50]}]                
});            function init(){                                 dm = new ht.DataModel();                treeView = new ht.widget.TreeView(dm);                                                                                                 gv1 = new ht.graph3d.Graph3dView(dm);   gv2 = new ht.graph3d.Graph3dView(dm);   splitView = new ht.widget.SplitView(gv1, gv2, 'v', 0.6);   mainSplit = new ht.widget.SplitView(treeView, splitView, 'h', 0.27);   view = mainSplit.getView();  view.className = 'main';document.body.appendChild(view);    window.addEventListener('resize', function (e) {mainSplit.invalidate();}, false);                         gv1.setMoveStep(30);gv1.setGridVisible(true); gv1.setEye(0, 100, 1000);gv1.setCenter(0, 200, 0);gv1.pan(0, 100, true);gv1.getLabel = function(){return null;};gv1.getBrightness = function(data){return null;};gv1.setVisibleFunc(function(data){if(data.showMe){return true;}if(data instanceof ht.CSGNode && data.getHost()){return false;}return true;});gv2.setMoveStep(30);gv2.setEditable(true);gv2.setGridVisible(true); gv2.setEditable(true);gv2.pan(0, 200, true);gv2.getLabel = function(){return null;};                initShelf1();                       initShelf2();                       initShelf3();                       treeView.expandAll();var angle = 0;setInterval(function(){angle += Math.PI/40;earth.r3(0, angle, 0);photos.s('dw.angle', angle);}, 50);                 
}            function initShelf1(){var shelf = new ht.CSGNode();shelf.s3(500, 400, 120);shelf.p3(0, 200, 0);shelf.setName('shelf1');shelf.s({'all.color': '#E5BB77'});dm.add(shelf);for(var i=0; i<2; i++){for(var j=0; j<5; j++){var clipNode = new ht.CSGNode();clipNode.setHost(shelf);clipNode.s3(80, 100, 120);clipNode.p3(-200+j*100, 340-i*120, 20);clipNode.setName('substract-'+i+'-'+j);clipNode.s('batch', 'tt');clipNode.setParent(shelf);dm.add(clipNode);}}var leftNode = new ht.CSGNode();leftNode.setHost(shelf);leftNode.s3(23, 380, 100);leftNode.p3(-255, 200, 0);leftNode.setName('substract left');leftNode.setParent(shelf);dm.add(leftNode);var rightNode = new ht.CSGNode();rightNode.setHost(shelf);rightNode.s3(23, 380, 100);rightNode.p3(255, 200, 0);rightNode.setName('substract right');rightNode.setParent(shelf);dm.add(rightNode);var bottomNode = new ht.CSGNode();bottomNode.setHost(shelf);bottomNode.s3(480, 140, 140);bottomNode.p3(0, 80, 0);bottomNode.setName('substract bottom');bottomNode.setParent(shelf);dm.add(bottomNode);  var topNode = new ht.CSGNode();topNode.setHost(shelf);topNode.s3(480, 10, 100);topNode.p3(0, 400, 0);topNode.setName('union top');topNode.s('attach.operation', 'union');topNode.setParent(shelf);dm.add(topNode);  var book = new ht.Node();book.setName('CSS3: The Missing Manual');book.s3(60, 80, 8);book.p3(-100, 210, 20);book.r3(-Math.PI/6, Math.PI/5, 0);book.setIcon('book');book.s({'front.image': 'book','back.color': 'white','left.color': 'white','all.color': 'gray'});book.setHost(shelf);book.setParent(shelf);dm.add(book);                                }function initShelf2(){                var shelf = new ht.CSGNode();shelf.s3(120, 240, 120);shelf.p3(0, 120, 0);shelf.setName('shelf2');shelf.s({'all.color': '#805642','csg.color': 'yellow','csg.reverse.flip': true});dm.add(shelf);var clipNode = new ht.CSGNode();clipNode.setName('shelf2-substract-up');clipNode.s3(100, 100, 130);clipNode.p3(0, 180, 0);clipNode.setHost(shelf);clipNode.s('attach.cull', true);clipNode.setParent(shelf);dm.add(clipNode);clipNode = new ht.CSGBox();clipNode.setName('CSGBox-Expand-Left');clipNode.s3(100, 100, 120);clipNode.p3(0, 65, 0.1);clipNode.setHost(shelf);clipNode.showMe = true;clipNode.s({'all.visible': false,'front.visible': true,'front.toggleable': true,                    'front.reverse.flip': true,'front.transparent': true,'front.end': Math.PI * 0.7,'front.color': 'rgba(0, 50, 50, 0.7)'});clipNode.setParent(shelf);clipNode.setFaceExpanded('front', true, true);dm.add(clipNode);                earth = new ht.Node();earth.setName('earth');earth.setIcon('earth');earth.s3(70, 70, 70);earth.p3(0, 50, 0);earth.s({'shape3d': 'sphere','shape3d.image': 'earth'});earth.setHost(shelf);  earth.setParent(shelf);dm.add(earth);shelf.t3(-360, 0, 50);shelf.r3(0, Math.PI/7, 0);                               
}            function initShelf3(){                var shelf = new ht.CSGNode();shelf.s3(120, 240, 120);shelf.p3(0, 120, 0);shelf.setName('shelf3');shelf.setIcon('ben');shelf.s({'all.image': 'brick','all.uv.scale': [2, 4],'top.uv.scale': [2, 2],'bottom.uv.scale': [2, 2],                                                             'csg.image': 'ben','csg.blend': 'yellow'});dm.add(shelf);photos = new ht.DoorWindow();photos.setName('DoorWindow-Photos');photos.setIcon('ben12');photos.s3(110, 100, 130);photos.p3(5, 180, 0);                photos.setHost(shelf);  photos.showMe = true;photos.s({                    'bottom.uv': [1,1, 1,0, 0,0, 0,1],'bottom.uv.scale': [1, 1],'left.uv.scale': [3, 3],'top.uv.scale': [2, 2],'dw.s3': [0.8, 0.9, 0.05],'dw.t3': [0, -5, 0],'dw.axis': 'v','dw.toggleable': false,'front.image': 'ben1','back.image': 'ben2','all.color': '#F8CE8B'});photos.setParent(shelf);dm.add(photos);var clipNode = new ht.CSGBox();clipNode.setName('CSGBox-Expand-Top');clipNode.s3(100, 100, 120);clipNode.p3(0, 65, 0.1);clipNode.setHost(shelf);clipNode.showMe = true;clipNode.s({                    'all.visible': false,'front.visible': true,'front.color': 'red','front.transparent': true,'front.opacity': 0.7,                    'front.reverse.flip': true,'front.toggleable': true,                                        'front.axis': 'top','front.end': Math.PI * 0.4});clipNode.setParent(shelf);clipNode.setFaceExpanded('front', true, true);dm.add(clipNode);                shelf.t3(360, 0, 50);shelf.r3(0, -Math.PI/7, 0);}   

 

这篇关于基于HT的CSG功能构建HTML5的3D书架的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

前端bug调试的方法技巧及常见错误

《前端bug调试的方法技巧及常见错误》:本文主要介绍编程中常见的报错和Bug,以及调试的重要性,调试的基本流程是通过缩小范围来定位问题,并给出了推测法、删除代码法、console调试和debugg... 目录调试基本流程调试方法排查bug的两大技巧如何看控制台报错前端常见错误取值调用报错资源引入错误解析错误

Vue中动态权限到按钮的完整实现方案详解

《Vue中动态权限到按钮的完整实现方案详解》这篇文章主要为大家详细介绍了Vue如何在现有方案的基础上加入对路由的增、删、改、查权限控制,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、数据库设计扩展1.1 修改路由表(routes)1.2 修改角色与路由权限表(role_routes)二、后端接口设计

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx

Vue ElementUI中Upload组件批量上传的实现代码

《VueElementUI中Upload组件批量上传的实现代码》ElementUI中Upload组件批量上传通过获取upload组件的DOM、文件、上传地址和数据,封装uploadFiles方法,使... ElementUI中Upload组件如何批量上传首先就是upload组件 <el-upl

前端知识点之Javascript选择输入框confirm用法

《前端知识点之Javascript选择输入框confirm用法》:本文主要介绍JavaScript中的confirm方法的基本用法、功能特点、注意事项及常见用途,文中通过代码介绍的非常详细,对大家... 目录1. 基本用法2. 功能特点①阻塞行为:confirm 对话框会阻塞脚本的执行,直到用户作出选择。②

如何使用CSS3实现波浪式图片墙

《如何使用CSS3实现波浪式图片墙》:本文主要介绍了如何使用CSS3的transform属性和动画技巧实现波浪式图片墙,通过设置图片的垂直偏移量,并使用动画使其周期性地改变位置,可以创建出动态且具有波浪效果的图片墙,同时,还强调了响应式设计的重要性,以确保图片墙在不同设备上都能良好显示,详细内容请阅读本文,希望能对你有所帮助...

CSS3 最强二维布局系统之Grid 网格布局

《CSS3最强二维布局系统之Grid网格布局》CS3的Grid网格布局是目前最强的二维布局系统,可以同时对列和行进行处理,将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,本文介... 深入学习 css3 目前最强大的布局系统 Grid 网格布局Grid 网格布局的基本认识Grid 网

HTML5中下拉框<select>标签的属性和样式详解

《HTML5中下拉框<select>标签的属性和样式详解》在HTML5中,下拉框(select标签)作为表单的重要组成部分,为用户提供了一个从预定义选项中选择值的方式,本文将深入探讨select标签的... 在html5中,下拉框(<select>标签)作为表单的重要组成部分,为用户提供了一个从预定义选项中

前端 CSS 动态设置样式::class、:style 等技巧(推荐)

《前端CSS动态设置样式::class、:style等技巧(推荐)》:本文主要介绍了Vue.js中动态绑定类名和内联样式的两种方法:对象语法和数组语法,通过对象语法,可以根据条件动态切换类名或样式;通过数组语法,可以同时绑定多个类名或样式,此外,还可以结合计算属性来生成复杂的类名或样式对象,详细内容请阅读本文,希望能对你有所帮助...

MobaXterm远程登录工具功能与应用小结

《MobaXterm远程登录工具功能与应用小结》MobaXterm是一款功能强大的远程终端软件,主要支持SSH登录,拥有多种远程协议,实现跨平台访问,它包括多会话管理、本地命令行执行、图形化界面集成和... 目录1. 远程终端软件概述1.1 远程终端软件的定义与用途1.2 远程终端软件的关键特性2. 支持的