采用平面方式展現(xiàn)機(jī)房室內(nèi)場(chǎng)景是我們?cè)谄匠5膽?yīng)用系統(tǒng)中最常見的界面,平面展現(xiàn)具有高效、直觀、準(zhǔn)確的優(yōu)點(diǎn),隨著信息量的擴(kuò)增和技術(shù)的發(fā)展,客戶希望在系統(tǒng)能夠提供更逼真的3D場(chǎng)景,用于增加系統(tǒng)的可閱讀性。TWaver Flex 3D借用TWaver的Element對(duì)象,通過(guò)在Element對(duì)像上面擴(kuò)展3D Style,實(shí)現(xiàn)了3D場(chǎng)景的再現(xiàn)。

在最常見的需求中就是創(chuàng)建規(guī)則形狀的機(jī)房?jī)?nèi)設(shè)備陣列,要求按照指定的行、列數(shù)自動(dòng)構(gòu)建機(jī)柜。

這種標(biāo)準(zhǔn)場(chǎng)景使用下面的代碼就可以輕松創(chuàng)建
public static function getRoomBox(id:Object):ElementBox {
var size:Number=1600;
var box:ElementBox=new ElementBox();
var xgap:Number=size / 8;
var ygap:Number=size / 8;
var startX:Number=-xgap * 2.5;
var starty:Number=-ygap * 2.5;
for (var i:int=0; i < 6; i++)
{
for (var j:int=0; j < 6; j++)
{
box.add(createRack(i + ":" + j, startX + i * xgap, starty + j * xgap));
}
}
var floor:IElement=new Element();
floor.setStyle(Style3D.MAPPINGTYPE, Consts3D.MAPPINGTYPE_COLOR);
floor.setStyle(Style3D.THREED_SHAPE_TYPE, Consts3D.THREED_SHAPE_TYPE_CUBE);
floor.setStyle(Style3D.MATERIAL_ALPHA, 0.6);
floor.setStyle(Style3D.MATERIAL_COLOR, 0x999999);
floor.setStyle(Style3D.ZORDERING_OFFSET, 2500);
floor.setStyle(Style3D.BOTH_SIDES_VISIBLE, true);
floor.setStyle(Style3D.PROPERTY_SPACE_LOCATION, new Vector3D(0, 0, 0));
floor.setStyle(Style3D.PROPERTY_SIZE, new Vector3D(size + 10, 0, size + 10));
box.add(floor);
return box;
}
private static function createRack(id:String, x:Number, z:Number):IElement{
var element:IElement=new Element(id);
element.setStyle(Style3D.MAPPINGTYPE, Consts3D.MAPPINGTYPE_MAP6);
element.setStyle(Style3D.MAPPING_COMMON_PATH, "rack3DImage");
element.setStyle(Style3D.PROPERTY_SIZE, new Vector3D(80, 150, 80));
element.setStyle(Style3D.PROPERTY_SPACE_LOCATION, new Vector3D(x, 150 / 2 + 10, z));
return element;
}
var size:Number=1600;
var box:ElementBox=new ElementBox();
var xgap:Number=size / 8;
var ygap:Number=size / 8;
var startX:Number=-xgap * 2.5;
var starty:Number=-ygap * 2.5;
for (var i:int=0; i < 6; i++)
{
for (var j:int=0; j < 6; j++)
{
box.add(createRack(i + ":" + j, startX + i * xgap, starty + j * xgap));
}
}
var floor:IElement=new Element();
floor.setStyle(Style3D.MAPPINGTYPE, Consts3D.MAPPINGTYPE_COLOR);
floor.setStyle(Style3D.THREED_SHAPE_TYPE, Consts3D.THREED_SHAPE_TYPE_CUBE);
floor.setStyle(Style3D.MATERIAL_ALPHA, 0.6);
floor.setStyle(Style3D.MATERIAL_COLOR, 0x999999);
floor.setStyle(Style3D.ZORDERING_OFFSET, 2500);
floor.setStyle(Style3D.BOTH_SIDES_VISIBLE, true);
floor.setStyle(Style3D.PROPERTY_SPACE_LOCATION, new Vector3D(0, 0, 0));
floor.setStyle(Style3D.PROPERTY_SIZE, new Vector3D(size + 10, 0, size + 10));
box.add(floor);
return box;
}
private static function createRack(id:String, x:Number, z:Number):IElement{
var element:IElement=new Element(id);
element.setStyle(Style3D.MAPPINGTYPE, Consts3D.MAPPINGTYPE_MAP6);
element.setStyle(Style3D.MAPPING_COMMON_PATH, "rack3DImage");
element.setStyle(Style3D.PROPERTY_SIZE, new Vector3D(80, 150, 80));
element.setStyle(Style3D.PROPERTY_SPACE_LOCATION, new Vector3D(x, 150 / 2 + 10, z));
return element;
}
室內(nèi)場(chǎng)景搭建出來(lái)了,用戶又有了新的要求,說(shuō)我能不能看看房間外面的場(chǎng)景呢,比如說(shuō)想要看到機(jī)房與機(jī)房之間的連接情況。那么這就要求我們轉(zhuǎn)移到戶外,將樓房展示出來(lái),樓房與樓房之間的連接關(guān)系呈現(xiàn)出來(lái)。那么就用下面的代碼我們做一個(gè)戶外的展示
public static function buildSpacialTopo(box:ElementBox):void{
var o:Vector3D = new Vector3D(0,0,0);
var cbp:Vector3D = new Vector3D(0,50,0);
var lup:Vector3D = new Vector3D(100,10,-60);
var rup:Vector3D = new Vector3D(-100,10,-60);
var fp:Vector3D = new Vector3D(0,10,100);
var l1:Node = createLine([o,new Vector3D(rup.x,3,0),new Vector3D(rup.x,3,rup.z)],5,0x000000);
box.add(l1);
l1.name = "black line";
var l2:Node = createLine([o,new Vector3D(0,3,lup.z),new Vector3D(lup.x,3,lup.z)],5,0x00FF00);
l2.name = "green line";
box.add(l2);
var l3:Node = createLine([o,new Vector3D(fp.x,2,fp.z)],3,0xFF0000);
l3.name = "red line";
box.add(l3);
var cb:Node = createCube(cbp,"BI",new Vector3D(50,100,30));
cb.name = "building";
box.add(cb);
var ds1:Node = createCube(lup,"NO",new Vector3D(25,40,10));
ds1.name = "NO.1";
box.add(ds1);
var ds2:Node = createCube(rup,"NT",new Vector3D(35,20,10));
ds2.name = "No.2";
box.add(ds2);
var f:Node = createCube(fp,"SM",new Vector3D(20,35,10));
f.setStyle(Style3D.PROPERTY_ROT_ANGLE,new Vector3D(0,180,0));
f.name = "SM";
box.add(f);
}
public static function createLine(ps,width,color):Node{
var line:Node = new Node();
line.setStyle(Style3D.THREED_SHAPE_TYPE,Consts3D.THREED_SHAPE_TYPE_LINE);
line.setStyle(Style3D.LINE_SHAPE_POINTS,ps);
line.setStyle(Style3D.MAPPINGTYPE,Consts3D.MAPPINGTYPE_COLOR);
line.setStyle(Style3D.MATERIAL_COLOR,color);
line.setStyle(Style3D.LINE_SHAPE_WIDTH,width);
return line;
}
public static function createCube(pos,mappingsource,size):Node {
var node:Node = new Node();
node.setClient("TYPE","building");
node.setStyle(Style3D.PROPERTY_SPACE_LOCATION,pos);
node.setStyle(Style3D.PROPERTY_SIZE,size);
if(mappingsource!=null){
node.setStyle(Style3D.MAPPINGTYPE,Consts3D.MAPPINGTYPE_MAP6);
node.setStyle(Style3D.MAPPING_COMMON_PATH,mappingsource);
}else{
node.setStyle(Style3D.MAPPINGTYPE,Consts3D.MAPPINGTYPE_COLOR);
node.setStyle(Style3D.MATERIAL_COLOR,0x33FF88);
}
return node;
}
var o:Vector3D = new Vector3D(0,0,0);
var cbp:Vector3D = new Vector3D(0,50,0);
var lup:Vector3D = new Vector3D(100,10,-60);
var rup:Vector3D = new Vector3D(-100,10,-60);
var fp:Vector3D = new Vector3D(0,10,100);
var l1:Node = createLine([o,new Vector3D(rup.x,3,0),new Vector3D(rup.x,3,rup.z)],5,0x000000);
box.add(l1);
l1.name = "black line";
var l2:Node = createLine([o,new Vector3D(0,3,lup.z),new Vector3D(lup.x,3,lup.z)],5,0x00FF00);
l2.name = "green line";
box.add(l2);
var l3:Node = createLine([o,new Vector3D(fp.x,2,fp.z)],3,0xFF0000);
l3.name = "red line";
box.add(l3);
var cb:Node = createCube(cbp,"BI",new Vector3D(50,100,30));
cb.name = "building";
box.add(cb);
var ds1:Node = createCube(lup,"NO",new Vector3D(25,40,10));
ds1.name = "NO.1";
box.add(ds1);
var ds2:Node = createCube(rup,"NT",new Vector3D(35,20,10));
ds2.name = "No.2";
box.add(ds2);
var f:Node = createCube(fp,"SM",new Vector3D(20,35,10));
f.setStyle(Style3D.PROPERTY_ROT_ANGLE,new Vector3D(0,180,0));
f.name = "SM";
box.add(f);
}
public static function createLine(ps,width,color):Node{
var line:Node = new Node();
line.setStyle(Style3D.THREED_SHAPE_TYPE,Consts3D.THREED_SHAPE_TYPE_LINE);
line.setStyle(Style3D.LINE_SHAPE_POINTS,ps);
line.setStyle(Style3D.MAPPINGTYPE,Consts3D.MAPPINGTYPE_COLOR);
line.setStyle(Style3D.MATERIAL_COLOR,color);
line.setStyle(Style3D.LINE_SHAPE_WIDTH,width);
return line;
}
public static function createCube(pos,mappingsource,size):Node {
var node:Node = new Node();
node.setClient("TYPE","building");
node.setStyle(Style3D.PROPERTY_SPACE_LOCATION,pos);
node.setStyle(Style3D.PROPERTY_SIZE,size);
if(mappingsource!=null){
node.setStyle(Style3D.MAPPINGTYPE,Consts3D.MAPPINGTYPE_MAP6);
node.setStyle(Style3D.MAPPING_COMMON_PATH,mappingsource);
}else{
node.setStyle(Style3D.MAPPINGTYPE,Consts3D.MAPPINGTYPE_COLOR);
node.setStyle(Style3D.MATERIAL_COLOR,0x33FF88);
}
return node;
}
在建筑物之間我們使用Line的3D模型來(lái)模擬相互之間的連接。讓我們看看這樣的代碼會(huì)建立什么樣的場(chǎng)景

在我們做應(yīng)用做的順風(fēng)順?biāo)臅r(shí)候,客戶又出現(xiàn)了,他們有時(shí)候會(huì)說(shuō)現(xiàn)在有了室內(nèi),戶外場(chǎng)景,不過(guò)戶外場(chǎng)景上只有孤零零的建筑物,看不出之間的相互地理關(guān)系來(lái),這怎么辦,能不能再增強(qiáng)些這種功能?
嗚~~~~~,淚奔。
再奔也得干哪,悲催的碼農(nóng)總得服務(wù)于千變?nèi)f化的客戶需求,咋整咋整?
要不加載下模擬的高程數(shù)據(jù)?
public static function buildTerrain(box:ElementBox):void{
var node:Node = new Node();
node.setStyle(Style3D.THREED_SHAPE_TYPE,Consts3D.THREED_SHAPE_TYPE_TERRAIN);
node.setStyle(Style3D.MAPPINGTYPE,Consts3D.MAPPINGTYPE_COMMON);
node.setStyle(Style3D.MAPPING_COMMON_PATH,"TT");
node.setStyle(Style3D.MAPPING_HEIGHTMAP,"HM");
node.setStyle(Style3D.EXTRUSION_SAMPLES,70);
node.setStyle(Style3D.EXTRUSION_XSCALE,1);
node.setStyle(Style3D.EXTRUSION_YSCALE,1);
node.setStyle(Style3D.EXTRUSION_RECENTER,true);
node.setStyle(Style3D.PROPERTY_ROT_ANGLE,new Vector3D(90,0,0));
node.setStyle(Style3D.EXTRUSION_HSCALE,0.1);
node.setStyle(Style3D.PROPERTY_SPACE_LOCATION,new Vector3D(-100,-100,0));
node.setClient("TYPE","terrain");
box.add(node);
}
var node:Node = new Node();
node.setStyle(Style3D.THREED_SHAPE_TYPE,Consts3D.THREED_SHAPE_TYPE_TERRAIN);
node.setStyle(Style3D.MAPPINGTYPE,Consts3D.MAPPINGTYPE_COMMON);
node.setStyle(Style3D.MAPPING_COMMON_PATH,"TT");
node.setStyle(Style3D.MAPPING_HEIGHTMAP,"HM");
node.setStyle(Style3D.EXTRUSION_SAMPLES,70);
node.setStyle(Style3D.EXTRUSION_XSCALE,1);
node.setStyle(Style3D.EXTRUSION_YSCALE,1);
node.setStyle(Style3D.EXTRUSION_RECENTER,true);
node.setStyle(Style3D.PROPERTY_ROT_ANGLE,new Vector3D(90,0,0));
node.setStyle(Style3D.EXTRUSION_HSCALE,0.1);
node.setStyle(Style3D.PROPERTY_SPACE_LOCATION,new Vector3D(-100,-100,0));
node.setClient("TYPE","terrain");
box.add(node);
}
要不這樣的場(chǎng)景交一下作業(yè),跟客戶交待好,這樣就可以模擬地理情況了,

人生是美好的,不過(guò)那可是由一系列的意外組合而成的。用戶又問(wèn)場(chǎng)景見出來(lái)了,不過(guò)我可怎么操作,怎么交互啊,我怎么能引導(dǎo)用戶從樓外進(jìn)入機(jī)房,從機(jī)房操作機(jī)柜,從機(jī)柜查看設(shè)備,從設(shè)備查看面板啊。
我暈-------,悲催的生活還沒有結(jié)束,人家客戶也沒有說(shuō)錯(cuò),總得把這些零件拼起來(lái)吧。抓緊趕工,添加交互機(jī)制。我要讓用戶單擊樓房的時(shí)候,彈出一個(gè)機(jī)房?jī)?nèi)景,機(jī)房?jī)?nèi)景里面我可以選擇機(jī)柜,雙擊機(jī)柜我要呈現(xiàn)出機(jī)柜內(nèi)設(shè)備的3D模型,當(dāng)我雙擊一個(gè)設(shè)備的時(shí)候又可以查看他的設(shè)備面板。

network.selectionFunction = function(element:Element){
if("terrain" == element.getClient("TYPE")){
return false;
}
return true;
}
network.addEventListener(MouseEvent.MOUSE_MOVE,onClick);



.
private function onSelectionChanged(evt:SelectionChangeEvent):void{
hideShapedWindow();
level = 0;
b1 = null;
b2 = null;
var data:Element = box.selectionModel.lastData as Element;
if(box.selectionModel.selection.contains(data)){
showRoomInfo(data,this.mousePos);
}
}
private function onClick(evt:MouseEvent):void{
var pos:Point = new Point(evt.stageX,evt.stageY);
this.mousePos = network.globalToContent(pos);
}
private function showRoomInfo(element:Element,pos:Point):void{
if("building" == element.getClient("TYPE")){
var box:ElementBox =DataUtils.getRoomBox("fd");
room = createRoom();
showShapedWindow(room,pos);
}
}
if("terrain" == element.getClient("TYPE")){
return false;
}
return true;
}
network.addEventListener(MouseEvent.MOUSE_MOVE,onClick);




private function onSelectionChanged(evt:SelectionChangeEvent):void{
hideShapedWindow();
level = 0;
b1 = null;
b2 = null;
var data:Element = box.selectionModel.lastData as Element;
if(box.selectionModel.selection.contains(data)){
showRoomInfo(data,this.mousePos);
}
}
private function onClick(evt:MouseEvent):void{
var pos:Point = new Point(evt.stageX,evt.stageY);
this.mousePos = network.globalToContent(pos);
}
private function showRoomInfo(element:Element,pos:Point):void{
if("building" == element.getClient("TYPE")){
var box:ElementBox =DataUtils.getRoomBox("fd");
room = createRoom();
showShapedWindow(room,pos);
}
}
長(zhǎng)出一口氣,終于完成一個(gè)展示全過(guò)程了,
為了讓客戶檢驗(yàn)我的成果,我就把可以直接操作的swf放在了這里,可以直接下載去。鼠標(biāo)拖拽,滾輪縮放。
代碼也都放在了這里