TWaver - 专注UI技术

http://twaver.servasoft.com/
posts - 171, comments - 191, trackbacks - 0, articles - 2
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

在3D场景中显示汉字

Posted on 2012-08-06 18:00 TWaver 阅读(1113) 评论(0)  编辑  收藏
TWaver 3D for Flex本身支持3D文字的显示,但是用户必须嵌入一套字库才可以。使用传统的方式,显示3D文字。

 1 [Embed("extrusionfonts.swf", mimeType="application/octet-stream")]
 2 private var font:Class;
 3 ..
 4 twaver.threed.util.Util3D.checkTextFont(font);
 5 var network:Network3D = new Network3D();
 6 network.applyHoverCamera(-180,10,5,300);
 7 this.addElement(network);
 8 var n2:Node = new Node();
 9 n2.setStyle(Style3D.THREED_SHAPE_TYPE,Consts3D.THREED_SHAPE_TYPE_TEXT);
10 n2.setStyle(Style3D.TEXT_FONT_SIZE,20);
11 n2.setStyle(Style3D.TEXT_FONT_3D,"Arial");
12 n2.setStyle(Style3D.TEXT_WIDTH,200);
13 n2.setStyle(Style3D.TEXT_CONTENT,"Hello");
14 n2.setStyle(Style3D.MAPPINGTYPE,Consts3D.MAPPINGTYPE_COLOR);
15 n2.setStyle(Style3D.MATERIAL_COLOR,0x00FF00);
16 n2.setStyle(Style3D.PROPERTY_SPACE_LOCATION,new Vector3D(100,0,0));
17 n2.setStyle(Style3D.BOTH_SIDES_VISIBLE,true);
18 network.elementBox.add(n2);
19 network.showAxises();


对于国内客户来说,这一点就有些痛苦了,一个中文字库的体积太大,嵌入发布程序中的话,会增大发布包的大小,及时是远程加载,也会因为其恐怖的体积,让用户的web化设计面临网络情况的挑战。当然为了用户也可以去裁剪一个字库,把自己会用到的文字收入其中,做个可控数量级的枚举,但是实时系统在运行过程中,会碰到什么样的汉字也是个未知,很难做裁剪的时候枚举尽所需要的汉字。这个问题一直苦苦萦绕在每个人的心头。
,,,,,,
,,,,,,
终于,TWaver 3D支持动态贴图了,这里的动态贴图已经不只是说可以动态切换贴图资源的来源,更重要的是可以动态切换上在内存中生成的BitmapData对象。大家都知道,Flex的BitmapData支持将其UIComponent绘制出来,这一下子为我们解决汉字显示提供了一个非常便捷的方式,那就是我们把汉字写进一个TextInput组件中去,然后再把这个组件画到一个BitmapData对象中,然后在将这个对象变成我们一个3D对象的贴图(例如一个Plane,一个Billboard,一个Cube等等)。ok,动手试验
按步就班,搭建一个3D场景,并且放入一个Plane对象。

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
 3                xmlns:s="library://ns.adobe.com/flex/spark"
 4                xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:ns="http://www.servasoft.com/twaver/3D" creationComplete="init()">
 5     <fx:Declarations>
 6         <!-- Place non-visual elements (e.g., services, value objects) here -->
 7     </fx:Declarations>
 8     <fx:Script>
 9         <![CDATA[
10             import twaver.*;
11             import twaver.threed.event.*;
12             import twaver.threed.util.*;
13             private var databox:ElementBox;
14             private var source:BitmapData;
15             private var rect:Rectangle = new Rectangle(0,0,128,128);
16             private var text:TextInput = new TextInput();
17             private var n1:Node;
18             private function init():void{
19                 prepare();
20                 setupNetwork();
21                 fillData();
22                 network.showAxises();
23                 network.callLater(function():void{
24                     paintTexture(n1);
25                 });
26             }
27             private function fillData():void{
28                 n1 = NodeUtils.buildPlane(new Vector3D(0,0,0),new Vector3D(32,0,32),new Vector3D(90,0,0),Consts3D.MAPPINGTYPE_COMMON,source,true);
29                 databox.add(n1);
30             }
31             private function setupNetwork():void{
32                 databox = network.elementBox;
33                 network.applyHoverCamera(-180,10,5,200);
34             }
35         ]]>
36     </fx:Script>
37     <ns:Network3D id="network" width="100%" height="100%"/>
38 </s:Application>

我们会得到一个类似截图的效果,一个只有一个plane对象的3D场景:

现在就让我们用点小技巧,把自己需要的汉字画到3D场景中去吧。 我们需要针对前面的代码做点改进,引入一个TextInput组件,用来呈现汉字;然后我们需要动态地生成一个BitmapData对象,把这个汉字画到指定的图片中去,最后我们再把内存里的这个画好了汉字的图片作为贴图,贴到plane上去。

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
 3                xmlns:s="library://ns.adobe.com/flex/spark"
 4                xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:ns="http://www.servasoft.com/twaver/3D" creationComplete="init()">
 5     <fx:Declarations>
 6         <!-- Place non-visual elements (e.g., services, value objects) here -->
 7     </fx:Declarations>
 8     <fx:Script>
 9         <![CDATA[
10             import mx.controls.TextInput;
11             import twaver.*;
12             import twaver.threed.event.*;
13             import twaver.threed.util.*;
14             private var databox:ElementBox;
15             private var source:BitmapData;
16             private var rect:Rectangle = new Rectangle(0,0,128,128);
17             private var text:TextInput = new TextInput();
18             private var n1:Node;
19             private function init():void{
20                 prepare();
21                 setupNetwork();
22                 fillData();
23                 network.showAxises();
24                 network.callLater(function():void{
25                     paintTexture(n1);
26                 });
27             }
28             private function prepare():void{
29                 text.width = 150;
30                 text.height = 60;
31                 text.setStyle('borderStyle','none');
32                 text.text = "你好";
33                 text.alpha = 1;
34                 this.addElement(text);
35                 text.visible = false;
36             }
37             private function fillData():void{
38                 n1 = NodeUtils.buildPlane(new Vector3D(0,0,0),new Vector3D(32,0,32),new Vector3D(90,0,0),Consts3D.MAPPINGTYPE_COMMON,source,true);
39                 databox.add(n1);
40             }
41             private function setupNetwork():void{
42                 databox = network.elementBox;
43                 network.applyHoverCamera(-180,10,5,200);
44             }
45             private function setTexture(n:Element,source:BitmapData):void{
46                 var type:String = n.getStyle(Style3D.THREED_SHAPE_TYPE);
47                 switch(type){
48                     case Consts3D.THREED_SHAPE_TYPE_BILLBOARD:
49                         n.setStyle(Style3D.BILLBOARD_TEXTURE,source);
50                         break;
51                     case Consts3D.THREED_SHAPE_TYPE_PLANE:
52                         n.setStyle(Style3D.PLANE_MATERIAL,source);
53                         break;
54                     default:
55                         n.setStyle(Style3D.MAPPING_COMMON_PATH,source);
56                         break;
57                 }
58             }
59             private function paintTexture(n:Element):void{
60                 source = new BitmapData(32,32,true,0x00000000);
61                 text.text = n.getClient("label");
62                 source.fillRect(rect,0x00000000);
63                 source.draw(text);
64                 setTexture(n,source);
65             }
66         ]]>
67     </fx:Script>
68     <ns:Network3D id="network" width="100%" height="100%"/>
69 </s:Application>
70 

再次运行,看看是不是能够得偿所愿。

吼吼,look,出来了,汉字出来了,没有引入任何字库,汉字就能够出现在我的3D场景中了。 8过,还是有些遗憾,那就是有时候如果让这汉字的内容动态地变化的时候,可怎么办??
......
......
有了!我动态切换不就行了!?说干就干,抓紧验证,重新打造代码,添加动态变化。

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
 3                xmlns:s="library://ns.adobe.com/flex/spark"
 4                xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:ns="http://www.servasoft.com/twaver/3D" creationComplete="init()">
 5     <fx:Declarations>
 6         <!-- Place non-visual elements (e.g., services, value objects) here -->
 7     </fx:Declarations>
 8     <fx:Script>
 9         <![CDATA[
10             import mx.controls.TextInput;
11             import mx.events.PropertyChangeEvent;
12             import twaver.*;
13             import twaver.threed.event.*;
14             import twaver.threed.util.*;
15             private var databox:ElementBox;
16             private var source:BitmapData;
17             private var rect:Rectangle = new Rectangle(0,0,128,128);
18             private var text:TextInput = new TextInput();
19             private var n1:Node;
20             private function init():void{
21                 prepare();
22                 setupNetwork();
23                 fillData();
24                 network.showAxises();
25                 network.callLater(function():void{
26                     paintTexture(n1);
27                 });
28 
29                 var timer:Timer = new Timer(1000);
30                 timer.addEventListener(TimerEvent.TIMER,function(evt:Event):void{
31                     var date:Date = new Date();
32                     n1.setClient("label",date.seconds);
33                 });
34                 timer.start();
35             }
36             private function prepare():void{
37                 text.width = 150;
38                 text.height = 60;
39                 text.setStyle('borderStyle','none');
40                 text.text = "你好";
41                 text.alpha = 1;
42                 this.addElement(text);
43                 text.visible = false;
44             }
45             private function fillData():void{
46                 n1 = NodeUtils.buildPlane(new Vector3D(0,0,0),new Vector3D(32,0,32),new Vector3D(90,0,0),Consts3D.MAPPINGTYPE_COMMON,source,true);
47                 databox.add(n1);
48             }
49             private function setupNetwork():void{
50                 databox = network.elementBox;
51                 network.applyHoverCamera(-180,10,5,200);
52                 databox.addDataPropertyChangeListener(this.onPropertyChanged);
53             }
54             private function onPropertyChanged(evt:PropertyChangeEvent):void{
55                 var name:String = Util3D.getPropertyName(evt.property as String);
56                 if("label"==name){
57                     var element:Element = evt.source as Element;
58                     paintTexture(element);
59                 }
60             }
61             private function setTexture(n:Element,source:BitmapData):void{
62                 var type:String = n.getStyle(Style3D.THREED_SHAPE_TYPE);
63                 switch(type){
64                     case Consts3D.THREED_SHAPE_TYPE_BILLBOARD:
65                         n.setStyle(Style3D.BILLBOARD_TEXTURE,source);
66                         break;
67                     case Consts3D.THREED_SHAPE_TYPE_PLANE:
68                         n.setStyle(Style3D.PLANE_MATERIAL,source);
69                         break;
70                     default:
71                         n.setStyle(Style3D.MAPPING_COMMON_PATH,source);
72                         break;
73                 }
74             }
75             private function paintTexture(n:Element):void{
76                 source = new BitmapData(50,32,true,0x00000000);
77                 text.text = n.getClient("label");
78                 source.fillRect(rect,0x00000000);
79                 source.draw(text);
80                 setTexture(n,source);
81             }
82         ]]>
83     </fx:Script>
84     <ns:Network3D id="network" width="100%" height="100%"/>
85 </s:Application>

run again! Please check you screen!

大家一起来看看,哪里还有可以改进的,让我们把3D应用做得更彻底一些。
这里是文章中用到的代码(见原文最下方)

只有注册用户登录后才能发表评论。


网站导航: