HTTP协议是用来规范/约束哪一类事物?

 1                var str_res=xmlHttp.responseText;//从h2数据库获取到的是一个dom文档,要从中找到所需要的字段
 2                         xmlHttp.abort();
 3                         var div=document.createElement("div");
 4                         //div.innerHTML=str_res;//这样做会报错,因为加载整个dom时,标签中的引用和代码都会被执行!!!!
 5                         div.innerHTML=str_res.substring(str_res.search(/<table/),str_res.search(/<\/table>/)+8);
 6                         div.style.display=false;
 7                         //document.getElementById("div_allbase").appendChild(div);不需要这一句
 8                         var tr=div.getElementsByTagName("tr")[1];//从返回的数据表里提取出数据部分
 9                         var tds=tr.getElementsByTagName("td");
10                         min_floor=parseInt(tds[0].innerHTML);
11                         max_floor=parseInt(tds[1].innerHTML);
12                         width_room=parseInt(tds[2].innerHTML);//房间最多的一层有多少房间
13                         height_floor=min_floor+max_floor+1;//总共有多少层
14                         var int_wh=width_room>height_floor?width_room:height_floor;//取宽高中较大的值
15                         var int_size=newland.FindPower(int_wh);//找到大于size的最小的2的整数次幂,注意!!!!
16                         can_temp.width=int_size;
17                         can_temp.height=int_size;
18                         context_temp=can_temp.getContext("2d");
19                         context_temp.fillStyle="rgba(0,0,255,1)";
20                         context_temp.fillRect(0,0,int_size,int_size);
21                         imagedata_temp=context_temp.getImageData(0,0,int_size,int_size);//取canvas的像素数据
22 
23                         arr_floorroom=[];
24                         pbeta=0;//认为每一层的弧度区分度是一定的
25                         arr_palpha=[];//每一层内的房间的弧度区分度不同
26                         var arr_temp=JSON.parse(localStorage.getItem("arr_floorroom"));//读取本地存储
27 
28                         if(arr_temp&&arr_temp.length>0)//如果有本地持久化存储就使用本地的存储,节省时间
29                         {//经测试Chrome浏览器的5M空间正好可以放下一个行星的数据
30                             strsrc_dqk=JSON.parse(localStorage.getItem("strsrc_dqk"));
31                             arr_floorroom=arr_temp;
32                             arr_palpha=JSON.parse(localStorage.getItem("arr_palpha"));
33                             pbeta=JSON.parse(localStorage.getItem("pbeta"));
34 
35                         }
36                         else
37                         {
38                             for(var i=min_floor;i<=max_floor;i++)//读取每一层的数据
39                             {
40                                 Url="http://127.0.0.1:8082/query.do?jsessionid="+jsessionid;
41                                 Argv="sql=select id,beta,pbeta,alpha,palpha,weight,floor,room from tab_dqk" +
42                                         " where planetid='test' and floor="+i;//查找这个行星的地区块层数
43                                 //使用同步Ajax请求保证进度同步
44                                 Request(xmlHttp,"POST",Url,false,Argv,"application/x-www-form-urlencoded",QueryCallBack,0);
45                             }
46                         }
47                         localStorage.setItem("arr_floorroom",JSON.stringify(arr_floorroom));
48                         localStorage.setItem("arr_palpha",JSON.stringify(arr_palpha));
49                         localStorage.setItem("pbeta",JSON.stringify(pbeta));
50                         //大小超过了本地存储限制
51                         xmlHttp.abort();
52                         DrawPlanet();//绘制行星

3.下面就可以使用axios获取数据了

无论是什么协议它们都有一个共同点,就是用来规范/约束某一类事物

在进行glsl编程之前,一个重要的步骤是选择要使用的WebGL版本:

import axios from 'axios'

Vue.prototype.$http = axios

沟通最常见的问题就是语言不通,例如中国人和美国人沟通,一个人说中文,一个人说英文,如果两个人都不懂中文或者英文,那么就会出现沟通问题

Babylon.js源码里包括很多实用的3D编程工具,即使不使用Babylon.js引擎也可以使用其中的工具简化原生WebGL开发。

2.在main.js里面导入axios

HTTP协议就是相当于我们让两个人都说中文或者都说英文一样,就是提前规范两个人之间如何沟通,也就是规范/约束浏览器和服务器之间如何沟通

1、生成地区块的基本数据结构:

  1. 安装axios

    $ npm install axios

HTTP是Hypertext Transfer Protocol的缩写,译为:超文本传输协议

其中id是计算出来的索引,另外glsl的for循环的中段也不支持“i<len”这种写法,i必须小于一个明确的常数。

 

沟通问题?

借助这一方法,我们把datatexture(数据纹理)设置为边长是2的整数次幂的正方形图片。在原生WebGL中,纹理图片的边长必须是2的整数次幂,否则会发生错误,而Babylon.js虽然支持使用任意尺寸的图片,但非标准图片在传入显卡时会自动进行线性采样模式的拉伸,而导致图片颜色交界处的模糊,这种模糊对于数据纹理准确性的影响是致命的。

// 发送get请求

// 向具有指定ID的用户发出请求
this.$http.get('/user?ID=12345')
  .then(response => {
    console.log(response);
  })
// 错误处理
  .catch(error => {
    console.log(error);
  });
// 也可以通过 params 对象传递参数
$http.get('/user', {
    params: {
      ID: 12345
    }
  })
   .then(response => {
    console.log(response);
  })
// 错误处理
  .catch(error => {
    console.log(error);
  });

// 发送post请求
this.$http.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(response => {
    console.log(response);
  })
  .catch(error => {
    console.log(error);
  });

如果想解决沟通问题,是不是需要先拟定规定,两个人都说中文或者两个人都说英文,或者请一个既懂中文又懂英文的翻译

View Code

在现实生活中有很多的协议,例如租房协议/买卖协议/离婚协议

 1 function getLandtypeDqk(obj)
 2     {
 3         var height=obj.altitude;//对于这个地区块
 4         var beta=obj.beta;
 5         var rate_land=Math.random();
 6         for(key in tab_landtypedqk)//这个方法并不能保证顺序!!!!//for key和eval占用了大量时间????
 7         {//按顺序查找每一个地区块级地形是否符合条件,
 8             if(eval(tab_landtypedqk[key].eval))//JavaScript语言的一大特点是可以随时把字符串转化为可执行代码,
 9             {//这使得JavaScript语言可以非常灵活,但是会降低执行效率和安全性
10                 obj.type1=key;
11                 var count_rate=0;//用来累加概率
12                 var obj1=tab_landtypedqk[key];
13                 for(key2 in obj1)
14                 {
15                     if(key2!="eval")
16                     {
17                         var rate_type2=Math.random();
18                         count_rate+=obj1[key2].rate;
19                         if(rate_type2<count_rate)
20                         {
21                             obj.type2=key2;
22                             obj.effect=obj1[key2].effect;//对周边地块的影响程度
23                             break;
24                         }
25                     }
26                 }
27                 break;
28             }
29         }
30         if (!obj.type1)//如果这个地区块没有被分配地形
31         {
32             obj.type1="未定义";
33             obj.type2="默认dqk";
34             obj.effect=0;
35         }
36         obj.landtypedqk={};//这三个变量用于对地形进行平滑处理
37         obj.landtypedqk[obj.type2]=obj.effect;
38         obj.landtypedqkeffect=obj.effect;
39     }

什么是协议?

图片 1

 1 Effect.prototype._loadFragmentShader = function (fragment, callback) {
 2             // DOM element ?着色器代码是DOM标签中的内容
 3             if (fragment instanceof HTMLElement) {
 4                 var fragmentCode = BABYLON.Tools.GetDOMTextContent(fragment);
 5                 callback(fragmentCode);
 6                 return;
 7             }
 8             // Base64 encoded ?着色器代码使用了base64编码
 9             if (fragment.substr(0, 7) === "base64:") {
10                 var fragmentBinary = window.atob(fragment.substr(7));
11                 callback(fragmentBinary);
12                 return;
13             }
14             // Is in local store ?着色器代码在Babylon.js自带的着色器代码库里
15             if (Effect.ShadersStore[fragment + "PixelShader"]) {
16                 callback(Effect.ShadersStore[fragment + "PixelShader"]);
17                 return;
18             }
19             if (Effect.ShadersStore[fragment + "FragmentShader"]) {
20                 callback(Effect.ShadersStore[fragment + "FragmentShader"]);
21                 return;
22             }
23             var fragmentShaderUrl;//着色器代码是一个单独的文件,需要通过Ajax加载
24             if (fragment[0] === "." || fragment[0] === "/" || fragment.indexOf("http") > -1) {
25                 fragmentShaderUrl = fragment;
26             }
27             else {//默认情况下Engine.ShadersRepository = "src/Shaders/";
28                 fragmentShaderUrl = BABYLON.Engine.ShadersRepository + fragment;
29             }
30             // Fragment shader
31             BABYLON.Tools.LoadFile(fragmentShaderUrl + ".fragment.fx", callback);
32         };

在glsl中使用长数组的另一个问题是:glsl竟然不支持直接用临时赋值的变量作为数组索引!类似

 1 //根据正方形边长找大于size的最小的2的整数次幂
 2 newland.FindPower=function(size)
 3 {
 4     var int1=Math.ceil(Math.log2(size));
 5     return Math.pow(2,int1);
 6 }
 7 //根据数据长度找最小的2的整数次幂
 8 newland.FindPower2=function(len)
 9 {
10     var int1=Math.sqrt(len);
11     return this.FindPower(int1);
12 }

 

图片 2

图片 3图片 4

2、WebGL版本选择:

然后将一张纹理贴图的纹理坐标对应到球体网格中的每个三角形上,具体原理如下:

  1 //使用正态随机数和加和平均确定每个地区块的海拔
  2     function CookDqk2()
  3     {
  4         var len=arr_floorroom.length;
  5         //生成初始的随机正态随机海拔
  6         console.log("生成初始的随机正态随机海拔");
  7         for(var i=0;i<len;i++)
  8         {
  9             //console.log(i+" in "+len);
 10             var len2=arr_floorroom[i].length;
 11             for(var j=0;j<len2;j++)
 12             {
 13                 var obj=arr_floorroom[i][j];
 14                 obj.altitude=dc1.getNumberInNormalDistribution(-10,1000);//平均海拔是-10,常见的海拔在正负1000以内
 15                 if(obj.altitude<-10000)
 16                 {
 17                     obj.altitude=-10000;
 18                 }
 19                 else if(obj.altitude>10000)
 20                 {
 21                     obj.altitude=10000;
 22                 }
 23                 obj.countcook=1;
 24                 if(i%2==1)//如果是奇数层,room偏移一个识别范围,这样地形看起来更自然
 25                 {
 26                     obj.alpha+=obj.palpha;
 27                 }
 28             }
 29         }
 30         //使用加和平均方法使海拔趋于连续(高度平滑)
 31         console.log("使用加和平均方法使海拔趋于连续");
 32         for(var i=0;i<len;i++)//将地区块的海拔和周围相邻的所有地区块的海拔相加取平均值,作为这个地区块的海拔
 33         {
 34             console.log(i+" in "+len);
 35             var len2=arr_floorroom[i].length;
 36             for(var j=0;j<len2;j++)
 37             {
 38                 var obj=arr_floorroom[i][j];
 39                 obj.altitude1=obj.altitude;
 40                 if(i>0)//考虑这个room下面的floor
 41                 {
 42                     //var alpha=obj.alpha;
 43                     var len3=arr_floorroom[i-1].length;
 44                     for(var k=0;k<len3;k++)//遍历下层的room
 45                     {
 46                         var subplpha=Math.abs(arr_floorroom[i-1][k].alpha-obj.alpha);
 47                         if(subplpha>Math.PI)
 48                         {
 49                             subplpha=Math.PI*2-subplpha;
 50                         }
 51                         if(subplpha<=(obj.palpha+arr_floorroom[i-1][k].palpha))
 52                         {//对这个地区块有影响
 53                             obj.altitude1+=arr_floorroom[i-1][k].altitude;
 54                             obj.countcook++;
 55                         }
 56                     }
 57 
 58                 }
 59                 if(i<len-1)//考虑这个room上面的floor
 60                 {
 61                     var len3=arr_floorroom[i+1].length;
 62                     for(var k=0;k<len3;k++)//遍历上层的room
 63                     {
 64                         var subplpha=Math.abs(arr_floorroom[i+1][k].alpha-obj.alpha);
 65                         if(subplpha>Math.PI)
 66                         {
 67                             subplpha=Math.PI*2-subplpha;
 68                         }
 69                         if(subplpha<=(obj.palpha+arr_floorroom[i+1][k].palpha))
 70                         {//对这个地区块有影响
 71                             obj.altitude1+=arr_floorroom[i+1][k].altitude;
 72                             obj.countcook++;
 73                         }
 74                     }
 75                 }
 76                 //考虑本层的相邻元素
 77                 if(j==0)
 78                 {
 79                     obj.altitude1+=arr_floorroom[i][1].altitude;
 80                     obj.altitude1+=arr_floorroom[i][len2-1].altitude;
 81                     obj.countcook+=2;
 82                 }else if(j==(len2-1))
 83                 {
 84                     obj.altitude1+=arr_floorroom[i][0].altitude;
 85                     obj.altitude1+=arr_floorroom[i][len2-2].altitude;
 86                     obj.countcook+=2;
 87                 }
 88                 else{
 89                     obj.altitude1+=arr_floorroom[i][j-1].altitude;
 90                     obj.altitude1+=arr_floorroom[i][j+1].altitude;
 91                     obj.countcook+=2;
 92                 }
 93             }
 94         }
 95         var min_altitude= 0,max_altitude=0;
 96         console.log("去除总权值");
 97         for(var i=0;i<len;i++)
 98         {
 99             console.log(i+" in "+len);
100             var len2=arr_floorroom[i].length;
101             for(var j=0;j<len2;j++)
102             {
103                 var obj=arr_floorroom[i][j];
104                 obj.altitude=obj.altitude1/obj.countcook;
105                 if(obj.altitude<min_altitude)
106                 {
107                     min_altitude=obj.altitude;
108                 }
109                 if(obj.altitude>max_altitude)
110                 {
111                     max_altitude=obj.altitude;
112                 }
113                 //delete obj.altitude1;
114             }
115         }
116         console.log("最低、最高海拔为:"+min_altitude+"、"+max_altitude);
117         //根据海拔高度与概率规则确定海洋与陆地,根据纬度和高度确定陆地的类型(高度达到一定程度后优于纬度)
118         CookDqk3();
119     }

1、在Babylon.js引擎中使用自定义着色器:

c、处理每一层的地区块数据:

View Code

  1 function CookDqk3()
  2     {
  3         console.log("开始生成地区块级地形");
  4         var len=arr_floorroom.length;
  5         for(var i=0;i<len;i++) {
  6             console.log(i+" in "+len);
  7             var len2 = arr_floorroom[i].length;
  8             for (var j = 0; j < len2; j++)
  9             {
 10                 var obj=arr_floorroom[i][j];
 11                 getLandtypeDqk(obj);//根据规则确定这个地区块的地形
 12             }
 13         }
 14         //地区块平滑
 15         console.log("地区块平滑");
 16         for(var i=0;i<len;i++)
 17         {
 18             console.log(i+" in "+len);
 19             var len2=arr_floorroom[i].length;
 20             for(var j=0;j<len2;j++)
 21             {
 22                 var obj=arr_floorroom[i][j];
 23 
 24                 if(i>0)//考虑这个room下面的floor
 25                 {
 26                     //var alpha=obj.alpha;
 27                     var len3=arr_floorroom[i-1].length;
 28                     for(var k=0;k<len3;k++)//遍历下层的room
 29                     {
 30                         var obj1=arr_floorroom[i-1][k];
 31                         var subplpha=Math.abs(obj1.alpha-obj.alpha);
 32                         if(subplpha>Math.PI)
 33                         {
 34                             subplpha=Math.PI*2-subplpha;
 35                         }
 36                         if(subplpha<=(obj.palpha+obj1.palpha))
 37                         {//对这个地区块有影响
 38                             if(!obj.landtypedqk[obj1.type2])
 39                             {
 40                                 obj.landtypedqk[obj1.type2]=obj1.effect;//这一种地形的权重
 41                             }
 42                             else
 43                             {
 44                                 obj.landtypedqk[obj1.type2]+=obj1.effect;
 45                             }
 46                             obj.landtypedqkeffect+=obj1.effect;//所有地形的权重
 47                         }
 48                     }
 49 
 50                 }
 51                 if(i<len-1)//考虑这个room上面的floor
 52                 {
 53                     var len3=arr_floorroom[i+1].length;
 54                     for(var k=0;k<len3;k++)//遍历上层的room
 55                     {
 56                         var obj1=arr_floorroom[i+1][k];
 57                         var subplpha=Math.abs(obj1.alpha-obj.alpha);
 58                         if(subplpha>Math.PI)
 59                         {
 60                             subplpha=Math.PI*2-subplpha;
 61                         }
 62                         if(subplpha<=(obj.palpha+obj1.palpha))
 63                         {//对这个地区块有影响
 64                             if(!obj.landtypedqk[obj1.type2])
 65                             {
 66                                 obj.landtypedqk[obj1.type2]=obj1.effect;
 67                             }
 68                             else
 69                             {
 70                                 obj.landtypedqk[obj1.type2]+=obj1.effect;
 71                             }
 72                             obj.landtypedqkeffect+=obj1.effect;
 73                         }
 74                     }
 75                 }
 76                 //考虑本层的相邻元素
 77                 if(j==0)
 78                 {
 79                     var obj1=arr_floorroom[i][1];
 80                     if(!obj.landtypedqk[obj1.type2])
 81                     {
 82                         obj.landtypedqk[obj1.type2]=obj1.effect;
 83                     }
 84                     else
 85                     {
 86                         obj.landtypedqk[obj1.type2]+=obj1.effect;
 87                     }
 88                     obj.landtypedqkeffect+=obj1.effect;
 89                     var obj1=arr_floorroom[i][len2-1];
 90                     if(!obj.landtypedqk[obj1.type2])
 91                     {
 92                         obj.landtypedqk[obj1.type2]=obj1.effect;
 93                     }
 94                     else
 95                     {
 96                         obj.landtypedqk[obj1.type2]+=obj1.effect;
 97                     }
 98                     obj.landtypedqkeffect+=obj1.effect;
 99                 }
100                 else if(j==(len2-1))
101                 {
102                     var obj1=arr_floorroom[i][0];
103                     if(!obj.landtypedqk[obj1.type2])
104                     {
105                         obj.landtypedqk[obj1.type2]=obj1.effect;
106                     }
107                     else
108                     {
109                         obj.landtypedqk[obj1.type2]+=obj1.effect;
110                     }
111                     obj.landtypedqkeffect+=obj1.effect;
112                     var obj1=arr_floorroom[i][len2-2];
113                     if(!obj.landtypedqk[obj1.type2])
114                     {
115                         obj.landtypedqk[obj1.type2]=obj1.effect;
116                     }
117                     else
118                     {
119                         obj.landtypedqk[obj1.type2]+=obj1.effect;
120                     }
121                     obj.landtypedqkeffect+=obj1.effect;
122                 }
123                 else{
124                     var obj1=arr_floorroom[i][j-1];
125                     if(!obj.landtypedqk[obj1.type2])
126                     {
127                         obj.landtypedqk[obj1.type2]=obj1.effect;
128                     }
129                     else
130                     {
131                         obj.landtypedqk[obj1.type2]+=obj1.effect;
132                     }
133                     obj.landtypedqkeffect+=obj1.effect;
134                     var obj1=arr_floorroom[i][j+1];
135                     if(!obj.landtypedqk[obj1.type2])
136                     {
137                         obj.landtypedqk[obj1.type2]=obj1.effect;
138                     }
139                     else
140                     {
141                         obj.landtypedqk[obj1.type2]+=obj1.effect;
142                     }
143                     obj.landtypedqkeffect+=obj1.effect;
144                 }
145             }
146         }
147         console.log("对每个地区块进行加权并入库");
148         for(var i=0;i<len;i++)//对每个地区块进行加权,这段代码执行很慢
149         {
150             var len2=arr_floorroom[i].length;
151             console.log(i+" in "+len);
152             for(var j=0;j<len2;j++)
153             {
154 
155                 var obj=arr_floorroom[i][j];
156                 obj.altitude=obj.altitude/obj.countcook;
157                 var rate_type1final=Math.random()*obj.landtypedqkeffect;
158                 var rate_type1final_count=0;
159                 obj.type2final="默认dqk";
160                 for(key in obj.landtypedqk)
161                 {
162                     rate_type1final_count+=obj.landtypedqk[key];//这一种地形的权重
163                     if(rate_type1final<rate_type1final_count)//如果随机数小于这种地形的累积权重
164                     {
165                         obj.type2final=key;
166                         break;
167                     }
168                 }
169                 //在这里把这个地区块插入数据库?不知道什么原因POST方法失败了,改用GET方法
170                 /*Url="http://127.0.0.1:8082/query.do?jsessionid="+jsessionid;
171                 Argv="sql=insert into tab_dqk values(uuid(),'test1',"+obj.beta+","+obj.pbeta+","+obj.alpha+","+obj.palpha+",'"
172                         +obj.type2final+"',"+obj.floor+","+obj.room+","+obj.altitude+")";
173                 //使用同步Ajax请求保证进度同步,在连续使用同步Ajax时不需要xmlHttp.abort()!!!!
174                 Request(xmlHttp,"POST",Url,false,Argv,"application/x-www-form-urlencoded",PushChessCallBack,0);*/
175                 Url="http://127.0.0.1:8082/query.do?jsessionid="+jsessionid+"&sql=insert into tab_dqk values(uuid(),'test1',"+obj.beta+","+obj.pbeta+","+obj.alpha+","+obj.palpha+",'"
176                         +obj.type2final+"',"+obj.floor+","+obj.room+","+obj.altitude+")"
177                 Argv="";
178                 Request(xmlHttp,"GET",Url,false,Argv,"application/x-www-form-urlencoded",PushChessCallBack,0);
179             }//这里改变了一下数据结构,直接用weight字段存储确定了的地区块级地形
180         }
181         CookDqk4();//着色
182     }

假设行星的周长为40000km,将每个地块设为长宽均为100km的正方形,生成并保存一个包含50000多个地块的棋盘型地面:

为了避开上述缺点,我决定采用另一种球体纹理绘制方式。

 1 --建立地区块表
 2 create table tab_dqk (
 3 ID varchar(40) NOT NULL,
 4 planetid varchar(40),
 5 beta double,
 6 pbeta double,
 7 alpha double,
 8 palpha double,
 9 weight varchar(1000)
10 );
11 comment on table tab_dqk is '地区块表';
12 comment on column tab_dqk.id is '主键ID';
13 comment on column tab_dqk.planetid is '地区块所属的行星id';
14 comment on column tab_dqk.beta is '地区块的仰角';
15 comment on column tab_dqk.pbeta is '地区块仰角的区分度';--即这个beta仰角上下pbeta弧度都属于这一层
16 comment on column tab_dqk.alpha is '地区块水平转角';
17 comment on column tab_dqk.palpha is '地区块水平转角的区分度';--即这个alpha水平转角左右palpha弧度都属于这个房间
18 comment on column tab_dqk.weight is '用JSON表示的地形类型id权重';
19 
20 alter table tab_dqk add column floor int;
21 alter table tab_dqk add column room int;
22 alter table tab_dqk add column altitude double;
23 
24 comment on column tab_dqk.floor is '地区块位于第几层';
25 comment on column tab_dqk.room is '地区块位于这一层的第几个房间';
26 comment on column tab_dqk.altitude is '地区块的海拔高度';
27 comment on column tab_dqk.weight is '地区块类型';

 1 --建立行星表
 2 create table tab_planet
 3 (
 4 id varchar(40) NOT NULL,
 5 name varchar(20) NOT NULL,
 6 coreid varchar(40),
 7 min_floor int NOT NULL,
 8 max_floor int NOT NULL,
 9 width_room int NOT NULL,
10 radius double,
11 mass double,
12 gravity double,
13 orbit double,
14 cycle double
15 );
16 comment on table tab_planet is '行星表';
17 comment on column tab_planet.id is '主键ID';
18 comment on column tab_planet.name is '行星名字';
19 comment on column tab_planet.coreid is '围绕旋转的主星id';
20 comment on column tab_planet.min_floor is '最低层数';
21 comment on column tab_planet.max_floor is '最高层数';
22 comment on column tab_planet.width_room is '数据宽度';
23 comment on column tab_planet.radius is '半径(km)';
24 comment on column tab_planet.mass is '质量(t)';
25 comment on column tab_planet.gravity is '重力加速度';
26 comment on column tab_planet.orbit is '同步轨道高度';
27 comment on column tab_planet.cycle is '自转周期';
28 
29 alter table tab_planet add column perimeter int;
30 
31 comment on column tab_planet.perimeter is '行星周长';

图片 5

片元着色器:

但是我认为这个实验中的所有参与者都是可信任的,所以为了程序的简洁要尝试去掉后台程序,我发现h2数据库服务支持http协议通信,通过使用Fiddler对h2的网页控制台进行抓包,编写了直接用浏览器和数据库通信的代码:(代码在Linkh2.js中)

 1 uniform mat4 worldViewProjection;
 2 uniform mat4 worldView;
 3 attribute vec3 position;
 4 
 5 varying vec3 vPosition;
 6 
 7 void main(){
 8     gl_Position=worldViewProjection*vec4(position,1);    
 9     vPosition=vec3(worldView*vec4(position,1));
10 }

View Code

数据中包含了每个地区块的“层数”和“房间号”信息,我的思路是把这些信息传入显卡,由片元着色器程序算出每个片元所属的房间,然后在传入的数据中找到这个房间的颜色,这个思路类似OpenGL中的3D纹理。

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>演示球体的绘制</title>
 6     <link href="../../CSS/newland.css" rel="stylesheet">
 7     <link href="../../CSS/stat.css" rel="stylesheet">
 8     <script src="../../JS/LIB/babylon.32.all.max.js"></script>
 9     <script src="../../JS/LIB/stat.js"></script>
10 </head>
11 <body>
12 <div id="div_allbase">
13     <canvas id="renderCanvas"></canvas>
14     <div id="fps" style="z-index: 301;"></div>
15 </div>
16 </body>
17 <script>
18     var canvas,engine,scene,gl;
19     canvas = document.getElementById("renderCanvas");
20     engine = new BABYLON.Engine(canvas, true);
21     gl=engine._gl;//决定在这里结合使用原生OpenGL和Babylon.js;
22     scene = new BABYLON.Scene(engine);
23     var divFps = document.getElementById("fps");
24     //全局对象
25     var light0//全局光源
26             ,camera0//主相机
27             ;
28     window.onload=webGLStart;
29     window.addEventListener("resize", function () {
30         engine.resize();
31     });
32     function webGLStart()
33     {
34         gl=engine._gl;
35         createScene();
36         MyBeforeRender();
37     }
38     var createScene = function (engine) {
39         camera0 =new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, -20), scene);
40         camera0.attachControl(canvas, true);
41         camera0.speed=0.5;
42         camera0.minZ=0.0001;
43         light0 = new BABYLON.HemisphericLight("Hemi0", new BABYLON.Vector3(0, 1, 0), scene);
44         sphere1=BABYLON.MeshBuilder.CreateSphere("sphere1",{segments:10,diameter:10.0},scene);
45         var groundMaterial = new BABYLON.StandardMaterial("groundMat", scene);
46         groundMaterial.wireframe=true;
47         sphere1.material=groundMaterial;
48 
49     }
50     function MyBeforeRender()
51     {
52         scene.registerBeforeRender(function() {
53             if(scene.isReady())
54             {
55 
56             }
57         });
58         engine.runRenderLoop(function () {
59             engine.hideLoadingUI();
60             if (divFps) {
61                 // Fps
62                 divFps.innerHTML = engine.getFps().toFixed() + " fps";
63             }
64             scene.render();
65         });
66 
67     }
68 </script>
69 </html>
1 int i=1;
2 float f=arr[i+1];

4、着色器代码:

 1 function CookDqk4()
 2     {
 3         var len=arr_floorroom.length;
 4         //开始生成数据纹理
 5         console.log("开始生成数据纹理");
 6         for(var i=0;i<len;i++) //每一行
 7         {
 8             //console.log(i+" in "+len);
 9             var len2 = arr_floorroom[i].length;
10             for (var j = 0; j < len2; j++) {
11                 var obj = arr_floorroom[i][j];
12                 var index= (i)*4*can_temp.width+(j-1)*4;//每个room由4个元素组成
13                 var color4=[];
14                 if(tab_landtypedqk2[obj.type2final].color)
15                 {//从地形对象中获取颜色
16                     color4=tab_landtypedqk2[obj.type2final].color;
17                 }
18                 else
19                 {
20                     color4=[250,126,126];//默认纹理远观颜色
21                 }
22                 imagedata_temp.data[index]=color4[0];//这里存的真的是颜色
23                 imagedata_temp.data[index+1]=color4[1];
24                 imagedata_temp.data[index+2]=color4[2];
25                 imagedata_temp.data[index+3]=255;
26 
27             }
28         }
29 
30     }

palpha是水平区分度,表示每个房间的中心到房间墙壁的弧度,显然越靠近两极房间越少,水平区分的值也就越高,arr_palpha保存了每一层的水平区分度,是一个长度为199的数组。

a、顶点着色器:

这里我只选择了将每个顶点的位置传递给着色器,Babylon.js引擎替我们进行了编译链接着色器程序、绑定缓存等一系列操作(Babylon.js中以“_”开头的变量一般都是在渲染过程中建立的,只有在渲染开始后才有值)。

 1 //将一个浮点数组转化为DataTexture,这是浮点数小于1的情况,要注意canvas和webgl对颜色属性的自动处理!!!!
 2 newland.TranArrToPng1=function(arr,width,height)
 3 {
 4     var can_temp=document.createElement("canvas");
 5     can_temp.width=width;
 6     can_temp.height=height;
 7     var context=can_temp.getContext("2d");
 8     context.fillStyle="rgba(0,0,255,1)";//多余的位都是1?
 9     context.fillRect(0,0,width,height);
10     var imagedata=context.getImageData(0,0,width,height);
11     var len=arr.length;//小数部分会自动四舍五入!!!!默认palpha必定小于1
12     for(var i=0;i<len;i+=1)
13     {
14         var str_num=arr[i]+"";
15         //var int_0=str_num.indexOf();
16         var len_str=str_num.length;
17         var count_0=0;
18         for(var j=0;j<len_str;j++)
19         {
20             if(str_num[j]=="0"||str_num[j]==".")
21             {
22                 continue;
23             }
24             else
25             {
26                 count_0=j;//找到第一个非零数
27                 break;
28             }
29         }
30         var num1=parseInt(str_num.substr(count_0,2));
31         var num2=parseInt(str_num.substr(count_0+2,2));
32         //var num3=parseInt(str_num.substr(count_0+4,2));
33         var num4=4+(count_0-2);
34         imagedata.data[i*4]=num1;//科学计数法:用像素颜色的第一第二个分量保存四位有效数字,用第四个分量保存10的负指数
35         imagedata.data[i*4+1]=num2;
36         imagedata.data[i*4+2]=num4;
37         //imagedata.data[i*4+3]=num4;
38     }
39     context.putImageData(imagedata,0,0);
40     var strsrc_palpha=can_temp.toDataURL("image/png");
41     //can_temp.dispose();
42     can_temp=null;
43     return strsrc_palpha;
44 }

1、数据保存:

这里设定每一个100km*100km的地区块可以由更小的“地貌块”组成,在极近时地貌块的地形显示为实际的纹理图,在较远时地貌块表现为纹理图的平均色,在更远一些时用地区块代替地貌块,地区块的颜色为地貌块的加权。

要将计算结果作为数组的索引只能使用if else或者switch
case枚举出每一种对应的情况,或者使用:

一、在球体网格上显示纹理的传统方法:

可以看到每个地区块的边界清晰可见,没有发生模糊。

 1 // GL
 2             if (!options.disableWebGL2Support) {
 3                 try {
 4                     this._gl = (canvas.getContext("webgl2", options) || canvas.getContext("experimental-webgl2", options));
 5                     if (this._gl) {
 6                         this._webGLVersion = 2.0;
 7                     }
 8                 }
 9                 catch (e) {
10                     // Do nothing
11                 }
12             }
13             if (!this._gl) {
14                 if (!canvas) {
15                     throw new Error("The provided canvas is null or undefined.");
16                 }
17                 try {
18                     this._gl = (canvas.getContext("webgl", options) || canvas.getContext("experimental-webgl", options));
19                 }
20                 catch (e) {
21                     throw new Error("WebGL not supported");
22                 }
23             }
24             if (!this._gl) {
25                 throw new Error("WebGL not supported");
26             }

然而使用datatexture时又遇到一个问题,canvas会自动把颜色分量转化为0到255的整数,而这里的水平区分度全是0到1之间的小数,会被自动转为0或1,为解决这一问题把水平区分度数据转化为科学计数法并用像素表示:

执行代码效果如下:

可见,随着相机的移动,球体的纹理自动发生变化,这类效果是很难用贴图方式实现的。

a、在数据库中建表:

b、处理获得的行星信息,据此获取每个地区块的数据:(这段代码的执行效率较低)

数据查询和显示代码如下:(testdatatexture.html)

 1 //用glsl和Babylon.js结合的方式绘制行星
 2     function DrawPlanet()
 3     {
 4         var amigaMaterial = new BABYLON.ShaderMaterial("amiga2", scene,{
 5                     vertexElement: "sh2v4.sh",
 6                     fragmentElement: "sh2f4.sh",
 7                 },
 8                 {
 9                     attributes: ["position"],
10                     uniforms: ["worldViewProjection","worldView"]
11                 });
12         amigaMaterial.doNotSerialize=true;
13         sphere1.material=amigaMaterial;
14         if(strsrc_dqk=="")
15         {
16             context_temp.putImageData(imagedata_temp,0,0);
17             strsrc_dqk=can_temp.toDataURL("image/png");//将canvas转化为dataurl
18             localStorage.setItem("strsrc_dqk",JSON.stringify(strsrc_dqk));
19         }
20         var utexturedqk = new BABYLON.Texture.CreateFromBase64String(strsrc_dqk,"utexturedqk", scene
21                 ,false,false,BABYLON.Texture.NEAREST_NEAREST);//将dataurl转化为Babylon.js纹理
22         amigaMaterial.setTexture("utexturedqk",utexturedqk);//将纹理和显卡采样器关联
23         amigaMaterial.setFloat("wid_utexturedqk",can_temp.width);//数据纹理宽度,将内存中的变量和显卡中的通用变量关联
24         amigaMaterial.setFloat("hei_utexturedqk",can_temp.width);
25         amigaMaterial.setFloat("pbeta",pbeta);//层间区分角度
26 
27         var size=newland.FindPower2(arr_palpha.length);//注意!!!!
28         var strsrc_palpha=newland.TranArrToPng1(arr_palpha,size,size);//每一层内的房间区分角度,用4个元素保存一个浮点数
29         var utexturepalpha = new BABYLON.Texture.CreateFromBase64String(strsrc_palpha,"utexturepalpha", scene
30                 ,true,false,BABYLON.Texture.NEAREST_NEAREST);
31         amigaMaterial.setTexture("utexturepalpha",utexturepalpha);
32         amigaMaterial.setFloat("wid_utexturepalpha",size);//room区分度的纹理宽度
33         amigaMaterial.setFloat("hei_utexturepalpha",size);
34 
35         amigaMaterial.setFloat("uarrpalphalen",arr_palpha.length);
36         amigaMaterial.setFloat("max_floorf",max_floor);//Babylon.js不支持传递整形量??GpenGL中int也是以float形式计算的!!!!
37         amigaMaterial.setFloat("MathPI",Math.PI);
38 
39         amigaMaterial.onCompiled=function()//Babylon.js文档中写effect是material的一个内容,而material需要一个“编译过程”,编译之后的material才具备effect属性
40         {//而且对Babylon.js来说,material能传递的变量类型比较少,比如不能传递整形量,而effect则可以传递更多的数据类型
41          //amigaMaterial.getEffect().setArray("uarrpalpha",arr);//每一层水平区分度*/effect可以向显卡传递数组

           //console.log(amigaMaterial.getEffect());        
      }

42     }

下一步准备给地区块添加鼠标交互,和更细节的地貌块显示。

github地址:

将行星想象为一个一半在地上一半在地下的建筑,不同的纬度对应了不同的层数,每一层有若干个大小相同的房间

可见WebGL1.0对应早期的OpenGL2.x,WebGL2.0对应较新的OpenGL4.x,显然WebGL2.0的功能更为强大,但考虑到我的笔记本显卡不支持WebGL2.0,只好使用旧的WebGL1.0。本文后面的glsl编程均使用OpenGL2.0的语法,OpenGL2.0存在很多缺陷,所以后面的部分内容也正是为了解决这些缺陷而编写的。

 1 //地区块地形元素分布表
 2 var beta_2326=((23+26/60)/180)*Math.PI;//南北回归线弧度
 3 var beta_6034=((60+34/60)/180)*Math.PI;//南北极圈弧度
 4 var beta_8=((8)/180)*Math.PI;//赤道附近弧度
 5 var tab_landtypedqk={//rate按从小到大排列生成的随机数小于哪个就定为何种地形,effect在卷积平滑阶段起作用,表示这个地形对周围环境的影响程度
 6     "热带海洋":{eval:"height<0&&rate_land<0.9&&Math.abs(beta)<beta_2326","热带海洋dqk":{rate:1,effect:1}},//eval是判断地区块大类型的判断条件,以后在设计技能效果时也可能要借鉴这里
 7     "温带海洋":{eval:"height<0&&rate_land<0.9&&Math.abs(beta)>beta_2326&&Math.abs(beta)<beta_6034","温带海洋dqk":{rate:1,effect:1}},
 8     "寒带海洋":{eval:"height<0&&rate_land<0.9&&Math.abs(beta)>beta_6034","寒带海洋dqk":{rate:1,effect:1}},
 9     "温带1500米以下":{eval:"rate_land>0.1&&Math.abs(beta)>beta_2326&&Math.abs(beta)<beta_6034&&height<1500","草原dqk":{rate:0.4,effect:1},"森林dqk":{rate:0.4,effect:1},"戈壁dqk":{rate:0.2,effect:2}},
10     "温带1500米以上":{eval:"rate_land>0.1&&Math.abs(beta)>beta_2326&&Math.abs(beta)<beta_6034&&height>=1500","雪山dqk":{rate:1,effect:1}},
11     "亚热带3000米以下":{eval:"rate_land>0.1&&Math.abs(beta)>beta_8&&Math.abs(beta)<beta_2326&&height<3000","热带雨林dqk":{rate:0.5,effect:1},"稀树草原dqk":{rate:0.5,effect:1}},
12     "亚热带3000米以上":{eval:"rate_land>0.1&&Math.abs(beta)>beta_8&&Math.abs(beta)<beta_2326&&height>=3000","雪山dqk":{rate:1,effect:1}},
13     "热带3000米以下":{eval:"rate_land>0.1&&Math.abs(beta)<beta_8&&height<3000","热带雨林dqk":{rate:0.5,effect:1},"沙漠dqk":{rate:0.5,effect:2}},
14     "热带3000米以上":{eval:"rate_land>0.1&&Math.abs(beta)<beta_8&&height>=3000","雪山dqk":{rate:1,effect:1}},
15     "寒带-100米以下":{eval:"rate_land>0.1&&Math.abs(beta)>beta_6034&&height<-100","草原dqk":{rate:0.4,effect:1},"森林dqk":{rate:0.4,effect:1},"戈壁dqk":{rate:0.2,effect:2}},
16     "寒带-100到200米以内":{eval:"rate_land>0.1&&Math.abs(beta)>beta_6034&&height<200&&height>=-100","寒带森林dqk":{rate:0.6,effect:1},"冰川dqk":{rate:0.4,effect:1}},
17     "寒带200米以上":{eval:"rate_land>0.1&&Math.abs(beta)>beta_6034&&height>200","冰川dqk":{rate:1,effect:1}}
18 }
19 var tab_landtypedqk2={//每一种地区块的远观颜色和内部地貌块(单位块?)占比
20     "默认dqk":{color:[250,126,126],content:{"红白格dmk":{rate:1,effect:0}}},//完全红白格,这种表示错误和未定义的地貌块不会影响周围
21     "热带海洋dqk":{color:[15,63,105],content:{"海洋水面dmk":{rate:0.99,effect:1},"雨林dmk":{rate:0.995,effect:0},"沙滩dmk":{rate:1,effect:0}}},
22     "温带海洋dqk":{color:[15,63,105],content:{"海洋水面dmk":{rate:0.99,effect:1},"森林dmk":{rate:0.995,effect:0},"沙滩dmk":{rate:1,effect:0}}},
23     "寒带海洋dqk":{color:[15,63,105],content:{"海洋水面dmk":{rate:0.5,effect:1},"冰面dmk":{rate:1,effect:1}}},
24     "草原dqk":{color:[93, 153, 63],content:{"草地dmk":{rate:0.95,effect:1},"内陆水面dmk":{rate:1,effect:1}}},
25     "森林dqk":{color:[33,68,44],content:{"森林dmk":{rate:0.95,effect:1},"内陆水面dmk":{rate:1,effect:1}}},
26     "戈壁dqk":{color:[127, 102, 79],content:{"戈壁dmk":{rate:1,effect:1}}},
27     "雪山dqk":{color:[220, 221, 220],content:{"雪地dmk":{rate:0.8,effect:1},"岩石dmk":{rate:1,effect:0}}},
28     "热带雨林dqk":{color:[33,68,44],content:{"雨林dmk":{rate:0.95,effect:1},"内陆水面dmk":{rate:1,effect:1}}},
29     "稀树草原dqk":{color:[117, 118, 68],content:{"稀树草原dmk":{rate:0.95,effect:1},"内陆水面dmk":{rate:1,effect:1}}},
30     "沙漠dqk":{color:[175, 117, 68],content:{"沙地dmk":{rate:0.99,effect:1},"内陆水面dmk":{rate:0.995,effect:0},"绿洲dmk":{rate:1,effect:0}}},
31     "寒带森林dqk":{color:[],content:{"寒带森林dmk":{rate:0.85,effect:1},"雪地dmk":{rate:1,effect:1}}},
32     "冰川dqk":{color:[201, 216, 220],content:{"冰面dmk":{rate:0.85,effect:1},"雪地dmk":{rate:1,effect:1}}}
33 }
34 var tab_landtypedmk={//每一种地貌块的纹理url
35     "红白格dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/amiga.jpg",color:[250,126,126]},//对单位的影响,纹理Url,纹理的平均颜色
36     "海洋水面dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/sea.png",color:[15,63,105]},
37     "雨林dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/yulin.png",color:[33,68,44]},
38     "沙滩dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/shatan.png",color:[205, 160, 109]},
39     "森林dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/yulin.png",color:[33,68,44]},//没找到温带森林,暂时用雨林代替
40     "冰面dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/ice.png",color:[201, 216, 220]},
41     "草地dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/grass.png",color:[93, 153, 63]},
42     "内陆水面dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/lake.png",color:[93,143,180]},
43     "戈壁dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/gebi.png",color:[127, 102, 79]},
44     "雪地dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/snow.png",color:[220, 221, 220]},
45     "岩石dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/stone.png",color:[82, 81, 74]},
46     "稀树草原dmk":{eval_effect:"../../ASSETS/IMAGE/Texture_landtypedmk/xishucaoyuan.png",Url:"",color:[117, 118, 68]},
47     "沙地dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/sand.png",color:[175, 117, 68]},
48     "绿洲dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/lvzhou.png",color:[127, 144, 111]},
49     "寒带森林dmk":{eval_effect:"",Url:"../../ASSETS/IMAGE/Texture_landtypedmk/lvzhou.png",color:[127, 144, 111]}
50 
51 }

二、使用自定义着色器绘制自定义纹理:

发表评论

电子邮件地址不会被公开。 必填项已用*标注