知识回顾:
Node#getHost()和Node#setHost(node)获取和设置吸附的图元对象
Node#getAttaches()返回目前吸附到该图元的所有对象,返回ht.List链表对象,无吸附对象时返回空
Node#isHostOn(node)判断该图元是否吸附到指定图元对象上
Node#isLoopedHostOn(node)判断该图元是否与指定图元相互形成环状吸附,例如A吸附B,B吸附C,C又吸附回A,则A,B和C图元相互环状吸附
参看代码解释:
效果图:
var createInsideWall = function(dataModel) {
ht.Default.setImage('door', 'images/door_left.png');
ht.Default.setImage('ldoor', 'images/ldoor.jpg');
ht.Default.setImage('rdoor', 'images/rdoor.jpg');
ht.Default.setImage('winImage', 'images/chuang.jpg');
ht.Default.setImage('ceramic_tile', 'images/ceramic_tile.png');
// wall.setPoints({})里面的左边点要按顺序绘制
//在2d平面图上,正方向是向右、向下
//setPoints结合setTall方法类似于s3的作用
//内墙相关参数
var wall = new ht.CSGShape();
//参数对应关系x:width、y:height;
var x1=-2000,x2=2000,x3=2000,x4=-2000,y1=-1500,y2=-1500,y3=1500,y4=1500;
wall.setPoints([{
x: x1,
y: y1
}, {
x: x2,
y: y2
}, {
x: x3,
y: y3
}, {
x: x4,
y: y4
}]);
wall.setPosition(0,-1500);
wall.setTall(500); //设置墙体高度
wall.setElevation(wall.getTall() / 2); //把墙体往地板上部上移tall的一半高度
wall.setClosePath(true);
wall.setThickness(50);
wall.s({
'shape.border.width': 20,
'shape.border.color': '#898989',
'all.color':'white',
'back.image': 'ceramic_tile',
'back.uv.scale': [1, 10],
'repeat.uv.length': 80,//改变图片重复问题,同样可以解决机器区域的图片问题--重复贴墙纸
'front.color': 'lightgray',
'csg.color': '#DDDDDD'
});
dataModel.add(wall);
/**************************挖空一半正前方的墙体***************************/
var frontWall = new ht.CSGNode();
frontWall.setHost(wall);
frontWall.setParent(wall);
frontWall.setWidth(4000);
frontWall.setHeight(40);
frontWall.setTall(wall.getTall()/2);
frontWall.setElevation(wall.getTall()*0.75);
frontWall.s({
'attach.index':2,
'attach.offset.relative':true,
'attach.offset':0.5,
'all.visible':false
});
dataModel.add(frontWall);
/*
* 因为ht.CSGNode继承于ht.Node,
* 因为ht.DoorWindow继承于ht.CSGNode,
* 所以ht.DoorWindow具有前两者的所有属性方法,包括挖空墙的方法,
* 所以在创建窗户时,不需要再进行挖空的操作。
*
* */
// //挖空门
// var HollowDoor = new ht.CSGNode();
// HollowDoor.setHost(wall);
// HollowDoor.setParent(wall);
// HollowDoor.setWidth(240);
// HollowDoor.setHeight(30);
// HollowDoor.setTall(200);
//// HollowDoor.s3(240,200,30)
// HollowDoor.setElevation(70);
// HollowDoor.s({
// 'attach.index': 2,
// 'attach.offset.relative': true,
// 'attach.offset': 0.864,
// 'all.visible': false
// });
// dataModel.add(HollowDoor);
var door_left = new ht.DoorWindow();
door_left.setHost(wall);
// doorleft.setParent(wall);
door_left.setWidth(120);
door_left.setTall(200);
door_left.setElevation(door_left.getTall() / 2+10);
door_left.s({
'attach.index': 2,//根据setPoints的左边点的顺序来确定index的值
'attach.offset.relative': true,
'attach.offset': 0.864,//根据绘制的顺序,距离上一个点的距离(0~1)
'front.image': 'ldoor',
'back.image': 'ldoor',
'all.color': 'white',
// 'all.blend': '#A95A10',
'front.uv': [1, 0, 1, 1, 0, 1, 0, 0],
'back.transparent': true,
'dw.axis': 'right',
'dw.s3': [1, 1, 0.1]
})
dataModel.add(door_left);
var door_right = new ht.DoorWindow();
door_right.setHost(wall);
// doorleft.setParent(wall);
door_right.setWidth(120);
door_right.setTall(200);
door_right.setElevation(door_right.getTall()/2+10);
door_right.s({
'attach.index': 2,
'attach.offset.relative': true,//相对定位
'attach.offset': 0.81,
'front.image': 'rdoor',
'back.image': 'rdoor',
'all.color': 'white',
'front.uv': [0,1, 0,0, 1,0, 1,1],
'back.uv': [1,0, 1,1, 0,1, 0,0],
'dw.axis': 'right',//右手边打开门
'dw.s3': [1, 1, 0.1]//窗户的透明度的参数
})
dataModel.add(door_right);
/***************************************创建窗户和窗台相关操作*********************/
//挖空窗
for(i=0;i<3;i++){
var offset=0.17, offsetX=0.32;
offset+=offsetX*i;
createWindowOnWall(offset);
}
function createWindowOnWall(offset){
var windowH=400;
var windowW=600;
var insideWindow =new ht.CSGNode();
insideWindow.setHost(wall);
insideWindow.setParent(wall);
insideWindow.setWidth(windowW);
insideWindow.setHeight(30);
insideWindow.setTall(windowH);
insideWindow.setElevation(insideWindow.getTall()/2+25);
insideWindow.s({
'attach.index':0,
'attach.offset.relative':true,
'attach.offset':offset,
'all.visible':false
})
dataModel.add(insideWindow);
//创建窗台
var table =new ht.Node();
noteStyle = {
'note': '英雄联盟',
'note.position': 17,
'note.offset.x': 0,
'note.offset.y': 0
};
table.setHost(wall);
table.setParent(wall);
table.s3(windowW,10,40);
table.setElevation(20);
table.s(noteStyle);
table.s({
'attach.index':0,
'attach.offset.relative':true,
'attach.offset':offset,
'all.color':'white',
'attach.gap': -20//z轴偏移
})
dataModel.add(table);
//创建玻璃
var windowInside =new ht.Node();
windowInside.setHost(wall);
windowInside.setParent(wall);
// windowInside.setImage('winImage');//注意区分setImage方法与all.image之间的区别
windowInside.setWidth(windowW);
windowInside.setHeight(15);
windowInside.setTall(windowH);
windowInside.open = false;
//旋转角度
windowInside.angle = Math.PI / 4;
windowInside.window = true; //旋转方向
windowInside.setElevation(windowInside.getTall()/2+25);
windowInside.s({
'attach.index': 0,
'attach.offset.relative': true,//相对定位
'attach.offset':offset,
'front.image':'winImage',
'back.image':'winImage',
'dw.s3': [1, 1, 0.1],//窗户的透明度的参数
})
dataModel.add(windowInside);
}
/************************************************************/
//************************创建柱子*************************
for(i=0;i<4;i++){
var pillarX=-1925,pillar=1280,pillarZ=-2970;
pillarX+=pillar*i;
createPillar(pillarX,250,pillarZ);
}
function createPillar(x,y,z){
var node=new ht.Node();
node.setHost(wall);
node.setParent(wall);
node.p3(x,y,z);
node.s3(150,495,100);
node.s({
'all.color':'white'
});
dataModel.add(node);
}
/****************************************************************************/
/*****************************创建左右两侧的大门**********************/
var index_l=3,index_r=1;
for(i=0;i<2;i++){
if(i==0){
createBigGate(index_r);
}
if(i==1){
createBigGate(index_l);
}
}
function createBigGate(index){
var bigGate1 =new ht.DoorWindow();
bigGate1.setHost(wall);
bigGate1.setParent(wall);
bigGate1.setWidth(300);
bigGate1.setHeight(30);
bigGate1.setTall(380);
bigGate1.setToolTip('Double click to open the window');
bigGate1.setElevation(bigGate1.getTall()/2+15);
bigGate1.s({
'attach.index': index,
'attach.offset.relative': true,//相对定位
'attach.offset': 0.2,
'front.image': 'ldoor',
'back.image': 'ldoor',
'all.color': 'white',
'front.uv': [0,1, 0,0, 1,0, 1,1],
'back.uv': [1,0, 1,1, 0,1, 0,0],
'dw.axis': 'left',
'dw.s3': [1, 1, 0.1]//窗户的透明度的参数
});
dataModel.add(bigGate1);
var bigGate2 =new ht.DoorWindow();
bigGate2.setHost(wall);
bigGate2.setParent(wall);
bigGate2.setWidth(300);
bigGate2.setHeight(30);
bigGate2.setTall(380);
bigGate2.setElevation(bigGate2.getTall()/2+15);
bigGate2.s({
'attach.index': index,
'attach.offset.relative': true,
'attach.offset': 0.3,
'front.image': 'rdoor',
'back.image': 'rdoor',
'all.color': 'white',
'front.uv': [0,1, 0,0, 1,0, 1,1],
'back.uv': [1,0, 1,1, 0,1, 0,0],
'dw.axis': 'right',
'dw.s3': [1, 1, 0.1]
});
dataModel.add(bigGate2);
var bigGate3 =new ht.DoorWindow();
bigGate3.setHost(wall);
bigGate3.setParent(wall);
bigGate3.setWidth(300);
bigGate3.setHeight(30);
bigGate3.setTall(380);
bigGate3.setElevation(bigGate3.getTall()/2+15);
bigGate3.s({
'attach.index': index,
'attach.offset.relative': true,//相对定位
'attach.offset': 0.7,
'front.image': 'ldoor',
'back.image': 'ldoor',
'all.color': 'white',
'front.uv': [0,1, 0,0, 1,0, 1,1],
'back.uv': [1,0, 1,1, 0,1, 0,0],
'dw.axis': 'left',
'dw.s3': [1, 1, 0.1]//窗户的透明度的参数
});
dataModel.add(bigGate3);
var bigGate4 =new ht.DoorWindow();
bigGate4.setHost(wall);
bigGate4.setParent(wall);
bigGate4.setWidth(300);
bigGate4.setHeight(30);
bigGate4.setTall(380);
bigGate4.setElevation(bigGate4.getTall()/2+15);
bigGate4.s({
'attach.index': index,
'attach.offset.relative': true,
'attach.offset': 0.8,
'front.image': 'rdoor',
'back.image': 'rdoor',
'all.color': 'white',
// 'all.blend': '#A95A10',
'front.uv': [0,1, 0,0, 1,0, 1,1],
'back.uv': [1,0, 1,1, 0,1, 0,0],
// 'back.transparent': true,
// 'front.transparent': true,
// 'all.reverse.cull': true,
'dw.axis': 'right',
'dw.s3': [1, 1, 0.1]
});
dataModel.add(bigGate4);
}
}
把host作为参数传递的使用案例;
host = createNode([0, 51, 0], [100, 100, 100]).s({
'label': 'Cube',
'label.visible': false,
'all.image': 'dice',
'front.uv': [0.25, 0.75, 0.25, 1, 0.5, 1, 0.5, 0.75],
'back.uv': [0.25, 0.25, 0.25, 0.5, 0.5, 0.5, 0.5, 0.25],
'bottom.uv': [0.25, 0, 0.25, 0.25, 0.5, 0.25, 0.5, 0],
'left.uv': [0, 0.75, 0, 1, 0.25, 1, 0.25, 0.75],
'right.uv': [0.5, 0.75, 0.5, 1, 0.75, 1, 0.75, 0.75],
'front.opacity': 0.5,
'front.transparent': true,
'front.blend': 'red',
'top.visible': false,
'all.reverse.flip': true,
'note': 'A good example about customizing uv',
'note.face': 'right',
'note.autorotate': true,
'note2': 'A fixed note',
'note2.face': 'front',
'note2.position': 6,
'icons': {
ICONS1: {
names: ['node_icon', 'group_icon', 'subGraph_icon', 'grid_icon', 'shape_icon', 'edge_icon'],
position: 5
},
ICONS2: {
names: ['earth', 'colors', 'fab', 'dice'],
position: 26,
width: 30,
height: 30,
gap: 5,
direction: 'north',
face: 'left',
r3: [Math.PI/2, Math.PI/2, 0],
rotationMode: 'yxz',
t3: [-15, 15, 0]
}
}
});
createNode([0, 51, -50], [50, 50, 50], host).s({
'shape3d': 'sphere',
'shape3d.image': 'earth',
'body.color': 'red',
'label': 'Sphere',
'label.background': 'yellow',
'label2': 'Sphere',
'label2.background': 'blue',
'label2.position': 3,
'label2.face': 'back'
});
function createNode(p3, s3, host){
var node = new ht.Node();
node.p3(p3);
node.s3(s3);
node.setHost(host);
dataModel.add(node);
return node;
}