//对于这一层中的每个room
19 {
20 var tds=trs[i].getElementsByTagName("td");
21 var int_room=parseInt(tds[7].innerHTML);
22 var arr_landtype={land_textblack:[0,0,0,255],land_textyellow:[255,255,0,255]}
23 // 保存在内存中的数据结构
24 // var obj=eval(tds[5].innerHTML);
25 var obj={};
26 eval("obj="+tds[5].innerHTML);
27 arr_floorroom[int_floor][int_room]={id:tds[0],beta:tds[1].innerHTML,pbeta:tds[2].innerHTML,alpha:tds[3].innerHTML
28 ,palpha:tds[4].innerHTML,weight:obj};
29 // 使用何种数据结构传递到显卡?使用一个超长数组arr_set4?《-这是不行的
30 var num1= 0,num2= 0,num3= 0,num4= 255;
31 for (key in obj)// 将每一种颜色的三个通道加权到一起
32 {
33 var num_key=obj[key];
34 num1+=(num_key*arr_landtype[key][0]);
35 num2+=(num_key*arr_landtype[key][1]);
36 num3+=(num_key*arr_landtype[key][2]);
37 }
38 var index= (int_floor+max_floor)*4*can_temp.width+(i-1)*4;// 每个room由4个元素组成
39 imagedata_temp.data[index]=num1;// 这里存的真的是颜色
40 imagedata_temp.data[index+1]=num2;
41 imagedata_temp.data[index+2]=num3;
42 imagedata_temp.data[index+3]=num4;
43 }
因为100km*100km的地区块在近距离视角下也是一个很大的区域,下一步计划在拉近视角时,在一个地区块中再生成更多种类的地形,所以所谓“地区块的地形”,其实是其内包含的各种地形的比例分配,在远处看时地区块的颜色是其包含的各种地形的加权。
这段测试里我使用了两种地形:纯黑色的land_textblack和黄色的land_textyellow,而两种地区块的地形则分别是百分之百的land_textblack和land_textyellow。颜色的加权值被放进了canvas的像素中。
d、绘制行星:
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 }
这里我们要考虑使用何种方式把长度为199的浮点型数组arr_palpha传入显卡,事实上OpenGL支持传入数组型通用变量,但对数组的支持分成两种:一种是我们前面看到的vec3、vec4这类向量数组,glsl把整个向量看做一个变量,而另一种类似“uniform float uarrpalpha[500]”的自定义数组则是把数组中的每一个元素都看做一个uniform变量处理!(?)。
根据StackOverFlow上一个外国同行的试验,OpenGL最多只能支持200个左右的uniform变量(?),这意味着我们难以直接用数组的方式传入arr_palpha。另外在WebGL1.0中的glsl不支持不定长度的数组,这意味着我们必须在编写着色器代码前对数组的大小有恰当的估计,或者根据行星的大小临时调节着色器代码。
在glsl中使用长数组的另一个问题是:glsl竟然不支持直接用临时赋值的变量作为数组索引!类似
1 int i=1 ;
2 float f=arr[i+1 ];
这种数组用法是不允许的!!!!
要将计算结果作为数组的索引只能使用if else或者switch case枚举出每一种对应的情况,或者使用:
1 float getData500(float data[500 ],int id) {
2 int len=int (floor(uarrpalphalen+0.5 ));
3 for (int i=0 ; i<500 ; i++) {
4 if (i>=len)// i不能和非常量比较!!只好换个方式限制它
5 {
6 return 0.0 ;
7 }
8 if (i == id) return data[i];
9 }
10 }
其中id是计算出来的索引,另外glsl的for循环的中段也不支持“i
因此改为使用datatexture传递水平区分度数组
然而使用datatexture时又遇到一个问题,canvas会自动把颜色分量转化为0到255的整数,而这里的水平区分度全是0到1之间的小数,会被自动转为0或1,为解决这一问题把水平区分度数据转化为科学计数法并用像素表示:
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;i13 {
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)
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 }
执行程序,看到运行效果与设计有所偏差:
南半球的黑色地区块少了很多行,没有形成预计的棋盘形,时间有限没有详细调试
拉近相机:
可以看到每个地区块的边界清晰可见,没有发生模糊。
使用console.log输出用到的两个dataurl作为参考:
4、着色器代码:
a、顶点着色器:
1 uniform mat4 worldViewProjection;
2 uniform mat4 worldView;
3 attribute vec3 position;
4
5 varying vec3 vPosition;
6 varying vec3 oPosition;// 自身坐标系里的位置
7
8 void main(){
9 gl_Position=worldViewProjection*vec4(position,1 );
10 vPosition=vec3(worldView*vec4(position,1 ));
11 oPosition=position;
12 }
我们前面生成地形的计算都是在行星的自身坐标系里进行的,所以在片元着色器里也需要以行星的自身坐标系为参考确定地区块的层数和房间号,所以把一个不经过任何矩阵变换的顶点位置信息传入片元着色器。
b、片元着色器:
1 precision highp float ;
2 // varying vec4 vColor;
3 varying vec3 vPosition;
4 varying vec3 oPosition;
5 // uniform vec4 uColor;
6 uniform sampler2D utexturedqk;//地区块数据纹理的采样器
7 uniform float wid_utexturedqk;//数据纹理的宽高
8 uniform float hei_utexturedqk;
9
10 uniform sampler2D utexturepalpha;// 一个单元里保存了四个元素!!!!
11 // uniform vec3 uarrdqk[60000]; // es3.0之前的glsles不支持隐含数组!!!!
12 uniform float pbeta;
13 uniform float wid_utexturepalpha;
14 uniform float hei_utexturepalpha;
15 // uniform float uarrpalpha[500]; // 用来测试的行星只有199层,预设为500层应该够了
16 uniform float uarrpalphalen;
17 uniform float max_floorf;
18 uniform float MathPI;
19
20 float getDataVec4(vec4 data,int id) {
21 for (int i=0 ; i<4 ; i++) {
22 if (i == id) return data[i];
23 }
24 }
25 float getData500(float data[500 ],int id) {
26 int len=int (floor(uarrpalphalen+0.5 ));
27 for (int i=0 ; i<500 ; i++) {
28 if (i>=len)// i不能和非常量比较!!只好换个方式限制它
29 {
30 return 0.0 ;
31 }
32 if (i == id) return data[i];
33 }
34 }
35
36 void main()
37 {
38 // vec4 tempColor=uColor; // es3.0之前不支持round!!!!
39 // glsl事实上以float为计算基准
40 // int max_floor=int(floor(max_floorf+0.5));
41 // 算层数
42 float r=sqrt(oPosition.x*oPosition.x+oPosition.y*oPosition.y+oPosition.z*oPosition.z);//这个片元到球心的距离
43 float beta=asin(oPosition.y/r);// 俯仰角
44 // int int_beta=int(floor((beta/(pbeta*2.0))+0.5));
45 float count_beta=(beta/(pbeta*2.0 ));
46 // int index_beta=int(floor(count_beta+ max_floorf+0.5));
47 float index_beta=floor(count_beta+ max_floorf+0.5 );//第几层
48 // int roomcount=0;
49 // 使用数据纹理法,取这一层的区分度
50 // int int1=int(floor(mod(index_beta,4.0)+0.5)); 51 // float float1=(index_beta/4.0);
52 float floatu=(mod(index_beta,wid_utexturepalpha))/(wid_utexturepalpha)+(0.5 /wid_utexturepalpha);// u是x轴坐标,v是y轴坐标
53 float floatv=(((index_beta)/(wid_utexturepalpha)))/(hei_utexturepalpha)+(0.5 /(wid_utexturepalpha*hei_utexturepalpha));
54 vec2 UVpalpha=vec2(floatu,floatv);//上面计算的uv坐标加了一个偏移量,防止坐标正好落在两个像素的边界上
55 vec4 vec4palphas=texture2D(utexturepalpha, UVpalpha);//glsl中的颜色为0到1.0,所以要乘以255.0获得传入的科学计数法
56 float palpha=(vec4palphas[0 ]*255.0 *100.0 +vec4palphas[1 ]*255.0 )/pow(10.0 ,vec4palphas[2 ]*255.0 );
57 // float palpha=getData500(uarrpalpha,int(floor(index_beta+0.5))); // 改为尝试数组法传递数据
58 // 取这一层的转角
59 float alpha=atan(oPosition.z,oPosition.x);// 标准反正切函数有两个参数!!
60 if (alpha<0.0 )
61 {
62 alpha+=(MathPI*2.0 );
63 }
64 // 取地区块数据纹理的坐标
65 float floatu2=(alpha/(palpha*2.0 ))/wid_utexturedqk;
66 float floatv2=index_beta/hei_utexturedqk+0.5 /hei_utexturedqk;
67 vec2 UVdqk=vec2(floatu2,floatv2);
68 gl_FragColor=texture2D(utexturedqk, UVdqk);
69 // gl_FragColor=vec4palphas;
70 // gl_FragColor=texelFetch(utexturedqk,ivec2(int(floor(alpha/(palpha*2.0)+0.5)),int(floor(index_beta+0.5))),0); // 这个整数像素的方法是WebGL2开始加入的!!!!
71 // gl_FragColor=vec4(1.0*floatu,1.0*floatv,1.0*floatv2,1.0); // 红,绿,蓝结果不是0就是1??!!
72
73 // int index_dqk=roomcount-1+int(floor((alpha/palpha)+0.5));
74 // vec4 tempColor=vec4(uarrdqk[index_dqk],1.0);
75
76 // float float_3=index_beta/(max_floorf*2.0);
77 // float float_4=oPosition.y/5.0;
78 // canvas的imagedata用255,255,255,255定义颜色通道,而glsl用1.0,1.0,1.0,1.0定义!!!!
79
80
81 }
glsl语言不支持字符串类型,WebGL1.0也不支持从显卡反写数据到内存,一种可行的调试方法是将某个计算结果转化为颜色显示在屏幕上,然后用拾色器提取值。
四、根据规则生成随机的行星表面地形(testarenas.html)
1、生成地区块的基本数据结构:
1 function CookDqk()// 生成地区块,每一floor的每个room
2 {
3 var size_dqk=100;// 每个地区块的长宽都是100km
4 var r_planet=perimeter/(2*Math.PI);//行星的半径
5 var len_beta=sswr(((perimeter/2)/size_dqk)/2);//通过弧度来分层!!100
6 pbeta=(Math.PI/4)/len_beta;
7 // 对于每一层,
8 for (var i=-len_beta;i<=len_beta;i++)
9 {
10
11 var rad_beta=(Math.PI/2)*(i/len_beta);
12 var r_floor=Math.cos(rad_beta)*r_planet;// 这一层的半径
13 var len_alpha_floor=sswr((r_floor*2*Math.PI)/size_dqk);
14 var palpha=Math.PI/len_alpha_floor;//每一个地区块的角度边界,在这个边界范围内即属于这个地区块
15 arr_palpha.push(palpha);
16 var beta=i*pbeta*2;
17 // console.log(i+"/"+len_beta+">"+len_alpha_floor);
18 var arr1=[];
19 // 对于圆环上的每一个片
20 for (var j=0;j)
21 {
22 var obj={};
23 obj.palpha=palpha;
24 obj.alpha=j*palpha*2;
25 obj.pbeta=pbeta;
26 obj.beta=beta;
27 // obj.weight={};
28 obj.floor=i;
29 obj.room=j;
30 obj.countcook=0;
31 obj.altitude=0;
32
33 arr1.push(obj);
34
35 }
36 if (arr1.length>0)
37 {
38 arr_floorroom.push(arr1);
39 }
40
41 }
42 CookDqk2();// 对生成的数据结构进行 规律随机填充
43 }
View Code
2、使用正态随机数与加和平均确定每个地区块的海拔
1 // 使用正态随机数和加和平均确定每个地区块的海拔
2 function CookDqk2()
3 {
4 var len=arr_floorroom.length;
5 // 生成初始的随机正态随机海拔
6 console.log("生成初始的随机正态随机海拔");
7 for (var i=0;i)
8 {
9 // console.log(i+" in "+len);
10 var len2=arr_floorroom[i].length;
11 for (var j=0;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)//将地区块的海拔和周围相邻的所有地区块的海拔相加取平均值,作为这个地区块的海拔
33 {
34 console.log(i+" in "+len);
35 var len2=arr_floorroom[i].length;
36 for (var j=0;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//遍历下层的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//考虑这个room上面的floor
60 {
61 var len3=arr_floorroom[i+1].length;
62 for (var k=0;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)
98 {
99 console.log(i+" in "+len);
100 var len2=arr_floorroom[i].length;
101 for (var j=0;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 }
关于正态随机数的知识可以参考这篇文章:https://www.cnblogs.com/zztt/p/4025207.html
3、根据海拔高度和纬度确定地形:
1 function CookDqk3()
2 {
3 console.log("开始生成地区块级地形");
4 var len=arr_floorroom.length;
5 for (var i=0;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)
17 {
18 console.log(i+" in "+len);
19 var len2=arr_floorroom[i].length;
20 for (var j=0;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//遍历下层的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//考虑这个room上面的floor
52 {
53 var len3=arr_floorroom[i+1].length;
54 for (var k=0;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//对每个地区块进行加权,这段代码执行很慢
149 {
150 var len2=arr_floorroom[i].length;
151 console.log(i+" in "+len);
152 for (var j=0;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 }
getLandtypeDqk是根据海拔和纬度确定地形的方法:(这个方法效率很低)
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 }
在同一海拔和纬度可能有多种地形存在,每一种地形都有一个出现概率,取一个随机数,如果这个随机数小于遍历到这个地形时的概率累积,则将这个地区块设为这种地形。
每一种地形还有一个effect属性,表示这种地形对周边地形的影响能力,比如如果一片热带雨林周围全被沙漠包围,那么这片雨林有很大可能变成沙漠。
海拔和纬度与地形的对应关系设定如下:(tab_datalib.js)
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)//eval是判断地区块大类型的判断条件,以后在设计技能效果时也可能要借鉴这里
7 "温带海洋":{eval:"height<0&&rate_land<0.9&&Math.abs(beta)>beta_2326&&Math.abs(beta)}},
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)}},
10 "温带1500米以上":{eval:"rate_land>0.1&&Math.abs(beta)>beta_2326&&Math.abs(beta)=1500","雪山dqk":{rate:1,effect:1}},
11 "亚热带3000米以下":{eval:"rate_land>0.1&&Math.abs(beta)>beta_8&&Math.abs(beta)}},
12 "亚热带3000米以上":{eval:"rate_land>0.1&&Math.abs(beta)>beta_8&&Math.abs(beta)=3000","雪山dqk":{rate:1,effect:1}},
13 "热带3000米以下":{eval:"rate_land>0.1&&Math.abs(beta)}},
14 "热带3000米以上":{eval:"rate_land>0.1&&Math.abs(beta)=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 }
这里设定每一个100km*100km的地区块可以由更小的“地貌块”组成,在极近时地貌块的地形显示为实际的纹理图,在较远时地貌块表现为纹理图的平均色,在更远一些时用地区块代替地貌块,地区块的颜色为地貌块的加权。
目前这个切换功能还未编写,因为时间有限实际地形纹理也没有仔细设置,地区块的颜色加权也没做,直接使用了占比较多的地貌块颜色。
提取纹理图平均颜色的代码如下:(testpix.html)
1 DOCTYPE html >
2 < html lang ="en" >
3 < head >
4 < meta charset ="UTF-8" >
5 < title > 提取一副固定大小图片的平均颜色color4title >
6 head >
7 < body >
8 < div id ="div_allbase" >
9 < canvas style ="width: 512px;height: 512px" width ="512" height ="512" id ="can_pic" >
10
11 canvas >
12 div >
13 body >
14 < script >
15 var canvas = document.getElementById( " can_pic " );
16 window.onload = loadImage;
17 function loadImage()
18 {
19 var context = canvas.getContext( " 2d " );
20 var img = document.createElement( " img " );
21 img.src = " ../../ASSETS/IMAGE/Texture_landtypedmk/lvzhou.png " ;
22 img.onload = function ()
23 { // 在图片加载完毕后才可以在canvas里绘制
24 context.drawImage(img, 0 , 0 );
25 var imagedata_temp = context.getImageData( 0 , 0 , 512 , 512 ); // 规定地貌块纹理图片的宽高是512
26 var data = imagedata_temp.data;
27 var len = data.length;
28 var color4 = [ 0 , 0 , 0 , 0 ];
29 for ( var i = 0 ;i < len;i += 4 )
30 {
31 color4[ 0 ] += data[i];
32 color4[ 1 ] += data[i + 1 ];
33 color4[ 2 ] += data[i + 2 ];
34 color4[ 3 ] += data[i + 3 ];
35 }
36 var int = 512 * 512 ;
37 color4[ 0 ] = Math.round(color4[ 0 ] / int);
38 color4[ 1 ] = Math.round(color4[ 1 ] / int);
39 color4[ 2 ] = Math.round(color4[ 2 ] / int);
40 color4[ 3 ] = Math.round(color4[ 3 ] / int);
41 console.log(color4);
42 }
43
44 }
45 script >
46 html >
View Code
4、生成数据纹理
1 function CookDqk4()
2 {
3 var len=arr_floorroom.length;
4 // 开始生成数据纹理
5 console.log("开始生成数据纹理");
6 for (var i=0;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 }
然后用和前面类似的方式将数据纹理送入显卡并进行渲染
着色器代码如下:
顶点着色器:
1 uniform mat4 worldViewProjection;
2 uniform mat4 worldView;
3 attribute vec3 position;
4
5 varying vec3 vPosition;
6 varying vec3 oPosition;// 自身坐标系里的位置
7
8 void main(){
9 gl_Position=worldViewProjection*vec4(position,1 );
10 vPosition=vec3(worldView*vec4(position,1 ));
11 oPosition=position;
12 }
View Code
片元着色器:
1 precision highp float ;
2 // varying vec4 vColor;
3 varying vec3 vPosition;
4 varying vec3 oPosition;
5 // uniform vec4 uColor;
6 uniform sampler2D utexturedqk;
7 uniform float wid_utexturedqk;
8 uniform float hei_utexturedqk;
9
10 uniform sampler2D utexturepalpha;// 一个单元里保存了四个元素!!!!
11 // uniform vec3 uarrdqk[60000]; // es3.0之前的glsles不支持隐含数组!!!!
12 uniform float pbeta;
13 uniform float wid_utexturepalpha;
14 uniform float hei_utexturepalpha;
15 // uniform float uarrpalpha[500]; // 用来测试的行星只有199层,预设为500层应该够了
16 uniform float uarrpalphalen;
17 uniform float max_floorf;
18 uniform float MathPI;
19
20 float getDataVec4(vec4 data,int id) {
21 for (int i=0 ; i<4 ; i++) {
22 if (i == id) return data[i];
23 }
24 }
25 float getData500(float data[500 ],int id) {
26 int len=int (floor(uarrpalphalen+0.5 ));
27 for (int i=0 ; i<500 ; i++) {
28 if (i>=len)// i不能和非常量比较!!只好换个方式限制它
29 {
30 return 0.0 ;
31 }
32 if (i == id) return data[i];
33 }
34 }
35 float getOdevity(float a)// 判断浮点型整数的奇偶性,偶返回0,奇返回1
36 {
37 float b=mod(a,2.0 );
38 float c=0.0 ;
39 if (b>=0.5 &&b<1.5 )
40 {
41 c=1.0 ;
42 }
43 return c;
44 }
45
46 void main()
47 {
48 // vec4 tempColor=uColor; // es3.0之前不支持round!!!!
49 // glsl事实上以float为计算基准
50 // int max_floor=int(floor(max_floorf+0.5));
51 // 算层数
52 float r=sqrt(oPosition.x*oPosition.x+oPosition.y*oPosition.y+oPosition.z*oPosition.z);
53 float beta=asin(oPosition.y/r);// 俯仰角
54 // int int_beta=int(floor((beta/(pbeta*2.0))+0.5)); // 层数
55 float count_beta=(beta/(pbeta*2.0 ));
56 // int index_beta=int(floor(count_beta+ max_floorf+0.5)); // 整数层数索引
57 float index_beta=floor(count_beta+ max_floorf+0.5 );
58 // int roomcount=0;
59 // 使用数据纹理法,取这一层的区分度
60 // int int1=int(floor(mod(index_beta,4.0)+0.5)); // 使用哪个颜色分量
61 // float float1=(index_beta/4.0); // 在纹理采样器中的顺序索引
62 float floatu=(mod(index_beta,wid_utexturepalpha))/(wid_utexturepalpha)+(0.5 /wid_utexturepalpha);// 猜测u是x轴
63 float floatv=(((index_beta)/(wid_utexturepalpha)))/(hei_utexturepalpha)+(0.5 /(wid_utexturepalpha*hei_utexturepalpha));
64 vec2 UVpalpha=vec2(floatu,floatv);
65 vec4 vec4palphas=texture2D(utexturepalpha, UVpalpha);
66 float palpha=(vec4palphas[0 ]*255.0 *100.0 +vec4palphas[1 ]*255.0 )/pow(10.0 ,vec4palphas[2 ]*255.0 );
67 // float palpha=getData500(uarrpalpha,int(floor(index_beta+0.5))); // 改为尝试数组法传递数据
68 // 取这一层的转角
69 float alpha=atan(oPosition.z,oPosition.x);// 标准反正切函数有两个参数!!
70
71 if (getOdevity(index_beta)==1.0 )// 为了体现交错效果,如果是奇数层alpha要减去palpha
72 {
73 alpha-=palpha;
74 }
75 if (alpha<0.0 )
76 {
77 alpha+=(MathPI*2.0 );
78 }
79 // 取地区块数据纹理的索引
80 float floatu2=(alpha/(palpha*2.0 ))/wid_utexturedqk;
81 float floatv2=index_beta/hei_utexturedqk+0.5 /hei_utexturedqk;
82 vec2 UVdqk=vec2(floatu2,floatv2);
83 gl_FragColor=texture2D(utexturedqk, UVdqk);
84 // gl_FragColor=vec4palphas;
85 // gl_FragColor=texelFetch(utexturedqk,ivec2(int(floor(alpha/(palpha*2.0)+0.5)),int(floor(index_beta+0.5))),0); // 这个整数像素的方法是WebGL2开始加入的!!!!
86 // gl_FragColor=vec4(1.0*floatu,1.0*floatv,1.0*floatv2,1.0); // 红,绿,蓝结果不是0就是1??!!
87
88 // int index_dqk=roomcount-1+int(floor((alpha/palpha)+0.5));
89 // vec4 tempColor=vec4(uarrdqk[index_dqk],1.0);
90
91 // float float_3=index_beta/(max_floorf*2.0);
92 // float float_4=oPosition.y/5.0;
93 // canvas的imagedata用255,255,255,1定义颜色通道,而glsl用1.0,1.0,1.0,1.0定义!!!!
94
95
96 }
View Code
片元着色器和前面的区别是加了一个判断奇偶层数的方法,另外,在WebGL2.0中加入的texelFetch方法可以直接根据像素的位置对纹理图进行采样,比使用纹理坐标进行采样方便许多。
执行程序效果如下:
拉近相机:
其中生成地形耗时1分30秒,平滑地形并入库耗时3分10秒,从数据库查询需要约1分钟
五、总结
这个方法耗时比较长,无法实时应用,但可以用来一次性构建地形多次使用,也许可以通过优化代码来提高运行速度。生成的海洋和陆地混杂度比较高,也许可以考虑从种子位置随机生长地形的算法,这样可以使得大陆和海洋区分的更加分明。着色器代码中没有考虑周期性光照效果,也没有考虑极点处的地区块如何处理。
下一步准备给地区块添加鼠标交互,和更细节的地貌块显示。
你可能感兴趣的:(使用着色器在WebGL3D场景中呈现行星表面地形)
美易官方:盘前道指期货涨0.5%,游戏驿站跌逾15%
美股投资
财经 人工智能 大数据 新浪微博 微信 微信公众平台 百度 金融
在股市开盘前的交易时段,道指期货上涨了0.5%,而游戏驿站(GameStop)的股价却出现了大幅下跌,跌幅超过15%。这一市场动态引发了投资者的广泛关注,也反映了当前股市的复杂性和不确定性。美股股指期货周三盘前走强,交易员为季度末的再平衡做准备。本周因假期而缩短,美国将公布关键通胀数据。道指期货涨0.5%,标普500指数期货涨0.6%,纳指期货涨0.5%。德国DAX指数涨0.4%,英国富时100指
别人能伤害你,是你允许的。
1125198e6b7d
不要对别人抱有太大期望,保护自己的最佳方式,就是从不高估自己在别人心中的份量。能伤害你的从来不是别人的无情,而是你心存幻想的坚持。及时止损,不盼望就不会失望。相识很久的关系,明明内心很不舒服,却还要装作若无其事的样子,强撑着去面对。一次又一次为了迎合而迎合,自我qipian,精神内耗。对于那些不能带给你任何积极能量的人,我们真正要做的就是及时止损。伤害你的人从来没想过帮助你成长,真正让你成长的是你
2023-02-16
执剑饮烈酒
1、开心点,反正谁也别想活着离开这个世界。——朱德庸2、我一直以为爱的反义词是不爱,直到现在我才明白,爱的反义词是遗忘。——《寻梦环游记》3、人生的最高境界是佛为心,道为骨,儒为表,大度看世界。技在手,能在身,思在脑,从容过生活。——南怀瑾4、如果一个民族沦落到,只剩下把升官发财当成最终目标和追求的时候,那么这个民族就危险了,一旦金钱和权利成了唯一的信仰,那将是悲哀的。——鲁迅5、人和人如果不在一
为什么wal会 提升数据库性能
浩澜大大
数据库
由于对于一个数据库内会存在很多张表,那么当数据库更新表数据时(1)直接写入磁盘实际写入的位置,会根据表的不同对应到不同的磁盘位置,在写入数据的时候,就会不停的寻找磁盘地址,找到地址后再去写入,对于机械硬盘来说,无规律的寻址是非常耗时的,对应SSD来说虽然性能提升很多,但是也会消耗时间;(2)先写入日志,在写入磁盘(WAL)WAL的过程,由于总是按照在文件末尾追加,只要找到文件写入位置,写入修改后,
《昼颜》里的日本女人:相遇要万种风情,分手要残忍绝情
迷影咖啡
作者:迷之菌子神奇菇迷影咖啡:一本正经做烘焙,胡说八道聊电影漫天萤火虫消散之时良宵就将过去,人们也说含苞待放的花蕾总会开了又谢,因紧紧相拥而面红耳赤的躯体,便是我们经历过这热爱的证明。夫妻关系介绍《昼颜》是2014年电视剧《昼颜:工作日下午三点的恋人们》的续集,故事发在电视剧情节结束的三年后,讲述了已经恢复独身的纱和偶然与曾经的出轨对象北野重逢后再次陷入感情漩涡的故事。《昼颜》制作灵感源自利佳子在
植物小记
番茄秧子
小时候,我养过一院子的花。今年,我重新开始从头开始养一点儿植物。别人说那也只是别人说临到快过年,我逛了一趟花市,买了两棵水仙花。路过另外一个卖水仙的摊位,霸气的卖花小妹瞧了一眼我捧着的那两棵弱小,说了一句:“你那个水仙不行,都不会开花的。”以我的脾气,这当然不能相信啊。结果,带回家好几天没动静。某一天早晨起来,两棵水仙悄不吭声全开了,然后香了屋子好多天。水仙三月,我在花市扛了一盆栀子花,花店老板见
Android和IOS应用开发-Flutter应用让屏幕在 app 运行期间保持常亮的方法
江上清风山间明月
Flutter android ios flutter KeepAlive 屏幕常亮 wakelock 熄屏
文章目录Flutter应用让屏幕在app运行期间保持常亮的方法方法一:使用系统插件方法二:使用Widgets注意事项Flutter应用让屏幕在app运行期间保持常亮的方法在Flutter开发中,可以使用以下两种方法让屏幕在app运行期间保持常亮:方法一:使用系统插件Flutter社区中已经有很多相关插件可供使用,比如wakelock:https://pub.dev/packages/wakeloc
微信小程序监听用户经纬度变化
某公司摸鱼前端
微信小程序 小程序
一些打卡App需要根据用户的位置来完成打卡那么就需要监听用户位置变化情况:示例://在某个生命周期函数中,如onLoad中onLoad:function(options){//开始监听位置变化wx.startLocationUpdate({success:function(){console.log('开始更新位置');},fail:function(){console.log('开始更新位置失败
2019-04-08早
梦雅的简动力
在上瑜伽课前10分钟的调息中,你的眼睛为什么总是想睁开?(焦虑)。你的眉头为什么总是紧锁?(压力)。练习体式时你为什么总是去看别人?(攀比)保持体式时你为什么总是烦躁?(性急)。保持长久而规律的练习,以上这些,终归离你远去。瑜伽,首先,不是帮你得到,而是教你放下。图片发自App时间,一时间无法跳离这个特殊的词汇毅力,坚持,真诚,需要时间来见证真相,现实,伪装,时间自然会揭秘珍惜它又害怕它可它丝毫不
极狐GitLab 论坛 2.0 全新上线,可以在论坛上查找与 GitLab 相关的问题了~
极小狐
gitlab 极狐GitLab devops GitLab ci/cd devsecops SCM
安装出现依赖错误?版本升级搞不定?遇到422、500就懵逼了?不知道某个功能是免费or付费?……使用GitLab这种全球顶级的DevOps平台进行软件研发时,总会遇到一些困惑,想跟专业的技术人员快速交流以便获得答案,同时又想把这些问题沉淀下来以帮助他人?有这种赠人玫瑰,手有余香的解决方案吗?答案肯定有:论坛!!!论坛——一个各路大神聚集的地方,一个可以解惑答疑问道的地方。解惑:搜索与自己问题相同或
数据结构奇妙旅程之深入解析快速排序
山间漫步人生路
数据结构 排序算法 算法
快速排序(QuickSort)是一种高效的排序算法,它使用了分治法的策略来将一个数组排序。其基本思想是选择一个基准元素,通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比基准元素小,另一部分的所有数据都比基准元素大,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。工作原理选择基准:从待排序的序列中选一个元素作为基准(pivo
教育微创新的意蕴
知北老师
我是1992年参加工作的,一毕业就被分配到一所全县最偏僻落后的农村学校——付窝中学,12年后被调往一所已经连续十年全县倒数第一,也是很偏僻落后的农村学校——北宋镇第三中学。三年后到了北宋镇第一中学工作,这所学校教学质量也是连续几年落后了。2014年我到了北京市育英学校,这所学校是京城名校。2016年7月,我被育英学校派往原密云区第七中学工作,这是一所城乡接合部薄弱学校。学校现名为北京市育英学校密云
我喝醉了,但是与你无关
Z先生的日记本
2019年04月10号晚上我和一个朋友喝酒了,彻彻底底的喝醉了,喝到短片,事后我问L,我说我喝醉了之后,都发生了什么,L没有告诉我详情,但是跟我说了大致,他说我跟他一直聊天,说自己小的时候的事,说自己爸妈的事,说自己现在过得很苦可能,确实是喝醉了酒,才会毫无防备的跟其他人说这些吧。L还说感觉我过得很苦,很心疼。醉了酒之后还哭了,想想还真是丢人一年前,在宿舍也有一瓶红酒,那是舍友出去拉赞助时候,友商
android 自定义曲线图,Android自定义View——贝赛尔曲线
weixin_39767513
android 自定义曲线图
个人博客:haichenyi.com。感谢关注本文针对有一定自定义View的童鞋,最好对贝赛尔曲线有辣么一丢丢了解,不了解也没关系。花5分钟看一下GcsSloop的安卓自定义View进阶-Path之贝塞尔曲线。本文的最终效果图:最终效果图.gif思路首先他是一个只有上半部分的正弦形状的水波纹,很规则。其次,他这个正弦图左右在移动。然后,就是它这个自定义View,上下也在移动,是慢慢增加的最后,优化
Flink中的SQL Client和SQL Gateway
BigDataMLApplication
flink flink sql gateway
Flink中的SQLClient和SQLGateway对比目录定义基本原理适用场景主要区别常用运维命令示例官方链接正文1.定义SQLClient:FlinkSQLClient是一种用于提交和执行FlinkSQL语句的命令行界面或图形界面工具。SQLGateway:FlinkSQLGateway是一个独立的服务,它允许客户端通过RESTfulAPI将SQL查询提交到Flink集群。2.基本原理SQL
2022年河南省高等职业教育技能大赛云计算赛项竞赛赛卷(样卷)
忘川_ydy
云计算 云计算 openstack kubernetes docker python k8s ansible
#需要资源(软件包及镜像)或有问题的,可私博主!!!#需要资源(软件包及镜像)或有问题的,可私博主!!!#需要资源(软件包及镜像)或有问题的,可私博主!!!第一部分:私有云任务1私有云服务搭建(10分)使用提供的用户名密码,登录竞赛用的云计算平台,按要求自行使用镜像创建两台云主机,创建完云主机后确保网络正常通信,然后按要求配置服务器。根据提供安装脚本框架,补充脚本完成OpenStack平台的安装搭
浪潮 M5系列服务器IPMI无法监控存储RAID卡问题.
Songxwn
硬件服务器 服务器 运维
简介浪潮的M5代服务器,可能有WebBMC无法查看存储RAID/SAS卡状态的情况,可以通过以下方式修改。修改完成后重启BMC即可生效。ESXiIPMITools使用:https://songxwn.com/ESXi8_IPMI/(Linux也可以直接使用)Linux/ESXiIPMITool下载:https://songxwn.com/file/ipmitoolWindows下载:https:/
【OpenModelica】4命令行大全
Wumbuk
python 开发语言 modelica
命令行大全文章目录命令行大全一、SummaryofCommandsfortheInteractiveSessionHandler二、Runningthecompilerfromcommandline一、SummaryofCommandsfortheInteractiveSessionHandler以下是交互式会话处理器中当前可用命令的完整列表。•simulate(modelname):翻译一个名为
unblock with ‘mysqladmin flush-hosts‘ 解决方法
祈祷平安,加油
数据库常见问题 oracle 数据库
MySqlHostisblockedbecauseofmanyconnectionerrors;unblockwith'mysqladminflush-hosts'解决方法环境:linux,mysql5.5.21错误:Hostisblockedbecauseofmanyconnectionerrors;unblockwith'mysqladminflush-hosts'原因:同一个ip在短时间内产
通俗易懂:MySQL中如何设置只读实例并确保数据一致性?
大龄下岗程序员
mysql java mysql spring
在MySQL中设置只读实例主要应用于构建高可用性和扩展性的数据库环境,通常是为了分担读取负载或者用于备份和灾难恢复。以下是创建MySQL只读实例并确保数据一致性的基本步骤:1.创建并配置只读实例-主从复制设置-首先,你需要有一个主数据库实例(Master)负责接收所有的写操作。-创建一个或多个从数据库实例(Slave),并将它们配置为主数据库的复制品。这通常通过设置主从复制(Replication
拼多多纸巾推荐:品质与性价比的完美结合
氧惠帮朋友一起省
拼多多纸巾推荐拼多多纸巾返现怎么做在我们的日常生活中,纸巾已经成为不可或缺的用品。无论是在家庭、办公室还是旅途中,纸巾都是我们随时随地需要的物品。随着电商平台的兴起,越来越多的人选择在网上购买纸巾。其中,拼多多作为国内知名的电商平台之一,以其独特的社交电商模式和实惠的价格吸引了大量用户。今天,我们就来探讨如何在拼多多上选择品质优良、性价比高的纸巾,以及如何通过一些小技巧来获取更多的优惠。一、品质与
LeetCode1047:删除字符串中的所有相邻重复项
一个小猴子`
LeetCode 算法 数据结构 c++ leetcode
题目描述给出由小写字母组成的字符串S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在S上反复执行重复项删除操作,直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。示例:输入:“abbaca”输出:“ca”解释:例如,在“abbaca”中,我们可以删除“bb”由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串“aaca”,其中又只有“a
Mac命令行查找SDK/JDK安装位置
iblade
Linux macos java 开发语言
要在命令行中查询AndroidSDKPlatformTools的安装位置,可以使用以下步骤:使用which命令:在命令行中执行以下命令:whichadb这将输出adb命令的安装路径,通常情况下,它会在AndroidSDK的platform-tools目录下。手动查找:如果whichadb没有输出,可以手动查找AndroidSDK的安装位置。通常情况下,AndroidSDK的默认安装路径是在用户的h
美团自动配送车2024春季招聘 | 社招专场
美团技术团队
关于美团自动配送团队美团自动配送以自研L4级自动驾驶软硬件技术为核心,与美团即时零售业务结合,形成满足公开道路、校园、社区、工业园区等室外全场景下的自动配送整体解决方案。美团自动配送团队成立于2016年,团队成员来自于Waymo、Cruise、Pony.ai、泛亚等自动驾驶行业头部公司,自动驾驶技术团队博士占比高达30%,依靠视觉、激光等传感器,实时感知预测周围环境,通过高精地图定位和智能决策规划
易经第六十一卦风泽中孚
徐徐微风正好
易经第六十一卦风泽中孚,巽上兑下。中孚:豚鱼吉,利涉大川,利贞。中孚卦象征着中心诚信,甚至诚信到了能够感动小猪小鱼,可获吉祥,对渡过大河巨流有利,对坚守正道有利。诚信是立人之本,立身处世心怀诚信广施仁义才会走的长远。但是诚信也要合理合时,君子从中得到启示,要以诚信的德行慎重审议案件并宽缓死刑。诚信可以使人信服,有利于坚守中正,内在谦逊柔顺外在坚守行动诚信,连最顽固的老百姓都被感化,天何言哉,四时行
天猫超市优惠获取渠道,天猫超市内部优惠劵领取方法使用教程
氧惠全网优惠
天猫超市是一个不错的购物平台,满足用户所需,基本次日达,很方便的购物平台,那么有人问我,天猫超市优惠获取渠道在哪?怎么能够优惠的购买,今天分享给大家;1、天猫超市优惠券抢好券:天猫超市首页每天可以领取满199减30、满235减35、满299减50、满399减60、满166减30等优惠券,领劵方法复制下条口令打开淘宝进入领劵会场;隐藏神券、实时爆款、天天更新!戳>(CZ9185ZatcdhNADlJ
读思001 ‖ 变负能为正能,变压力为动力
你不懂夜的黑
今天起开始写一个言说文集连载,重点为读写思考收获和感想,也收录生活和工作中开悟到的点滴,仍然是一个碎片式的思考积累。希望这样的思考能启迪我的生活智慧,开悟我的思想境界,也算是一个修心的过程吧。这个连载不定期更新,重在积累生活和工作中的随思碎思,或许也是一厢情愿的一个梦。也或许这个梦是我坚持说下去的一个重要理由。读思001变负能为正能,变压力为动力1从来没有一种哲学能解决一切问题,也从来没有一种药能
《对我而言危险的他》:“假千金”归来,携手神秘霸总共破迷局
入骨影评
由樊治欣李墨之主演的都市悬疑爱情剧《对我而言危险的他》在网上平台一次性播出全集。虽然是个小成本网剧,呈现出来的效果却十分有诚意。剧中从车祸到坠海、再到徒手灭火等惊险场面都是实景拍摄和主演们的无替身上场。说起樊治欣这个名字可能大家都不熟悉,但提起他演过的剧,大家都不陌生。饰演过《暗格里的秘密》中的学长苏柏从的樊治欣在这部剧中饰演霸总严星呈,即便同样戴着眼镜,却给人不一样的观感。该剧主要讲述了女主沈漫
学习JavaEE的日子 Day32 线程池
A 北枝
学习JavaEE 学习 java-ee java 线程池
Day32线程池1.引入一个线程完成一项任务所需时间为:创建线程时间-Time1线程中执行任务的时间-Time2销毁线程时间-Time32.为什么需要线程池(重要)线程池技术正是关注如何缩短或调整Time1和Time3的时间,从而提高程序的性能。项目中可以把Time1,T3分别安排在项目的启动和结束的时间段或者一些空闲的时间段线程池不仅调整Time1,Time3产生的时间段,而且它还显著减少了创建
花气袭人知昼暖
柒侠传
花气袭人知昼暖高一七班黄韵熹37号花袭人,原名花珍珠,位列金陵十二钗又副册中的第二位。“袭人”这一称呼源于“花气袭人知昼暖”这一诗句,是宝玉给起的。想起来便觉得暖融融的,一如花袭人温柔的笑容。但花袭人着实是令人又爱又怕的角色。第二十一回的回目将她赞作“贤袭人”,脂砚斋在一旁批道“当得起”。花袭人对宝玉的确是一片真心。她为劝宝玉收敛他那成日在大观园里与姐姐妹妹“厮混”的性子,假借家人赎回的机会,软语
java类加载顺序
3213213333332132
java
package com.demo;
/**
* @Description 类加载顺序
* @author FuJianyong
* 2015-2-6上午11:21:37
*/
public class ClassLoaderSequence {
String s1 = "成员属性";
static String s2 = "
Hibernate与mybitas的比较
BlueSkator
sql Hibernate 框架 ibatis orm
第一章 Hibernate与MyBatis
Hibernate 是当前最流行的O/R mapping框架,它出身于sf.net,现在已经成为Jboss的一部分。 Mybatis 是另外一种优秀的O/R mapping框架。目前属于apache的一个子项目。
MyBatis 参考资料官网:http:
php多维数组排序以及实际工作中的应用
dcj3sjt126com
PHP usort uasort
自定义排序函数返回false或负数意味着第一个参数应该排在第二个参数的前面, 正数或true反之, 0相等usort不保存键名uasort 键名会保存下来uksort 排序是对键名进行的
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8&q
DOM改变字体大小
周华华
前端
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml&q
c3p0的配置
g21121
c3p0
c3p0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。c3p0的下载地址是:http://sourceforge.net/projects/c3p0/这里可以下载到c3p0最新版本。
以在spring中配置dataSource为例:
<!-- spring加载资源文件 -->
<bean name="prope
Java获取工程路径的几种方法
510888780
java
第一种:
File f = new File(this.getClass().getResource("/").getPath());
System.out.println(f);
结果:
C:\Documents%20and%20Settings\Administrator\workspace\projectName\bin
获取当前类的所在工程路径;
如果不加“
在类Unix系统下实现SSH免密码登录服务器
Harry642
免密 ssh
1.客户机
(1)执行ssh-keygen -t rsa -C "
[email protected] "生成公钥,xxx为自定义大email地址
(2)执行scp ~/.ssh/id_rsa.pub root@xxxxxxxxx:/tmp将公钥拷贝到服务器上,xxx为服务器地址
(3)执行cat
Java新手入门的30个基本概念一
aijuans
java java 入门 新手
在我们学习Java的过程中,掌握其中的基本概念对我们的学习无论是J2SE,J2EE,J2ME都是很重要的,J2SE是Java的基础,所以有必要对其中的基本概念做以归纳,以便大家在以后的学习过程中更好的理解java的精髓,在此我总结了30条基本的概念。 Java概述: 目前Java主要应用于中间件的开发(middleware)---处理客户机于服务器之间的通信技术,早期的实践证明,Java不适合
Memcached for windows 简单介绍
antlove
java Web windows cache memcached
1. 安装memcached server
a. 下载memcached-1.2.6-win32-bin.zip
b. 解压缩,dos 窗口切换到 memcached.exe所在目录,运行memcached.exe -d install
c.启动memcached Server,直接在dos窗口键入 net start "memcached Server&quo
数据库对象的视图和索引
百合不是茶
索引 oeacle数据库 视图
视图
视图是从一个表或视图导出的表,也可以是从多个表或视图导出的表。视图是一个虚表,数据库不对视图所对应的数据进行实际存储,只存储视图的定义,对视图的数据进行操作时,只能将字段定义为视图,不能将具体的数据定义为视图
为什么oracle需要视图;
&
Mockito(一) --入门篇
bijian1013
持续集成 mockito 单元测试
Mockito是一个针对Java的mocking框架,它与EasyMock和jMock很相似,但是通过在执行后校验什么已经被调用,它消除了对期望 行为(expectations)的需要。其它的mocking库需要你在执行前记录期望行为(expectations),而这导致了丑陋的初始化代码。
&nb
精通Oracle10编程SQL(5)SQL函数
bijian1013
oracle 数据库 plsql
/*
* SQL函数
*/
--数字函数
--ABS(n):返回数字n的绝对值
declare
v_abs number(6,2);
begin
v_abs:=abs(&no);
dbms_output.put_line('绝对值:'||v_abs);
end;
--ACOS(n):返回数字n的反余弦值,输入值的范围是-1~1,输出值的单位为弧度
【Log4j一】Log4j总体介绍
bit1129
log4j
Log4j组件:Logger、Appender、Layout
Log4j核心包含三个组件:logger、appender和layout。这三个组件协作提供日志功能:
日志的输出目标
日志的输出格式
日志的输出级别(是否抑制日志的输出)
logger继承特性
A logger is said to be an ancestor of anothe
Java IO笔记
白糖_
java
public static void main(String[] args) throws IOException {
//输入流
InputStream in = Test.class.getResourceAsStream("/test");
InputStreamReader isr = new InputStreamReader(in);
Bu
Docker 监控
ronin47
docker监控
目前项目内部署了docker,于是涉及到关于监控的事情,参考一些经典实例以及一些自己的想法,总结一下思路。 1、关于监控的内容 监控宿主机本身
监控宿主机本身还是比较简单的,同其他服务器监控类似,对cpu、network、io、disk等做通用的检查,这里不再细说。
额外的,因为是docker的
java-顺时针打印图形
bylijinnan
java
一个画图程序 要求打印出:
1.int i=5;
2.1 2 3 4 5
3.16 17 18 19 6
4.15 24 25 20 7
5.14 23 22 21 8
6.13 12 11 10 9
7.
8.int i=6
9.1 2 3 4 5 6
10.20 21 22 23 24 7
11.19
关于iReport汉化版强制使用英文的配置方法
Kai_Ge
iReport汉化 英文版
对于那些具有强迫症的工程师来说,软件汉化固然好用,但是汉化不完整却极为头疼,本方法针对iReport汉化不完整的情况,强制使用英文版,方法如下:
在 iReport 安装路径下的 etc/ireport.conf 里增加红色部分启动参数,即可变为英文版。
# ${HOME} will be replaced by user home directory accordin
[并行计算]论宇宙的可计算性
comsci
并行计算
现在我们知道,一个涡旋系统具有并行计算能力.按照自然运动理论,这个系统也同时具有存储能力,同时具备计算和存储能力的系统,在某种条件下一般都会产生意识......
那么,这种概念让我们推论出一个结论
&nb
用OpenGL实现无限循环的coverflow
dai_lm
android coverflow
网上找了很久,都是用Gallery实现的,效果不是很满意,结果发现这个用OpenGL实现的,稍微修改了一下源码,实现了无限循环功能
源码地址:
https://github.com/jackfengji/glcoverflow
public class CoverFlowOpenGL extends GLSurfaceView implements
GLSurfaceV
JAVA数据计算的几个解决方案1
datamachine
java Hibernate 计算
老大丢过来的软件跑了10天,摸到点门道,正好跟以前攒的私房有关联,整理存档。
-----------------------------华丽的分割线-------------------------------------
数据计算层是指介于数据存储和应用程序之间,负责计算数据存储层的数据,并将计算结果返回应用程序的层次。J
&nbs
简单的用户授权系统,利用给user表添加一个字段标识管理员的方式
dcj3sjt126com
yii
怎么创建一个简单的(非 RBAC)用户授权系统
通过查看论坛,我发现这是一个常见的问题,所以我决定写这篇文章。
本文只包括授权系统.假设你已经知道怎么创建身份验证系统(登录)。 数据库
首先在 user 表创建一个新的字段(integer 类型),字段名 'accessLevel',它定义了用户的访问权限 扩展 CWebUser 类
在配置文件(一般为 protecte
未选之路
dcj3sjt126com
诗
作者:罗伯特*费罗斯特
黄色的树林里分出两条路,
可惜我不能同时去涉足,
我在那路口久久伫立,
我向着一条路极目望去,
直到它消失在丛林深处.
但我却选了另外一条路,
它荒草萋萋,十分幽寂;
显得更诱人,更美丽,
虽然在这两条小路上,
都很少留下旅人的足迹.
那天清晨落叶满地,
两条路都未见脚印痕迹.
呵,留下一条路等改日再
Java处理15位身份证变18位
蕃薯耀
18位身份证变15位 15位身份证变18位 身份证转换
15位身份证变18位,18位身份证变15位
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
蕃薯耀 201
SpringMVC4零配置--应用上下文配置【AppConfig】
hanqunfeng
springmvc4
从spring3.0开始,Spring将JavaConfig整合到核心模块,普通的POJO只需要标注@Configuration注解,就可以成为spring配置类,并通过在方法上标注@Bean注解的方式注入bean。
Xml配置和Java类配置对比如下:
applicationContext-AppConfig.xml
<!-- 激活自动代理功能 参看:
Android中webview跟JAVASCRIPT中的交互
jackyrong
JavaScript html android 脚本
在android的应用程序中,可以直接调用webview中的javascript代码,而webview中的javascript代码,也可以去调用ANDROID应用程序(也就是JAVA部分的代码).下面举例说明之:
1 JAVASCRIPT脚本调用android程序
要在webview中,调用addJavascriptInterface(OBJ,int
8个最佳Web开发资源推荐
lampcy
编程 Web 程序员
Web开发对程序员来说是一项较为复杂的工作,程序员需要快速地满足用户需求。如今很多的在线资源可以给程序员提供帮助,比如指导手册、在线课程和一些参考资料,而且这些资源基本都是免费和适合初学者的。无论你是需要选择一门新的编程语言,或是了解最新的标准,还是需要从其他地方找到一些灵感,我们这里为你整理了一些很好的Web开发资源,帮助你更成功地进行Web开发。
这里列出10个最佳Web开发资源,它们都是受
架构师之面试------jdk的hashMap实现
nannan408
HashMap
1.前言。
如题。
2.详述。
(1)hashMap算法就是数组链表。数组存放的元素是键值对。jdk通过移位算法(其实也就是简单的加乘算法),如下代码来生成数组下标(生成后indexFor一下就成下标了)。
static int hash(int h)
{
h ^= (h >>> 20) ^ (h >>>
html禁止清除input文本输入缓存
Rainbow702
html 缓存 input 输入框 change
多数浏览器默认会缓存input的值,只有使用ctl+F5强制刷新的才可以清除缓存记录。
如果不想让浏览器缓存input的值,有2种方法:
方法一: 在不想使用缓存的input中添加 autocomplete="off";
<input type="text" autocomplete="off" n
POJO和JavaBean的区别和联系
tjmljw
POJO java beans
POJO 和JavaBean是我们常见的两个关键字,一般容易混淆,POJO全称是Plain Ordinary Java Object / Pure Old Java Object,中文可以翻译成:普通Java类,具有一部分getter/setter方法的那种类就可以称作POJO,但是JavaBean则比 POJO复杂很多, Java Bean 是可复用的组件,对 Java Bean 并没有严格的规
java中单例的五种写法
liuxiaoling
java 单例
/**
* 单例模式的五种写法:
* 1、懒汉
* 2、恶汉
* 3、静态内部类
* 4、枚举
* 5、双重校验锁
*/
/**
* 五、 双重校验锁,在当前的内存模型中无效
*/
class LockSingleton
{
private volatile static LockSingleton singleton;
pri