UV Mapping

The Flash plugin is required to view this object.

I have tried to wrap a bitmap around the cube, but it hasn’t worked so far. The problem is, there are 8 points to and 3 x 12  indices to render a cube. To map the bitmap each vertex needs its own uv map position.

But if you look at uv map that starts top left at 0,0 and ends at bottom right 1,1, you will notice that the point at the vertext at 0,0 should also be at 1,0. There is the problem. Analising a .obj file exported from Modo shows that a cube needs more points than eight to be properly uv mappped.UVMAP

I think, I will have to run more than 8 points per cube. Points 3 and 1 need to be cloned 2 times so that the different uv coordinates can be applied. Points 7 and 5 will be cloned once. The number of points increases by 6 to total 14 points per cube. This seems to be a lot more points. I will show the results in the next article.

Here is the current code:

package core
{
	import __AS3__.vec.Vector;
 
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.display.TriangleCulling;
	import flash.events.Event;
	import flash.utils.getTimer;
 
	import mx.core.Application;
 
	public class GameEngine extends Sprite
	{
		private var _lastTime:int;
 
		private const third:Number = 1/3;
 
		private var _vertices:Vector. = new Vector.();
		private var _render:Vector. = new Vector.();
		private var _indices:Vector. = new Vector.();
		private var _uvtData:Vector. = new Vector.();
		private var _cubes:Vector. = new Vector.(); 
 
		// Rubiks Cube properties
		private var _type:uint = 3; // 3 x 3 cube
		private var _size:Number = 100;
		private var _gap:Number = 20;
		private var _halfSize:Number = _size / 2;
		private var _offset:Number = _size + _gap;
 
		private var _focalLength:Number = 1000;
		private var _radius:Number = 100;
		private var _rHalf:Number = _radius / 2;
 
		private var a:Number = Math.PI / 360;
		private	var cos:Number = Math.cos(a);
		private	var sin:Number = Math.sin(a);
 
		private var _sp:Sprite = new Sprite();
 
		[Embed(source='assets/bmp2.png')]
		private var Chee:Class;
		private var _img:Bitmap = new Chee as Bitmap;
 
		public var xRot:Boolean;
		public var yRot:Boolean;
		public var zRot:Boolean;		
 
		public function GameEngine()
		{
			super();
			init();
		}
 
		private function onAdded(e:Event):void
		{
			_sp.x = Application.application.width / 2;
			_sp.y = Application.application.height / 2;
 
			if(this.hasEventListener(Event.ADDED_TO_STAGE))
			this.removeEventListener(Event.ADDED_TO_STAGE, onAdded);
 
			if(!this.hasEventListener(Event.RESIZE))
			this.addEventListener(Event.RESIZE, onAdded);
		}
 
		private function init():void
		{
			// Set World
			this.addEventListener(Event.ADDED_TO_STAGE, onAdded);
			addChild(_sp);
 
			var i:uint = 0;
			for(var r:uint = 0; r < _type; r++)
			{
				for(var c:uint = 0; c < _type; c++)
				{
					for(var d:uint = 0; d < _type; d++)
					{
						var s:DepthSorter= new DepthSorter();
						s.name = i.toString();
						s.zIndex = i;
						_sp.addChild(s);
						_cubes.push(s);
						makeCube(i,r,c,d);
						i++
					}
				}
			}
			this.addEventListener(Event.ENTER_FRAME, update);
			//update(null);
		}
 
		private function makeCube(index:uint, r:uint, c:uint, d:uint):void
		{
			var v0:uint = 0 + 8 * index;
			var v1:uint = 1 + 8 * index;
			var v2:uint = 2 + 8 * index;
			var v3:uint = 3 + 8 * index;
			var v4:uint = 4 + 8 * index;
			var v5:uint = 5 + 8 * index;
			var v6:uint = 6 + 8 * index;
			var v7:uint = 7 + 8 * index;
 
			if(index == 0)
			{
				_uvtData.push(1,third, 0.75,third, 1,0, 0.25,0, 0.25,third, 1,1, 1,0, 0,0);
				_indices.push(v2,v6,v0);
				_indices.push(v6,v4,v0);
				_indices.push(v6,v7,v4);
				_indices.push(v7,v5,v4);
				_indices.push(v7,v3,v5);
				_indices.push(v3,v1,v5);
				_indices.push(v3,v2,v1);
				_indices.push(v2,v0,v1);
				_indices.push(v3,v7,v2);
				_indices.push(v7,v6,v2);
				_indices.push(v0,v4,v1);
				_indices.push(v4,v5,v1);
			}
 
			// Create 8 3D-Points
			for(var i:uint = 0; i < 2; i++)
			{
				for(var j:uint = 0; j < 2; j++)
				{
					for(var p:uint = 0; p < 2; p++) 					{ 						var xPos:Number = (i * _size - _halfSize) + c * (_size + _gap) - _offset; 						var yPos:Number = (j * _size - _halfSize) + r * (_size + _gap)- _offset; 						var zPos:Number = (p * _size - _halfSize) + d * (_size + _gap)- _offset; 						_vertices.push(xPos, yPos, zPos); 					}		 				} 			}  		} 		 		private function compare(a:DepthSorter, b:DepthSorter):Number  		{ 			var aZ:uint = a.name as uint; 			if(a.zIndex > b.zIndex)
				return -1;
			else
				return 1;
		}
 
		private function update(e:Event):void
		{
			var thisTime:int = getTimer();
			var fps:Number = thisTime - _lastTime;
			_lastTime = thisTime;
			//trace(fps);
 
			// Update
 
			/**
			 * RENDER LOOP, converts 3d to screen and applies matrices
			 * */
 
			_render = new Vector.();
			var j:uint = 0;
 
			for(var i:uint = 0; i < 216; i++)
			{
				var xPos:Number = _vertices[i*3];
				var yPos:Number = _vertices[i*3+1];
				var zPos:Number = _vertices[i*3+2];
 
				var x1:Number;
				var y1:Number;
				var z1:Number;
 
				if(xRot) // X Rotation
				{
					x1 = xPos;
					y1 = cos * yPos - sin * zPos;
					z1 = cos * zPos + sin * yPos;
				}
				if(yRot) // Y Rotation
				{
					if(true)
					{
						x1 = cos * xPos - sin * zPos;
						y1 = yPos;
						z1 = cos * zPos + sin * xPos;
					}else
					{
						x1 = xPos;
						y1 = yPos;
						z1 = zPos;
					}
				}
				if(zRot) // Z Rotation
				{
					x1 = cos * xPos - sin * yPos;
                    y1 = cos * yPos + sin * xPos;
                    z1 = zPos;
				}
 
				if(!zRot && !xRot && !yRot)
				{
					x1 = xPos
                    y1 = yPos
                    z1 = zPos;
				}
 
				_vertices[i*3] = x1;
				_vertices[i*3+1] = y1;
				_vertices[i*3+2] = z1;
				if(i % 8 == 0)
				{
					_cubes[j].zIndex = z1;
					j++;
				}
 
				// Render
				var scale:Number = _focalLength / (_focalLength + _vertices[i*3+2]);
				_render.push(_vertices[i*3] * scale, _vertices[i*3+1] * scale);
			} 
 
			// Draw
				for(var t:uint = 0; t < 27; t++)
				{
					with(_cubes[t].graphics)
					{
 
							clear();
							lineStyle(1,0);
							//drawCircle(300,300,t *10);
							beginBitmapFill(_img.bitmapData);
							//beginFill(0xFF9900);
								var f:uint = t*16;
								drawTriangles(_render.slice(f,f+16), _indices, _uvtData, TriangleCulling.POSITIVE);
							endFill();
 
					}
				} 
 
				// sort
				_cubes.sort(compare);
				for(var q:uint = 0; q < 27; q++)
				{
					_sp.addChild(_cubes[q]);
				}
 
		}
 
	}
 
}

One comment

  1. make a cube class and a 3DView class. your code is not readable.

    to color each face:

    vertices = Vector.([
    style.width,-style.height,style.depth,
    style.width,-style.height,-style.depth,
    -style.width,-style.height,-style.depth,
    -style.width,-style.height,style.depth,
    style.width,style.height,style.depth,
    style.width,style.height,-style.depth,
    -style.width,style.height,-style.depth,
    -style.width,style.height,style.depth
    ]);

    projection = new Vector.;

    face[1] = Vector.([3, 1, 0, 3, 2, 1]);
    face[2] = Vector.([5, 7, 4, 5, 6, 7]);
    face[3] = Vector.([1, 4, 0, 1, 5, 4]);
    face[4] = Vector.([2, 5, 1, 2, 6,5]);
    face[5] = Vector.([3, 6, 2, 3, 7, 6]);
    face[6] = Vector.([7, 0, 4, 7, 3, 0]);

    private function draw():void
    {
    Utils3D.projectVectors(matrix, vertices,projection,new Vector.);

    var i:int = 0;
    this.graphics.clear();

    for(var key:String in face)
    {
    var alpha:Number = 1; if(style.alphas[i] != undefined) alpha = style.alphas[i];
    this.graphics.beginFill(style.colors[i], alpha);
    this.graphics.lineStyle(0,0,0);
    var culling:String = “negative”; if(alpha != 1) culling = “none”; this.graphics.drawTriangles(projection, face[key], null, culling);
    i++;
    }

    this.graphics.endFill();
    }

    im new to this you can use the uvdata parameter in Utils3D.projectVectors. i dunno.

Leave a comment