Up to now, The flash 3D engine Away3DLite have no build in Cube primitive, just got a Cube6, which could not change the material of each cube face. So, I decide to do something. I have spent one afternoon to write and debug this Cube class. In order to make it better to use, I give the Cube class of Away3dLite the same user interface to the Cube of Away3d. Following comes the code:
package away3dlite.primitives
{
import away3dlite.primitives.Data.CubeMaterialsData;
import away3dlite.arcane;
import away3dlite.events.MaterialEvent;
import away3dlite.materials.Material;
import away3dlite.primitives.AbstractPrimitive;
use namespace arcane;
/**
* The Cube class
*
* @author Neugls
* @see http://www.neugls.info
*
* */
public class Cube extends AbstractPrimitive
{
private var _cubeMaterials:CubeMaterialsData;
private var _leftFaces:Vector.; //faces index
private var _rightFaces:Vector.;
private var _bottomFaces:Vector.;
private var _topFaces:Vector.;
private var _frontFaces:Vector.;
private var _backFaces:Vector.;
private var _cubeFaceArray:Vector.
private var _width:Number = 100;
private var _height:Number = 100;
private var _depth:Number = 100;
private var _segmentsW:int = 1;
private var _segmentsH:int = 1;
private var _segmentsD:int = 1;
/**
* Creates a new Cube object.
*
* @param material Defines the global material used on the faces in the cube.
* @param width Defines the width of the cube.
* @param height Defines the height of the cube.
* @param depth Defines the depth of the cube.
* @param segmentsW Defines the number of horizontal segments that make up the cube.
* @param segmentsH Defines the number of vertical segments that make up the cube.
* @param segmentsD Defines the number of depth segments that make up the cube.
* @param pixelBorder Defines the texture mapping border in pixels used around each face of the cube.
*/
public function Cube(material:CubeMaterialsData=null, width:Number=100, height:Number=100, depth:Number=100, segmentsW:int=1, segmentsH:int=1, segmentsD:int=1)
{
super(null);
_width = width;
_height = height;
_depth = depth;
_segmentsW = segmentsW;
_segmentsH = segmentsH;
_segmentsD = segmentsD;
cubeMaterials=material?material:new CubeMaterialsData();
_leftFaces=new Vector.();
_rightFaces=new Vector.();
_bottomFaces=new Vector.();
_topFaces=new Vector.();
_frontFaces=new Vector.();
_backFaces=new Vector.();
type = "Cube";
url = "primitive";
}
private function BuildFace(whichFace:Vector.,material:Material):void{
whichFace.push(int(_indices.length/3)-2);
whichFace.push(int(_indices.length/3)-1);
_faceMaterials[int(_indices.length/3)-2]=material;
_faceMaterials[int(_indices.length/3)-1]=material;
}
protected override function buildPrimitive():void{
super.buildPrimitive();
_leftFaces.length=0;
_rightFaces.length=0;
_bottomFaces.length=0;
_topFaces.length=0;
_frontFaces.length=0;
_backFaces.length=0;
var i:int;
var j:int;
var a:int;
var b:int;
var c:int;
var d:int;
var inc:int = 0;
for (i = 0; i <= _segmentsW; i++) {
for (j = 0; j <= _segmentsH; j++) {
//create front/back
_vertices.push(_width/2 - i*_width/_segmentsW, _height/2 - j*_height/_segmentsH, -_depth/2);
_vertices.push(_width/2 - i*_width/_segmentsW, _height/2 - j*_height/_segmentsH, _depth/2);
_uvtData.push(1-i/_segmentsW, 1-j/_segmentsH, 1);
_uvtData.push(i/_segmentsW, 1-j/_segmentsH, 1);
if (i && j) {
a = 2*((_segmentsW + 1)*j + i);
b = 2*((_segmentsW + 1)*j + i - 1);
c = 2*((_segmentsW + 1)*(j - 1) + i - 1);
d = 2*((_segmentsW + 1)*(j - 1) + i);
_indices.push(c,d,b);
_indices.push(d,a,b);
BuildFace(_frontFaces,_cubeMaterials.front);
_indices.push(c+1,b+1,d+1);
_indices.push(d+1,b+1,a+1);
BuildFace(_backFaces,_cubeMaterials.back);
}
}
}
inc += 2*(_segmentsW + 1)*(_segmentsH + 1);
for (i = 0; i <= _segmentsW; i++) {
for (j = 0; j <= _segmentsD; j++) {
//create top/bottom
_vertices.push(_width/2 - i*_width/_segmentsW, _height/2, -_depth/2 + j*_depth/_segmentsD);
_vertices.push(_width/2 - i*_width/_segmentsW, -_height/2, -_depth/2 + j*_depth/_segmentsD);
_uvtData.push(i/_segmentsW, j/_segmentsD, 1);
_uvtData.push(i/_segmentsW, 1-j/_segmentsD, 1);
if (i && j) {
a = inc + 2*((_segmentsW + 1)*j + i);
b = inc + 2*((_segmentsW + 1)*j + i - 1);
c = inc + 2*((_segmentsW + 1)*(j - 1) + i - 1);
d = inc + 2*((_segmentsW + 1)*(j - 1) + i);
_indices.push(c,b,d);
_indices.push(b,a,d);
BuildFace(_topFaces,_cubeMaterials.top);
_indices.push(c+1,d+1,b+1);
_indices.push(b+1,d+1,a+1);
BuildFace(_bottomFaces,_cubeMaterials.bottom);
}
}
}
inc += 2*(_segmentsW + 1)*(_segmentsD + 1);
for (i = 0; i <= _segmentsH; i++) {
for (j = 0; j <= _segmentsD; j++) {
//create left/right
_vertices.push(_width/2, _height/2 - i*_height/_segmentsH, -_depth/2 + j*_depth/_segmentsD);
_vertices.push(-_width/2, _height/2 - i*_height/_segmentsH, -_depth/2 + j*_depth/_segmentsD);
_uvtData.push(j/_segmentsD,1-i/_segmentsH, 1);
_uvtData.push(1-j/_segmentsD, 1-i/_segmentsH, 1);
if (i && j) {
a = inc + 2*((_segmentsH + 1)*j + i);
b = inc + 2*((_segmentsH + 1)*j + i - 1);
c = inc + 2*((_segmentsH + 1)*(j - 1) + i - 1);
d = inc + 2*((_segmentsH + 1)*(j - 1) + i);
_indices.push(c,d,b);
_indices.push(d,a,b);
BuildFace(_rightFaces,_cubeMaterials.right);
_indices.push(c+1,b+1,d+1);
_indices.push(d+1,b+1,a+1);
BuildFace(_leftFaces,_cubeMaterials.left);
}
}
}
}
/**
* Defines the face materials of the cube.
*/
public function get cubeMaterials():CubeMaterialsData
{
return _cubeMaterials;
}
public function set cubeMaterials(val:CubeMaterialsData):void
{
if (_cubeMaterials == val)
return;
if (_cubeMaterials)
_cubeMaterials.removeOnMaterialChange(onCubeMaterialChange);
_cubeMaterials = val;
_cubeMaterials.addOnMaterialChange(onCubeMaterialChange);
}
private function onCubeMaterialChange(event:MaterialEvent):void
{
switch (event.extra) {
case "left":
_cubeFaceArray = _leftFaces;
break;
case "right":
_cubeFaceArray = _rightFaces;
break;
case "bottom":
_cubeFaceArray = _bottomFaces;
break;
case "top":
_cubeFaceArray = _topFaces;
break;
case "front":
_cubeFaceArray = _frontFaces;
break;
case "back":
_cubeFaceArray = _backFaces;
}
for each (var i:int in _cubeFaceArray)
_faces[i].material = event.material as Material;
}
/**
* Defines the width of the cube. Defaults to 100.
*/
public override function get width():Number
{
return _width;
}
public override function set width(val:Number):void
{
if (_width == val)
return;
_width = val;
_primitiveDirty = true;
}
/**
* Defines the height of the cube. Defaults to 100.
*/
public override function get height():Number
{
return _height;
}
public override function set height(val:Number):void
{
if (_height == val)
return;
_height = val;
_primitiveDirty = true;
}
/**
* Defines the depth of the cube. Defaults to 100.
*/
public function get depth():Number
{
return _depth;
}
public function set depth(val:Number):void
{
if (_depth == val)
return;
_depth = val;
_primitiveDirty = true;
}
/**
* Defines the number of horizontal segments that make up the cube. Defaults to 1.
*/
public function get segmentsW():Number
{
return _segmentsW;
}
public function set segmentsW(val:Number):void
{
if (_segmentsW == val)
return;
_segmentsW = val;
_primitiveDirty = true;
}
/**
* Defines the number of vertical segments that make up the cube. Defaults to 1.
*/
public function get segmentsH():Number
{
return _segmentsH;
}
public function set segmentsH(val:Number):void
{
if (_segmentsH == val)
return;
_segmentsH = val;
_primitiveDirty = true;
}
/**
* Defines the number of depth segments that make up the cube. Defaults to 1.
*/
public function get segmentsD():Number
{
return _segmentsD;
}
public function set segmentsD(val:Number):void
{
if (_segmentsD == val)
return;
_segmentsD = val;
_primitiveDirty = true;
}
}
}
The following comes the CubeMaterialsData class:
package away3dlite.primitives.Data
{
import away3dlite.events.MaterialEvent;
import away3dlite.materials.Material;
import away3dlite.materials.WireframeMaterial;
import flash.events.EventDispatcher;
public class CubeMaterialsData extends EventDispatcher
{
/**
* Dispatched when the cube materials object has one of it's materials updated.
*
* @eventType away3dLite.events.MaterialEvent
*/
[Event(name="materialchanged",type="away3dlite.events.MaterialEvent")]
private var _materialchanged:MaterialEvent;
private var _left:Material;
private var _right:Material;
private var _bottom:Material;
private var _top:Material;
private var _front:Material;
private var _back:Material;
private function notifyMaterialChange(material:Material, faceString:String):void
{
if (!hasEventListener(MaterialEvent.MATERIAL_CHANGED))
return;
//if (!_materialchanged)
_materialchanged = new MaterialEvent(MaterialEvent.MATERIAL_CHANGED, material);
/*else
_materialchanged.material = material; */
_materialchanged.extra = faceString;
dispatchEvent(_materialchanged);
}
/**
* Defines the material applied to the left side of the cube.
*/
public function get left():Material
{
return _left;
}
public function set left(val:Material):void
{
if (_left == val)
return;
_left = val;
notifyMaterialChange(_left, "left");
}
/**
* Defines the material applied to the right side of the cube.
*/
public function get right():Material
{
return _right;
}
public function set right(val:Material):void
{
if (_right == val)
return;
_right = val;
notifyMaterialChange(_right, "right");
}
/**
* Defines the material applied to the bottom side of the cube.
*/
public function get bottom():Material
{
return _bottom;
}
public function set bottom(val:Material):void
{
if (_bottom == val)
return;
_bottom = val;
notifyMaterialChange(_bottom, "bottom");
}
/**
* Defines the material applied to the top side of the cube.
*/
public function get top():Material
{
return _top;
}
public function set top(val:Material):void
{
if (_top == val)
return;
_top = val;
notifyMaterialChange(_top, "top");
}
/**
* Defines the material applied to the front side of the cube.
*/
public function get front():Material
{
return _front;
}
public function set front(val:Material):void
{
if (_front == val)
return;
_front = val;
notifyMaterialChange(_front, "front");
}
/**
* Defines the material applied to the back side of the cube.
*/
public function get back():Material
{
return _back;
}
public function set back(val:Material):void
{
if (_back == val)
return;
_back = val;
notifyMaterialChange(_back, "back");
}
/**
* Get the indicated face material from the obj
* */
private function getMaterial(Obj:Object,face:String):Material{
if(!Obj||!Obj[face]||!(Obj[face] is Material))
return new WireframeMaterial(Math.random()*0xFFFFFF);
return Obj[face] as Material;
}
/**
* Creates a new CubeMaterialsData object.
*
* @param init [optional] An initialisation object for specifying default instance properties.
*/
public function CubeMaterialsData(init:Object = null)
{
_left = getMaterial(init,"left");
_right = getMaterial(init,"right");
_bottom = getMaterial(init,"bottom");
_top = getMaterial(init,"top");
_front = getMaterial(init,"front");
_back = getMaterial(init,"back");
}
/**
* Default method for adding a materialChanged event listener
*
* @param listener The listener function
*/
public function addOnMaterialChange(listener:Function):void
{
addEventListener(MaterialEvent.MATERIAL_CHANGED, listener, false, 0, false);
}
/**
* Default method for removing a materialChanged event listener
*
* @param listener The listener function
*/
public function removeOnMaterialChange(listener:Function):void
{
removeEventListener(MaterialEvent.MATERIAL_CHANGED, listener, false);
}
}
}
Like this :


You can download it from here.
Click HERE to DOWNLOAD
When you are reading this article, I am trying to make this update to the svn of Away3dLite.