Alternativa 3D Series – Tutorial 2 – Adding Material【翻译】

在第一篇文章中我们创建了一个简单的Alternativa 3D程序。编译后我们可以看到一个旋转的线框立方体。本篇文章我将向大家展示如何给立方体填充材质,让立方体看起来更美观。


Alternativa有三种标准材质类型:线框材质,填充材质和纹理材质。前面提到的线框材质可以显示模型的多边形边框。填充材质可以用颜色填充整个多边形模型,边框的显示和线框填充别无二致。最后的纹理材质可以用用一个2d图片填充整个模型。

本节的实例会用三种材质填充的上节做好的立方体。为达到更好的目的,我们需要创建一些按钮和滑动条来让用户操作。

代码
1 <?xml version="1.0" encoding="utf-8"?>
2  <mx:Application
3 xmlns:mx="http://www.adobe.com/2006/mxml"
4 layout="absolute"
5 xmlns:ns1="*"
6 width="600"
7 height="400"
8 color="#FFFFFF"
9 backgroundGradientAlphas="[1.0, 1.0]"
10 backgroundGradientColors="[#FFFFFF, #C0C0C0]"
11 frameRate="100">
12
13 <ns1:EngineManager id="engineManager" x="0" y="0" width="100%" height="100%"/>
14 <mx:HSlider x="56" y="147" width="53" id="sliderRed" minimum="0" maximum="255" snapInterval="1" change="{ApplicationManager.Instance.onColorChanged()}"/>
15 <mx:Label x="10" y="147" text="Red" color="#000000"/>
16 <mx:HSlider x="56" y="199" width="53" id="sliderBlue" minimum="0" maximum="255" snapInterval="1" change="{ApplicationManager.Instance.onColorChanged()}"/>
17 <mx:Label x="10" y="199" text="Blue" color="#000000"/>
18 <mx:Image x="10" y="10" id="imgAlternativa" source="@Embed(source='../media/alternativa.jpg')"/>
19 <mx:Image x="10" y="340" source="@Embed(source='../media/thetechlabs.png')"/>
20 <mx:Button x="10" y="50" label="Wireframe" color="#000000" id="btnWireframe" click="{ApplicationManager.Instance.setWireMaterial()}"/>
21 <mx:Button x="10" y="80" label="Texture" color="#000000" id="btnTexture" width="88" click="{ApplicationManager.Instance.setTextureMaterial()}"/>
22 <mx:Button x="10" y="110" label="Color Fill" color="#000000" width="88" id="btnColorFill" click="{ApplicationManager.Instance.setFillMaterial()}"/>
23 <mx:HSlider x="56" y="173" width="53" id="sliderGreen" minimum="0" maximum="255" snapInterval="1" change="{ApplicationManager.Instance.onColorChanged()}"/>
24 <mx:Label x="10" y="173" text="Green" color="#000000"/>
25
26  </mx:Application>


你会看到,我们可以用标准的flex组件来控制我们的3D程序。本例中我们会创建3个按钮(分别控制三种材质),3个滑动条(来定义红色,绿色和蓝色的线框和填充材质组件)和一些标签。滑动条改变事件可以触发程序调用ApplicationManager的setTextureMaterial方法。按钮的点击事件可以触发程序调用setWireMaterial, setFillMaterial 或 setTextureMaterial 方法,以改变立方体的材质。

代码
1 package
2 {
3 import alternativa.engine3d.materials.FillMaterial;
4 import alternativa.engine3d.materials.TextureMaterial;
5 import alternativa.engine3d.materials.WireMaterial;
6 import alternativa.utils.ColorUtils;
7
8 import flash.display.BlendMode;
9
10 import mx.core.Application;
11
12 /**
13 * The ApplicationManager holds all program related logic.
14 */
15 public class ApplicationManager
16 {
17 protected static const WIREFRAME:int = 1;
18 protected static const TEXTURE:int = 2;
19 protected static const FILL:int = 3;
20 protected static var instance:ApplicationManager = null;
21 protected var currentMaterial:int = 0;
22 protected var rotatingBox:RotatingBox = null;
23
24 public static function get Instance():ApplicationManager
25 {
26 if (instance == null)
27 instance = new ApplicationManager();
28 return instance;
29 }
30
31 public function ApplicationManager()
32 {
33
34 }
35
36 public function startupApplicationManager():ApplicationManager
37 {
38 // create a new instance of the rotating box
39   rotatingBox = new RotatingBox().startupRotatingBox();
40 // give the box a wireframe material by default
41   setWireMaterial();
42 // tell the camera to look at the box
43 Application.application.engineManager.cameraController.lookAt(rotatingBox.model.coords);
44
45 return this;
46 }
47
48 public function setWireMaterial():void
49 {
50 currentMaterial = WIREFRAME;
51 rotatingBox.model.cloneMaterialToAllSurfaces(new WireMaterial(1, getCurrentColor()));
52 }
53
54 public function setTextureMaterial():void
55 {
56 currentMaterial = TEXTURE;
57 rotatingBox.model.cloneMaterialToAllSurfaces(new TextureMaterial(ResourceManager.Texture1_Tex));
58 }
59
60 public function setFillMaterial():void
61 {
62 currentMaterial = FILL;
63 rotatingBox.model.cloneMaterialToAllSurfaces(new FillMaterial(getCurrentColor(), 1, BlendMode.NORMAL, 2, 0x000000));
64 }
65
66 public function onColorChanged():void
67 {
68 // reapply the current texture, taking into account the new color
69 switch (currentMaterial)
70 {
71 case WIREFRAME:
72 setWireMaterial();
73 break;
74 case FILL:
75 setFillMaterial();
76 break;
77 }
78 }
79
80 /**
81 * Returns a uint reprensenting the color specified by the 3 sliders in the main GUI
82 */
83 protected function getCurrentColor():uint
84 {
85 return ColorUtils.rgb(Application.application.sliderRed.value, Application.application.sliderGreen.value, Application.application.sliderBlue.value);
86 }
87 }
88 }

ApplicationManager类又多了很多代码,这些新的代码用来设置立方体的材质。我们引入了一个新的属性——currentMaterial,它的值根据我们设给立方体的材质类型发生改变。
你可以在setWireMaterial, setFillMaterial 和 etTextureMaterial 三个方法中看到这个属性。在这三个方法中我们会调用cloneMaterialToAllSurfaces方法来给立方体设置各种材质。


onColorChanged方法,会在用户改变滑动条修改颜色值时被调用,该方法会根据currentMaterial的当前值来给立方体设置不同材质颜色。细心的你可能会注意到在WireMaterial和FillMaterial的构造函数中都会调用getCurrentColor方法,该方法会返回一个用户滑动选择改变的uint颜色值。


TextureMaterial类有所不同,他可以用一张图片作为材质,而我们如何获得这种材质呢?往下看

代码
1 package
2 {
3 import alternativa.types.Texture;
4
5 /**
6 * ResourceManager is where we embed and create the resources needed by our application
7 */
8 public class ResourceManager
9 {
10 [Embed(source="../media/texture1.jpg")]
11 public static const Texture1:Class;
12 public static const Texture1_Tex:Texture = new Texture(new Texture1().bitmapData, "Texture1_Tex");
13 }
14 }


为获得材质,我们引入了一个新类——ResourceManager. 在这个类中我们导入了一些资源。大家看[Embed(source="../media/texture1.jpg")]。这一行的作用是嵌入一张图片资源。嵌入的这张图片会在Texture类中使用到。然后我们把Texture赋值给TextureMaterial,然后供我们的立方体使用。


总结:大家可以看到,我们根据上节的基础,很容易的创建了一个新的Alternativa 程序。EngineManager, BaseObject 和MeshObject类都没发生变化。(实际上MeshObject的model属性发生了些许变化,由原来的继承自:Object3D,变成了继承自:Mesh).ApplicationManager仅做了些许变动。同时我们引入了ResourceManager类,他为我们导入一些资源,并把它转化为材质供程序使用。

原文地址:https://www.cnblogs.com/crkay/p/1854233.html