TWaver - 专注UI技术

http://twaver.servasoft.com/
posts - 171, comments - 191, trackbacks - 0, articles - 2
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

TWaver3D拓扑图之人在江湖

Posted on 2016-11-24 10:03 TWaver 阅读(361) 评论(0)  编辑  收藏



俗话说,有人的地方就有江湖,江湖就是帮派林立错综复杂的关系网。今天我们就来展示这样一个小小的江湖。


故事背景

崇祯末年,民不聊生,烽烟四起……

江湖都是有背景的,我们的3D江湖也需要一个背景。江湖就是一个舞台,舞台就要有空间、场地、灯光和观众。在我们的3D舞台中,box就是空间,容纳所有物体;network就是场地,展示千姿百态;PointLight和AmbientLight就是灯光,让画面更立体鲜亮;Camera就是观众,没有观众戏就永远不会开场。下面就看看这个江湖是个怎样的背景:

var box = new mono.DataBox();
var network
= new mono.Network3D(box, null, twaverCanvas);
mono.Utils.autoAdjustNetworkBounds(network,document.documentElement,
'clientWidth','clientHeight');
network.getCamera().setPosition(
-5008001900);
network.getCamera().setFov(
30);
network.isSelectable
=function(){return false};
network.setClearColor(
'black');
network.getDefaultInteraction().minDistance 
= 500;
network.getDefaultInteraction().maxDistance 
= 3000;
network.getDefaultInteraction().yLowerLimitAngle
=0;
network.getDefaultInteraction().yUpLimitAngle
=Math.PI/2;
var pointLight 
= new mono.PointLight(0xFFFFFF,0.5);
pointLight.setPosition(
0,1000,0);
box.add(pointLight);
box.add(
new mono.AmbientLight(0x888888));

江湖初现

现在,江湖已经在那里了,但我们却什么都看不见。这是因为,里面还没有任何我们能看到的东西。

好吧,为了让这个江湖更像舞台,我们就真的搭建一个平台:


var ground=new mono.Cube(4200/2203000/2);
ground.s({
    
'm.type''phong',
    
'm.color''#f2f2f2',
    
'm.ambient''#f2f2f2',
});
ground.setPositionY(
-ground.getHeight()/2);
box.add(ground);


舞台已建好,接下来就该人物登场了。


大侠诞生

咱们创造的是一个高度意象的江湖,人物也是高度抽象的形象,所谓大象无形大音希声,大家就体会个概念吧。

首先,让我们看看大侠的头部:


var head=new mono.Sphere(81010);
head.s({
    
'm.color''#F3E2A9',
    
'm.ambient''#F3E2A9',
    
'm.type''phong',
});
head.setPositionY(
38);
box.add(head);

什么?就是个圆球!

嗯哪。都说一百个人心中就有一百个什么那他,至于五官样貌就全凭大家想象了。

接下来再看看大侠的身体:


var body=new mono.Sphere(111010);
body.s({
    
'm.type''phong',
    
'm.texture.image': pic,
    
'm.texture.repeat': repeat ? repeat : new mono.Vec2(2,2),
});
body.setScaleY(
1.6);
body.setPositionY(
15);
box.add(body);

不出大家意料,是个椭球。不过再抽象,衣服还是要穿的,裸奔不是我侠的风范。


立锥之地

大侠已诞生,怎么也要给人家个势力范围啊。


var pad=new mono.Cylinder(20,20,2.5);
pad.s({
    
'm.color''#F5F5F5',
    
'm.type''phong',
    
'top.m.lightmap.image''shadow.jpg',
});

还要稍微装饰一下,给加个边框:

var pad1=new mono.Cylinder(23,23,3,15);
pad1.s({
    
'm.color''#2ECCFA',
    
'm.ambient''#2ECCFA',
    
'm.type''phong',
});
var pad2
=new mono.Cylinder(20,20,3,15);
pad2.s({
    
'm.color''#2ECCFA',
    
'm.ambient''#2ECCFA',
    
'm.type''phong',
});
var padEdge
=new mono.ComboNode([pad1, pad2], ['-']);
box.add(padEdge);

为了将其变成大侠永远的私有之地,还需要将他们结合到一起。

head.setParent(pad);
body.setParent(pad);
padEdge.setParent(pad);
pad.setPosition(position);

初入江湖

大侠已出,终于可以闯江湖了!先来他50多个,来来来,排一排:


var user=createUser(box, new mono.Vec3(0,0,0), 'cloth.jpg');
var count
=50;
for(var i=0;i<count;i++){
    var x
=500*Math.cos(Math.PI*2/count*i);
    var z
=500*Math.sin(Math.PI*2/count*i);
    createUser(box, 
new mono.Vec3(x,0,z), 'cloth'+parseInt(Math.random()*3+1)+'.jpg');
}


不太壮观啊,再来他400个!果然有了江湖的感觉。


for(var i=0;i<400;i++){
    var x
=Math.random()*Math.random()*ground.getWidth()/2;
    x
=Math.random()>0.5 ? x : -x;
    var y
=Math.random()*Math.random()*ground.getDepth()/2;
    y
=Math.random()>0.5 ? y : -y;
    createUser(box, 
new mono.Vec3(x, 0, y), 'cloth'+parseInt(Math.random()*3+1)+'.jpg');
}


人在江湖

江湖险恶,哪里是只凭衣服就分出了帮派,必须是你中有我我中有你错综复杂恩怨情仇各种明争暗斗,这些复杂的关系就需要用各种连线标识一下了。


function createLine(box, x1, z1, x2, z2, color){
    color
=color || '#2ECCFA';
    var path 
= new mono.Path();
    path.moveTo(x1, z1,
0);
    path.lineTo((x1
+x2)/2+100, (z1+z2)/2+1000);
    path.lineTo(x2, z2, 
0);
    path
=mono.PathNode.prototype.adjustPath(path, 50);
    var line
=new mono.PathCube(path, 3110);
    line.s({
        
'm.color': color,
        
'm.ambient': color,
        
'm.type''phong',
    });
    box.add(line);
}

通过给出不同点和颜色,就可以形成各种连线。

对于最初的51人,我们简单的将周边与圆心连接,体现出一个强有力的领导核心。

后来的400人,每10人添加一根连线——当然按说应该是每人都有多根连线才真实,但那就满屏全是线没法看了。


一个小小的江湖,就这样形成了!你有没有感受到江湖的魔力和魅力呢?


江湖启示

其实,我们都身在江湖,要想安身立命,不能只靠江湖义气,真才实学才是闯荡江湖的本钱!

从这个实例中,我们应该学到在立体拓扑图中,借鉴平面拓扑布局的一种方法,提供的是一种在立体图形中展示平面拓扑的思路。其实类似的应用场景很多,大家稍做变换就可以打造适合自己的特色3D拓扑图了。

正看文章的小哥,我看你骨骼精奇,是个练武的奇才!我这里有一部TWaver3D宝典,何不入我赛瓦门,咱们一起闯荡江湖!


  1 <!DOCTYPE html>
  2 <html>
  3 <head>
  4     <title>TWaver 3D</title>
  5     <script type="text/javascript" src = "t.js"></script>
  6     <script type="text/javascript">
  7         function init(){
  8             var box = new mono.DataBox();
  9             var network= new mono.Network3D(box, null, twaverCanvas);
 10             mono.Utils.autoAdjustNetworkBounds(network,document.documentElement,'clientWidth','clientHeight');
 11             network.getCamera().setPosition(-5008001900);
 12             network.getCamera().setFov(30);
 13             network.isSelectable=function(){return false};
 14             network.setClearColor('black');
 15             network.getDefaultInteraction().minDistance = 500;
 16             network.getDefaultInteraction().maxDistance = 3000;
 17             network.getDefaultInteraction().yLowerLimitAngle=0;
 18             network.getDefaultInteraction().yUpLimitAngle=Math.PI/2;
 19             var pointLight = new mono.PointLight(0xFFFFFF,0.5);
 20             pointLight.setPosition(0,1000,0);
 21             box.add(pointLight);
 22             box.add(new mono.AmbientLight(0x888888));
 23             var ground=new mono.Cube(4200/2203000/2);
 24             ground.s({
 25                 'm.type''phong',
 26                 'm.color''#f2f2f2',
 27                 'm.ambient''#f2f2f2',
 28             });
 29             ground.setPositionY(-ground.getHeight()/2);
 30             box.add(ground);
 31             var user=createUser(box, new mono.Vec3(0,0,0), 'cloth.jpg');
 32             var count=50;
 33             for(var i=0;i<count;i++){
 34                 var x=500*Math.cos(Math.PI*2/count*i);
 35                 var z=500*Math.sin(Math.PI*2/count*i);
 36                 createUser(box, new mono.Vec3(x,0,z), 'cloth'+parseInt(Math.random()*3+1)+'.jpg');
 37                 createLine(box, 00, x, z);
 38             }
 39             var lastX, lastY;
 40             for(var i=0;i<400;i++){
 41                 var x=Math.random()*Math.random()*ground.getWidth()/2;
 42                 x=Math.random()>0.5 ? x : -x;
 43                 var y=Math.random()*Math.random()*ground.getDepth()/2;
 44                 y=Math.random()>0.5 ? y : -y;
 45                 createUser(box, new mono.Vec3(x, 0, y), 'cloth'+parseInt(Math.random()*3+1)+'.jpg');
 46                 if(i>0 && i%10==0){
 47                     createLine(box, lastX, -lastY, x, -y, getLinkColor());
 48                 }
 49                 lastX=x;
 50                 lastY=y;
 51             }
 52         }
 53         function getLinkColor(){
 54             var random=Math.random();
 55             if(random<0.05return 'red';
 56             if(random<0.1return 'orange';
 57             if(random<0.2return 'green';
 58         }
 59         function createLine(box, x1, z1, x2, z2, color){
 60             color=color || '#2ECCFA';
 61             var path = new mono.Path();
 62             path.moveTo(x1, z1,0);
 63             path.lineTo((x1+x2)/2+100, (z1+z2)/2+1000);
 64             path.lineTo(x2, z2, 0);
 65             path=mono.PathNode.prototype.adjustPath(path, 50);
 66             var line=new mono.PathCube(path, 3110);
 67             line.s({
 68                 'm.color': color,
 69                 'm.ambient': color,
 70                 'm.type''phong',
 71             });
 72             box.add(line);
 73         }
 74         function createUser(box, position, pic, repeat){
 75             var head=new mono.Sphere(81010);
 76             head.s({
 77                 'm.color''#F3E2A9',
 78                 'm.ambient''#F3E2A9',
 79                 'm.type''phong',
 80             });
 81             head.setPositionY(38);
 82             box.add(head);
 83             var body=new mono.Sphere(111010);
 84             body.s({
 85                 'm.type''phong',
 86                 'm.texture.image': pic,
 87                 'm.texture.repeat': repeat ? repeat : new mono.Vec2(2,2),
 88             });
 89             body.setScaleY(1.6);
 90             body.setPositionY(15);
 91             box.add(body);
 92             var padEdge=createPadEdge(box);
 93             var pad=new mono.Cylinder(20,20,2.5);
 94             pad.s({
 95                 'm.color''#F5F5F5',
 96                 'm.type''phong',
 97                 'top.m.lightmap.image''shadow.jpg',
 98             });
 99             head.setParent(pad);
100             body.setParent(pad);
101             padEdge.setParent(pad);
102             pad.setPosition(position);
103             box.add(pad);
104             return pad;
105         }
106         function createPadEdge(box){
107             var pad1=new mono.Cylinder(23,23,3,15);
108             pad1.s({
109                 'm.color''#2ECCFA',
110                 'm.ambient''#2ECCFA',
111                 'm.type''phong',
112             });
113             var pad2=new mono.Cylinder(20,20,3,15);
114             pad2.s({
115                 'm.color''#2ECCFA',
116                 'm.ambient''#2ECCFA',
117                 'm.type''phong',
118             });
119             var padEdge=new mono.ComboNode([pad1, pad2], ['-']);
120             box.add(padEdge);
121             return padEdge;
122         }
123     </script>
124 </head>
125 <body onload = 'init()'>
126     <div>
127         <canvas id="twaverCanvas"/>
128     </div>
129 </body>
130 </html>

如有任何问题,可以留言,或者发邮件给我们:tw-service@servasoft.com。

只有注册用户登录后才能发表评论。


网站导航: