zoukankan      html  css  js  c++  java
  • TWaver3D入门探索——3D拓扑图之绽放的小球花

    http://servasoft.com/wp-content/uploads/2016/09/3d拓扑小球花.jpg

    这样一簇绚烂丰满艳丽多姿的3D小球花,要多少代码才能完成?其实不足百行,您信吗?下面咱就看一下具体实现过程,让您分分钟学会用TWaver HTML5制作3D拓扑图。

    搭建3D空间

    首先为花簇的绽放建一个展示的舞台。接触过TWaver2D的都知道,box、network是必不可少的,但对3D场景来说,还远远不够。一是要添加镜头位置,确定我们在什么角度和距离进行观察;二是要加上灯光,否则再美的画面也看不见。灯光分为点光源和环境光,一般来说要一个环境光和若干点光源搭配才能出来好的效果。

    var box = new mono.DataBox();
    var network= new mono.Network3D(box, null, monoCanvas);
    mono.Utils.autoAdjustNetworkBounds(network,document.documentElement,'clientWidth','clientHeight');
    network.getCamera().setPosition(0, 0, 4000);
    network.isSelectable=function(){return false};
    network.setClearColor('black');
    var pointLight = new mono.PointLight(0xFFFFFF,0.8);
    box.add(pointLight);
    var pointLight = new mono.PointLight(0xFFFFFF,0.5);
    pointLight.setPosition(500,2000,0);
    box.add(pointLight);
    box.add(new mono.AmbientLight(0x888888));
    

    创建3D小球花瓣

    每一个3D小球就是一个花瓣,是整个花簇的基础部件,也是最容易做的,只要几行代码而已。

    function createNode(color){
      //var color = color || '#'+('00000'+(Math.random()*0x1000000<<0).toString(16)).slice(-6);
      var node=new mono.Sphere(10,BALL_SEGMENT,BALL_SEGMENT);
      node.s({
        'm.type': 'phong',
        'm.color': color,
        'm.ambient': color,
      });
      return node;
    }
    

    其中的BALL_SEGMENT是球体切片数量,数量越大越生成的球体越圆滑,但计算量也就越大。解除注释掉的那条语句将会每次生成一个随机颜色的小球,这种五颜六色的感觉也别有趣味。

    http://servasoft.com/wp-content/uploads/2016/09/3d拓扑彩球花.jpg

    生成3D花朵

    正如若干花瓣组成一朵小花,我们也要将若干个小球连接在一起。这一步最重要的是花瓣的排列,既要随机有活力,又要规律有造型。实例中是将小球随机排列在一个球面的局部。

    function getSpherePoint(r, angle1, angle2){
      var x=r*Math.sin(angle1)*Math.cos(angle2);
      var y=r*Math.cos(angle1);
      var z=r*Math.sin(angle1)*Math.sin(angle2);
      return new mono.Vec3(x, y, z);
    }
    

     

    有了花瓣的摆放位置,一朵花也就很容易开放了:

     

    function createTree(box, count, range, offset, color){
    	var angleStep=Math.PI/50;
    	var center=new mono.Sphere(10,BALL_SEGMENT,BALL_SEGMENT);
    	center.s({
    		'm.type': 'phong',
    		'm.color': color,
    		'm.ambient': color,
    	});
    	box.add(center);
    	for(var i=0;i<count;i++){
    		var node= createNode(color);
    		var r=1000;
    		var angle1=range*Math.random()/5;
    		var angle2=Math.PI*2*Math.random();
    		var point=getSpherePoint(r, angle1, angle2);
    		point.y-=offset;
    		node.setPosition(point);
    		node.setParent(center);
    		box.add(node);
    		box.add(createLink(center, node));
    	}
    	return center;
    }
    

    通过改变其参数,可以开出不同的花朵。其中count是花瓣的数量,range是花朵球面的角度,offset是花瓣到花托的长度,color是花朵的颜色。

    绽放3D花簇

    剩下的工作就极其简单了,先建一个中心小球,再通过两个循环,就生成了有两层花朵的球状花簇。

    当然,你可以说这根本不像什么花簇。其实本来也不是要做一个现实的什么东西,只是为了用一段小而美的程序,让大家领略TWaver3D拓扑图的风采。如果您从中get到了什么技能和兴趣,那才是我们的真正目的!

    实际上,这个例子稍作变化,就可以用来展示丰富的3D网络拓扑图、各种复杂数据的树状关系图。你一定可以让它绽放的更加美丽!

    为了证实代码确实不足百行,特附上完整源码:

    <!DOCTYPE html>
    <html>
    <head>
        <title>Mono Test</title>
        <script type="text/javascript" src = "t.js"></script>
        <script type="text/javascript">
    		var BALL_SEGMENT=7;
            function init(){
                var box = new mono.DataBox();
                var network= new mono.Network3D(box, null, monoCanvas);
                mono.Utils.autoAdjustNetworkBounds(network,document.documentElement,'clientWidth','clientHeight');
    			network.getCamera().setPosition(0, 0, 4000);
    			network.isSelectable=function(){return false};
    			network.setClearColor('black');
                var pointLight = new mono.PointLight(0xFFFFFF,0.8);
                box.add(pointLight);
        		var pointLight = new mono.PointLight(0xFFFFFF,0.5);
                pointLight.setPosition(500,2000,0);
                box.add(pointLight);
                box.add(new mono.AmbientLight(0x888888));
    			var center=createNode('red');
    			box.add(center);
    			for(var i=0;i<10;i++){
    				var angle1=Math.random()*Math.PI;
    				var angle2=Math.random()*Math.PI*2;
    				var point=getSpherePoint(300, angle1, angle2);
    				var tree=createTree(box, 100, Math.PI*0.6, 700, '#'+('00000'+(Math.random()*0x1000000<<0).toString(16)).slice(-6));
    				tree.setPosition(point.x, point.y, point.z);
    				var rotation=point.rotationTowards(new mono.Vec3(0,1,0), point);
    				tree.setRotation(rotation);
    				box.add(createLink(center, tree));
    			}
    			for(var i=0;i<40;i++){
    				var angle1=Math.random()*Math.PI;
    				var angle2=Math.random()*Math.PI*2;
    				var point=getSpherePoint(1000, angle1, angle2);
    				var tree=createTree(box, 100, Math.PI*0.4, 800);
    				tree.setPosition(point.x, point.y, point.z);
    				var rotation=point.rotationTowards(new mono.Vec3(0,1,0), point);
    				tree.setRotation(rotation);
    				box.add(createLink(center, tree));
    			}
    		}
    		function createTree(box, count, range, offset, color){
    			var angleStep=Math.PI/50;
    			var center=new mono.Sphere(10,BALL_SEGMENT,BALL_SEGMENT);
    			center.s({
    				'm.type': 'phong',
    				'm.color': color,
    				'm.ambient': color,
    			});
    			box.add(center);
    			for(var i=0;i<count;i++){
    				var node= createNode(color);
    				var r=1000;
    				var angle1=range*Math.random()/5;
    				var angle2=Math.PI*2*Math.random();
    				var point=getSpherePoint(r, angle1, angle2);
    				point.y-=offset;
    				node.setPosition(point);
    				node.setParent(center);
    				box.add(node);
    				box.add(createLink(center, node));
    			}
    			return center;
    		}
    		function getSpherePoint(r, angle1, angle2){
    			var x=r*Math.sin(angle1)*Math.cos(angle2);
    			var y=r*Math.cos(angle1);
    			var z=r*Math.sin(angle1)*Math.sin(angle2);
    			return new mono.Vec3(x, y, z);
    		}
    		function createNode(color){
    			var color = color || '#'+('00000'+(Math.random()*0x1000000<<0).toString(16)).slice(-6);
    			var node=new mono.Sphere(10,BALL_SEGMENT,BALL_SEGMENT);
    			node.s({
    				'm.type': 'phong',
    				'm.color': color,
    				'm.ambient': color,
    			});
    			return node;
    		}
    		function createLink(node1, node2){
    			var link=new mono.Link(node1, node2);
    			link.s({
    				'm.transparent': true,
    				'm.opacity': 0.2,
    			});
    			return link;
    		}     
        </script>
    </head>
    <body onload = 'init()'>
        <div>
            <canvas id="monoCanvas"/>
        </div>
    </body>
    </html>
    
  • 相关阅读:
    hdu 1151
    DAG的最小路径覆盖和二分图的最大匹配
    二部图 最小点覆盖集与最大匹配的关系
    sdut 2151
    sdut Emergency
    作业
    Node.prototype.contains
    微博登录
    markdown
    Object.observe
  • 原文地址:https://www.cnblogs.com/xiaor2/p/5833533.html
Copyright © 2011-2022 走看看