基于WebGL(ThingJS)的家具城 商场 3D展示 3D可视化 DEMO

本文将模拟一个家具城,让大家足不出户在家里就能更加直观立体的挑选家具。

第一步,利用CampusBuilder搭建模拟场景。CampusBuilder的模型库有各种各样的模型,使我们搭建出的场景更逼真。使用CampusBuilde创建层级,之后再给层级加外立面就出现了当前的效果。这次我们其实只是需要一个楼层,所以我们就把上次使用的过的场景拿来改造一下。详情移步:CampusBuilder3D场景制作工具
点击查看demo

	//加载场景代码
var app = new THING.App({
    // 场景地址
    "url": "http://www.thingjs.com/./uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/scene/家具城",
    //背景设置
    "skyBox": "BlueSky"
});

  第二步,开启层级切换。因为我们模拟的“宜家”是某建筑中的一层,所以这里要开启层级切换以便进入家具城。

app.on(‘load‘, function (ev) {
    //开启层级切换
    app.level.change(ev.campus);
});

  同时给家具城创建一个广告牌,防止我们在第一人称下行走会“迷路”。贴图可以自行上传。

//创建广告牌
var advertisingSign = app.create({
    type: ‘Box‘,
    width: 15.0, // 宽度
    height: 5.0, // 高度
    depth: 0.5, // 深度
    widthSegments: 1.0, //宽度上的节数
    heightSegments: 1.0, // 高度上的节数
    depthSegments: 1.0, // 深度上的节数
    center: ‘Bottom‘, // 中心点
    style: {
        color: ‘#ffffff‘,
        opacity: 2,
        image: ‘/uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/file/家具展销/欧派.jpg‘
    },
    parent: app.query(‘building_01‘)[0],
});
advertisingSign.position = [50.957, 15.883, -16];

  这里给我们给整个场景用抽象物体围起来了,以免第一人称控件开启时会造成无碰撞体系坠落出场景。记得要给他们组合并命名为‘碰撞盒’,在场景加载完成后将他们“隐藏”起来。

app.on(‘load‘, function (ev) {
    //开启层级切换
    app.level.change(ev.campus);
    //将碰撞盒的透明度设置为0,并且将他们的pickable属性设置为false,不可被选中。
	var crashBox = app.query(‘碰撞盒‘)[0];
    crashBox.style.opacity = 0;
    crashBox.pickable = false;
});

  第三步,添加第一人称控件。

先创建两个按钮来控制第一人称控件。

	new THING.widget.Button(‘第一人称‘, add_control);
    new THING.widget.Button(‘自由视角‘, remove_control);

  

添加第一人称控件

//第一人称组件
var ctrl = null;
function add_control() {
    if (app.level.current.name == ‘Campus‘) {
        app.camera.position = [75.28812158204005, 1.8016147124541857, 29.699063489018236];
        app.camera.target = [53.32909358623788, 4.541642332131091, -9.470748625431646];

    }
    if (app.level.current.name != ‘Campus‘) {
        app.level.change(app.query(‘新楼层‘)[0]);
        app.camera.flyTo({
            ‘position‘: [41.05650213795261, 1.3469938677565356, -18.6143831867287],
            ‘target‘: [38.982251559488404, 0.7081383467333933, -23.867802267306008],
            ‘time‘: 2000,
            ‘complete‘: function () {
            }
        });
    }
    if (ctrl) return;
    ctrl = app.addControl(
        new THING.WalkControl({
            walkSpeed: 0.02,
            turnSpeed: 0.25,
            gravity: 30,
            eyeHeight: 1.7,
            jumpSpeed: 0,
            enableKeyRotate: false,
            useCollision: true,//app.scene
            useGravity: true,
            groundObjects: [app.scene] //把整个场景都添加,可把楼层或其他需要检测的添加进入碰撞体系里 | 默认值 园区地板
        })
    );
}

  移除第一人称控件

	function remove_control() {
    if (!ctrl)
        return;
    app.removeControl(ctrl);
    ctrl = null;
}

  第四步,创建界面panel用于显示家居的详细信息。
添加界面

	var panel = null;
function add_panel(title, total, goodsInfo) {
    panel = new THING.widget.Panel({
        titleText: ‘商品名称:‘ + title,
        closeIcon: true, // 是否有关闭按钮
        dragable: false, // 是否可以拖拽
        retractable: true,
        opacity: 0.9, // 透明度
        hasTitle: true
    });
    panel.position = [1000, 0];
    var dataObj = {
        total: total,
        goodsInfo: goodsInfo
    };
    var total = panel.addString(dataObj, ‘total‘).caption(‘总价‘);
    var goodsInfo = panel.addString(dataObj, ‘goodsInfo‘).caption(‘商品介绍‘);

}

  

移除界面

	function remove_panel() {
    if (panel) {
        panel.destroy();
        panel = null;
    }
}

  

最后一步,为商品和大楼添加点击事件。这里我们也要卸载双击事件,因为鼠标双击时会聚焦当前物体,与我们的业务逻辑有冲突所以这里给他卸载掉。首先是普通的点击事件,鼠标左键点击时会出现商品的信息。右键点击时,会移除第一人称控件。

	//鼠标点击事件
app.on(‘click‘, function (ev) {
    if (ev.button == 2) {
        remove_control();
        return;
    }
    remove_panel();
    switch (ev.object.name) {
        case "桌椅组合1": add_panel(‘自然风格餐桌系列‘, "2598.00", "  简约的圆桌设计,微冷的现代居室围成一桌大自然的感觉。自然本色,简介的设计,彰显质朴、实用、少即是多的线代生活哲学。");
            break;
        case "桌椅组合2": add_panel(‘线代都市餐桌系列‘, "2198.00", "  利落线条,刻画几何形底座。自然致简的浅木色橡木拼花,带有淡淡的手工白蜡处理,搭配内敛的深灰色线条,形成微妙平衡,线代感呼之欲出。");
            break;
        case "桌椅组合3": add_panel(‘紧凑家庭餐桌系列‘, "1998.00", "  紧凑家庭餐厅,享四人围坐的宽适与惬意。精巧的尺寸,圆融包容的圆桌设计,即便是紧凑的客餐厅一体空间,也能欢畅小谈。");
            break;
        case "沙发组合1": add_panel(‘本色笔记组合沙发‘, "2598.00", "  简约的圆桌设计,微冷的现代居室围成一桌大自然的感觉。自然本色,简介的设计,彰显质朴、实用、少即是多的线代生活哲学。");
            break;
        case "沙发组合2": add_panel(‘云海阑珊组合沙发‘, "8888.00", "  全家人围坐的恬淡时刻,更多一份舒适。借一抹海天的蓝,再偷来云朵的舒软,只为全家围坐的时刻,尽享舒适怡然。");
            break;
        case "沙发组合3": add_panel(‘商务舒适组合沙发‘, "8598.00", "  简约的圆桌设计,微冷的现代居室围成一桌大自然的感觉。自然本色,简介的设计,彰显质朴、实用、少即是多的线代生活哲学。");
            break;
        case "沙发组合4": add_panel(‘自然风格餐桌系列‘, "5508.00", "  简约的圆桌设计,微冷的现代居室围成一桌大自然的感觉。自然本色,简介的设计,彰显质朴、实用、少即是多的线代生活哲学。");
            break;
        case "沙发组合5": add_panel(‘自然风格餐桌系列‘, "2578.00", "  简约的圆桌设计,微冷的现代居室围成一桌大自然的感觉。自然本色,简介的设计,彰显质朴、实用、少即是多的线代生活哲学。");
            break;
    }
});
app.off(‘dblclick‘);

  代码块 => 层级 => 触发 => 修改进入层级操作

这里我们将进入层级的操作改为直接进入我们的家具城这一层“新楼层”。

//修改singleClick点击之后进入级的操作
app.on(THING.EventType.SingleClick, function (ev) {
    var object = ev.object;
    if (object.name == "building_01") {
        app.level.change(app.query(‘新楼层‘)[0]);
        app.camera.flyTo({
            ‘position‘: [41.05650213795261, 1.3469938677565356, -18.6143831867287],
            ‘target‘: [38.982251559488404, 0.7081383467333933, -23.867802267306008],
            ‘time‘: 2000,
            complete: function () {
                console.log("我已经进来了" + app.level.current.name);
            }
        });
    }
    return;
}, ‘customLevelEnterMethod‘);

  小结:
第一人称控件的问题,Campus => 新楼层 ,如果不设置摄像机飞到一合理位置,摄像机将脱离楼层,因为进入楼层的时候摄像机的默认位置不在楼层上,所以每次在楼层内添加第一人称控件时我们必须要将摄像机放到一个合理的位置。

全部代码:

//加载场景代码
var app = new THING.App({
    // 场景地址
    "url": "http://www.thingjs.com/./uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/scene/家具城",
    //背景设置
    "skyBox": "BlueSky"
});

app.on(‘load‘, function (ev) {
    app.level.change(ev.campus);
    var crashBox = app.query(‘碰撞盒‘)[0];
    crashBox.style.opacity = 0;
    crashBox.pickable = false;
    new THING.widget.Button(‘第一人称‘, add_control);
    new THING.widget.Button(‘自由视角‘, remove_control);

});

//修改singleClick点击之后进入级的操作
app.on(THING.EventType.SingleClick, function (ev) {
    var object = ev.object;
    if (object.name == "building_01") {
        app.level.change(app.query(‘新楼层‘)[0]);
        app.camera.flyTo({
            ‘position‘: [41.05650213795261, 1.3469938677565356, -18.6143831867287],
            ‘target‘: [38.982251559488404, 0.7081383467333933, -23.867802267306008],
            ‘time‘: 2000,
            complete: function () {
                console.log("我已经进来了" + app.level.current.name);
            }
        });
    }
    return;
}, ‘customLevelEnterMethod‘);

//鼠标点击事件
app.on(‘click‘, function (ev) {
    if (ev.button == 2) {
        remove_control();
    }
    if (typeof (ev.object) == undefined)
        return;
    remove_panel();
    switch (ev.object.name) {
        case "桌椅组合1": add_panel(‘自然风格餐桌系列‘, "2598.00", "  简约的圆桌设计,微冷的现代居室围成一桌大自然的感觉。自然本色,简介的设计,彰显质朴、实用、少即是多的线代生活哲学。");
            break;
        case "桌椅组合2": add_panel(‘线代都市餐桌系列‘, "2198.00", "  利落线条,刻画几何形底座。自然致简的浅木色橡木拼花,带有淡淡的手工白蜡处理,搭配内敛的深灰色线条,形成微妙平衡,线代感呼之欲出。");
            break;
        case "桌椅组合3": add_panel(‘紧凑家庭餐桌系列‘, "1998.00", "  紧凑家庭餐厅,享四人围坐的宽适与惬意。精巧的尺寸,圆融包容的圆桌设计,即便是紧凑的客餐厅一体空间,也能欢畅小谈。");
            break;
        case "沙发组合1": add_panel(‘本色笔记组合沙发‘, "2598.00", "  简约的圆桌设计,微冷的现代居室围成一桌大自然的感觉。自然本色,简介的设计,彰显质朴、实用、少即是多的线代生活哲学。");
            break;
        case "沙发组合2": add_panel(‘云海阑珊组合沙发‘, "8888.00", "  全家人围坐的恬淡时刻,更多一份舒适。借一抹海天的蓝,再偷来云朵的舒软,只为全家围坐的时刻,尽享舒适怡然。");
            break;
        case "沙发组合3": add_panel(‘商务舒适组合沙发‘, "8598.00", "  简约的圆桌设计,微冷的现代居室围成一桌大自然的感觉。自然本色,简介的设计,彰显质朴、实用、少即是多的线代生活哲学。");
            break;
        case "沙发组合4": add_panel(‘自然风格餐桌系列‘, "5508.00", "  简约的圆桌设计,微冷的现代居室围成一桌大自然的感觉。自然本色,简介的设计,彰显质朴、实用、少即是多的线代生活哲学。");
            break;
        case "沙发组合5": add_panel(‘自然风格餐桌系列‘, "2578.00", "  简约的圆桌设计,微冷的现代居室围成一桌大自然的感觉。自然本色,简介的设计,彰显质朴、实用、少即是多的线代生活哲学。");
            break;
    }
});
//卸载双击事件
app.off(‘dblclick‘);

// 界面组件
var panel = null;
function add_panel(title, total, goodsInfo) {
    panel = new THING.widget.Panel({
        titleText: ‘商品名称:‘ + title,
        closeIcon: true, // 是否有关闭按钮
        dragable: false, // 是否可以拖拽
        retractable: true,
        opacity: 0.9, // 透明度
        hasTitle: true
    });
    panel.position = [1000, 0];
    var dataObj = {
        total: total,
        goodsInfo: goodsInfo
    };
    var total = panel.addString(dataObj, ‘total‘).caption(‘总价‘);
    var goodsInfo = panel.addString(dataObj, ‘goodsInfo‘).caption(‘商品介绍‘);

}
function remove_panel() {
    if (panel) {
        panel.destroy();
        panel = null;
    }
}

//创建广告牌
var advertisingSign = app.create({
    type: ‘Box‘,
    width: 15.0, // 宽度
    height: 5.0, // 高度
    depth: 0.5, // 深度
    widthSegments: 1.0, //宽度上的节数
    heightSegments: 1.0, // 高度上的节数
    depthSegments: 1.0, // 深度上的节数
    center: ‘Bottom‘, // 中心点
    style: {
        color: ‘#ffffff‘,
        opacity: 2,
        image: ‘/uploads/wechat/oLX7p05lsWJZUIxnIWsNXAzJ40X8/file/家具展销/欧派.jpg‘
    },
    parent: app.query(‘building_01‘)[0],
});
advertisingSign.position = [50.957, 15.883, -16];

//第一人称组件
var ctrl = null;
function add_control() {
    if (app.level.current.name == ‘Campus‘) {
        app.camera.position = [75.28812158204005, 1.8016147124541857, 29.699063489018236];
        app.camera.target = [53.32909358623788, 4.541642332131091, -9.470748625431646];

    }
    if (app.level.current.name != ‘Campus‘) {
        app.level.change(app.query(‘新楼层‘)[0]);
        app.camera.flyTo({
            ‘position‘: [41.05650213795261, 1.3469938677565356, -18.6143831867287],
            ‘target‘: [38.982251559488404, 0.7081383467333933, -23.867802267306008],
            ‘time‘: 2000,
            ‘complete‘: function () {
            }
        });
    }
    if (ctrl) return;
    ctrl = app.addControl(
        new THING.WalkControl({
            walkSpeed: 0.02,
            turnSpeed: 0.25,
            gravity: 30,
            eyeHeight: 1.7,
            jumpSpeed: 0,
            enableKeyRotate: false,
            useCollision: true,//app.scene
            useGravity: true,
            groundObjects: [app.scene] //把整个场景都添加,可把楼层或其他需要检测的添加进入碰撞体系里 | 默认值 园区地板
        })
    );
}
function remove_control() {
    if (!ctrl)
        return;
    app.removeControl(ctrl);
    ctrl = null;
}

  

原文地址:https://www.cnblogs.com/thingjs/p/10192046.html

时间: 2024-08-05 22:06:28

基于WebGL(ThingJS)的家具城 商场 3D展示 3D可视化 DEMO的相关文章

基于WebGL(ThingJS)的平面图导航,室内导航,3D聚焦 (二)

前言 基于WebGL架构的3D可视化平台-平面图导航(一)中已经完成了iframe面板与我们的3D场景的简单交互,下面我们继续完善并给iframe页加上鼠标悬停事件让iframe页的img标签和我们场景中的obj一起动起来. 实现 第一步,还是使用之前的场景接着上次的继续,先编写iframe页.给每一个img标签都加上onmouseover.onmouseout 事件. <!DOCTYPE html> <html lang="en"> <head>

基于 HTML5 + WebGL 的宇宙 3D 展示系统

前言 近年来随着引力波的发现.黑洞照片的拍摄.火星上存在水的证据发现等科学上的突破,以及文学影视作品中诸如<三体>.<流浪地球>.<星际穿越>等的传播普及,宇宙空间中那些原本遥不可及的事物离我们越来越近,人们对未知文明的关注和对宇宙空间的好奇达到了前所未有的高度.站在更高的立足点上,作为人类这个物种中的一员,我们理所应当对我们生活的星球.所在的太阳系有一定的认识,对 8 大行星各自的运行轨道.质量.资源存储量甚至是地形有一定的了解. 本系统采用 Hightopo 的 H

基于WebGL 的3D呈现A* Search Algorithm

http://www.hightopo.com/demo/astar/astar.html 最近搞个游戏遇到最短路径的常规游戏问题,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现,算法基于开源 https://github.com/bgrins/javascript-astar 的javascript实现,其实作者也有个不错的2D例子实现 http://www.briangrinstead.com/files/astar/ ,只不过觉得所有A*算法的可视化实现都是平面的不够

基于WebGL的炫酷元素背景水波涟漪jQuery特效

jquery.ripples是一款基于WebGL的效果非常炫酷的元素背景水波涟漪jQuery特效插件.该jQuery插件通过强大的WebGL,可以在指定的元素上添加一个水波层,制作出水波涟漪的炫酷效果,并且可以使用鼠标来和它进行互动. WebGL是一种3D绘图标准,这种绘图技术标准允许把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的一个JavaScript绑定,WebGL可以为HTML5 Canvas提供硬件3D加速渲染,这样Web开发人员就可以

ANDROID应用中嵌入Unity3D视图(展示3D模型)

效果展示:                 开篇废话: 我现在所在的Team每周需要一个人给大家介绍一个知识点,或者新技术.这礼拜正好轮到我了,由于我工作才一年,面对那帮老鸟讲知识点感觉有点作死.所以我就准备选个新技术介绍一下. 由于我在大学里自学过一段时间Unity3D,所以我想介绍的技术就是它,但我现在做的是应用开发,不能做个小游戏去给大家演示.所以我想到比较简单,直观,而且有可能真正能用到的就是在Android应用中展示3D模型.比如在产品展示时直接把这个产品的3D模型展示出来而不是个图片

直击东京产交会,弘瑞(HORI)在国际舞台展示3D打印魅力

11月14日,由日本东京都政府等主办.以"连接电源.连接未来"为主题的2018产业交流展,在东京国际展览中心隆重开幕.弘瑞(HORI)作为我国3D打印行业的知名品牌受邀参展,面向国际观众展示3D打印技术的魅力. 本届为期三天的东京产业交流展,聚焦信息.环境.医疗与福利.机械与金属等领域,是这项日本最大规模中小企业贸易展的第21次举办,致力于将日本首都圈(东京都.埼玉县.千叶县.神奈川县)内有办事机构的.富有个性的中小企业汇聚一堂,展示各自的先进技术及创新产品以扩大销路,并实现企业间的信

Unity 进度条3D制作(3D版)

昨天我们一起学习了2D进度跳的制作,那么趁着我们脑海中还残存昨日的记忆,今天继续学习另一种方法: 实现思路:当鼠标悬浮Start按钮->实例化物体并显示进度->100/100->进入游戏场景:   鼠标离开按钮进度还原为 0/100    直接点击Start按钮也可完成. 1,首先我们导入NGUI资源包,在当前工程的场景下创建UI. 2,在Herarchy下添加平行光,在Panel下添Button. 此处Background没有选择背景图片,即背景色为默认值,此处label设置字体显示S

HTML5 CSS3 诱人的实例: 3D立方体旋转动画DEMO

创意来自:http://www.html5tricks.com/demo/html5-3d-cube/index.html , 同学给我发的例子,感觉很不错,不过实在想不出来实际的用处,但是效果很炫~ 效果图: 知识点: 1.perspective ,transform 的复习 2.css3 backgroud实现格格背景,即面上的小格格 3. @-webkit-keyframes 实现动画 HTML: <body> <div class="stage"> &l

3D Transformation 3D物体位移函数

如何操作物体在3D空间中的位置呢,方法有很多. 这里总结一下最流行的矩阵操作. 1. 放大缩小一个物体,我们可以填写一个放大缩小矩阵,如下代码: void InitScaleTransform(Matrix4f& m) const { m.m[0][0] = m_scale.x; m.m[0][1] = 0.0f ; m.m[0][2] = 0.0f ; m.m[0][3] = 0.0f; m.m[1][0] = 0.0f ; m.m[1][1] = m_scale.y; m.m[1][2] =