script to create 3d cube

All things .jsx

Moderator: Paul Tuersley

Post Reply
vitaminman
Posts: 3
Joined: January 9th, 2005, 6:59 pm

Hey,

This script is used to create a 3d cube. You can later replace the different sides and spin the null around for easy animation. To make it more flexibe, you can enter the size of the sides and the script will adjust.

In order for the sides to hold their positions (I've found that during animations, sometimes the sides will slip slightly out of place), they are all positioned with expressions and should keep their place no matter what you do to them.

There is a null object as well, all the sides have been parented to it and should make moving the cube around relatively simple.

Take care,

Nick


Code: Select all


//*********************************************************
//this is a script to make a 3d cube with a null object with which to control the cube
//to run, simply have an empty comp ready, select it in the project window,
//and run the script. the cube's sides are held in place through expressions
//so they will 'always' hold their positions.
//thanks to dan ebberts and everyone at creative cow for their help.

//nicholas white
//vitamin_man@email.com


//****************************************************
// setting up project
side_size = prompt ("how big will each layer be?", "");
side_size = side_size/1
offset = side_size/2
myComp = app.project.item(1);
//***************************************************

//****************************
//create new 3d layers
for (i=1; i<=6; i++)
    {
      solid_name = i;
      mySolid = myComp.layers.addSolid([1.0,0.5,0.3], "side " +i , side_size, side_size, 1);
//make 3d
    mySolid.threeDLayer = true;
//add expression to fix the anchor point to the dead center of the solid
      solid_anchor_expression = "anchor = [" +offset+ "," +offset+ ",0]";
      mySolid.property("anchorPoint").expression = solid_anchor_expression;
//add expression to fix the x,y and z rotations to 0
        var rot_axis;
        for (r=1; r<=3; r++)
            {
            switch(r)
                  {
                  case 1:
                  rot_axis = 'X';
                  break;
                  case 2:
                  rot_axis = 'Y';
                  break;
                  case 3:
                  rot_axis = 'Z';
                  break;
                  default:
                  }
              rot_axis_expression = "rotation" +rot_axis+ " = 0";
              var rot_property = (rot_axis + " Rotation");
              mySolid.property(rot_property).expression = rot_axis_expression;
              }
//add expressions to orient the layers so they all face the right direction in 3d space
       var or_array;
        {
            switch(i)
                  {
                  case 1:
                  or_array = '[0,0,0]';
                  break;
                  case 2:
                  or_array = '[0,90,0]';
                  break;
                  case 3:
                  or_array = '[0,90,0]';
                  break;
                  case 4:
                  or_array = '[0,0,0]';
                  break;
                  case 5:
                  or_array = '[90,0,0]';
                  break;
                  case 6:
                  or_array = '[90,0,0]';
                  break;
                  default:
                  }
              or_array_expression = "orientation = " +or_array;
              mySolid.property("Orientation").expression = or_array_expression;
          }
//add expressions to position the layers correctly in 3d space
      var pos_array;
            {
            switch(i)
                  {
                  case 1:
                  pos_array = "[" +offset+ "," +offset+ ",0]";
                  break;
                  case 2:
                  pos_array = "[" +side_size+ "," +offset+ "," +offset+ "]";
                  break;
                  case 3:
                  pos_array = "[0," +offset+ "," +offset+ "]";
                  break;
                  case 4:
                  pos_array = "[" +offset+ "," +offset+ "," +side_size+ "]";
                  break;
                  case 5:
                  pos_array = "[" +offset+ ",0," +offset+ "]";
                  break;
                  case 6:
                  pos_array = "[" +offset+ "," +side_size+ "," +offset+ "]";
                  break;
                  default:
                  }
              pos_array_expression = "position = " +pos_array;
              mySolid.property("Position").expression = pos_array_expression;
            }
    }
//******************************************

//******************************************
//add null object, make it the parent of the solids
        
//add a null object with which to control the layers' movement
myNull = myComp.layers.addNull();
//make 3d
myNull.threeDLayer = true;
//add expression to fix the anchor point to the dead center of the null object
null_anchor_expression = "anchor = [0,0,0]";
myNull.property("anchorPoint").expression = null_anchor_expression;
//add expression to position the null in the dead center of the cube[/color]
myComp.layer(1).property("Position").setValue([offset,offset,offset]);//set the solids to be children of the null object
var null_parent;
null_parent = myComp.layer(1);
for (c=2; c<=7; c++)
    {
    myComp.layer(c).parent = null_parent;
    }
//***********************************************


alert ("done!");
vitaminman
Posts: 3
Joined: January 9th, 2005, 6:59 pm

Hey,

Here is a link where you can download the file directly:

http://wemads.com/stuff/3d_cube.zip

Take care,

Nick
o
Posts: 2
Joined: December 6th, 2006, 3:45 pm
Contact:

having a bit of trouble.
i'm using ae7. how do i define the dimensions when the script prompts "how big will each layer be?"
thanks.
User avatar
Disciple
Posts: 137
Joined: June 5th, 2004, 8:05 am
Location: Los Angeles, CA
Contact:

Just decide on a dimensions that works for your comp. For example if you were in a 720x576 comp and you wanted to see the whole cube you would choose a size of 400 for example. As it is a cube, only one dimension needs to be specified, since both sides will be equal (versus a rectangle)

Does that clarify it for you?

Alex
User avatar
Atomic
Posts: 157
Joined: April 30th, 2007, 5:55 am
Location: United States, Ohio

I re-wrote some of the script to fix the minor bugs that bothered me.

The origin can now be defined at the top, bottom, or center of the cube.

The sides are named and color coded.

You can also specify a height for the cube. This has some advantage over simply scaling the cube's height. This way if you want to image map to the sides of the cube you can match the width and height of those layers prior to creation and simply swap out the solids (CTRL-ALT-/) for your images after generation.

If you want a camera in your comp after generation, there is a flag for that as well.

This script inherits the aspect bug of the above script. It is currently configured for square pixels, so if you run it against a 0.9 or 1.2 aspect comp, the cube edges will not line up properly.

Play with it and enjoy!

Code: Select all

//*********************************************************
//this is a script to make a 3d cube with a null object with which to control the cube
//to run, simply have an empty comp ready, select it in the project window,
//and run the script. the cube's sides are held in place through expressions
//so they will 'always' hold their positions.
//thanks to dan ebberts and everyone at www.creativecow.net for their help.

//nicholas white
//vitamin_man@email.com
//ww.wemads.com

//Re-write to center cube and cube height by Atom.
//8-29-2007.

//Setting up the project
//side_size = prompt ("how big will each layer be?", "");
side_size = 360;
cube_height = 480;				//Set = to "side_size" for a cube.
side_height = cube_height-side_size;	//This number should not go negative!
pixel_aspect = 1.0;				//NTSC D1 Square Pixel 720x540 - This value must match comp or generated panel size will be wrong.
origin_index = 2;					//Origin styles 0=centered, 1=top, 2=bottom.
add_camera = true;
side_size = side_size/1;
offset = side_size/2;
myComp = app.project.item(1);

//Create new 3d layers
for (i=1; i<=6; i++)
{
	//Construct a color and a name for each side.
	side_adjust = side_height;			//All other sides need side adjust to facilitate new height parameter.
	switch(i)
	{
		case 1:
			side_color = [1.0,0.5,0.3];
			side_name = "front";
			break;
		case 2:
			side_color = [1.0,0.3,0.5];
			side_name = "right";
			break;
		case 3:
			side_color = [0.5,1.0,0.3];
			side_name = "left";
			break;
		case 4:
			side_color = [0.3,1.0,0.5];
			side_name = "back";
			break;
		case 5:
			side_color = [0.3,0.5,1.0];
			side_name = "top";
			side_adjust = 0;			//Top needs no side adjust.
			break;
		case 6:
			side_color = [0.5,0.3,1.0];
			side_name = "bottom";
			side_adjust = 0;			//Bottom needs no side adjust.
			break;
	}
	mySolid = myComp.layers.addSolid(side_color, side_name, side_size, side_size+side_adjust , pixel_aspect);
	mySolid.threeDLayer = true;	//make 3d

	//Set the orientation for each layer.
	myProperty = mySolid.property("orientation"); 
	switch(i)
	{
		case 1:
			myProperty.setValue ([0,0,0]);
			break;
		case 2:
			myProperty.setValue ([0,90,0]);
			break;
		case 3:
			myProperty.setValue ([0,90,0]);
			break;
		case 4:
			myProperty.setValue ([0,0,0]);
			break;
		case 5:
			myProperty.setValue ([90,0,0]);
			break;
		case 6:
			myProperty.setValue ([90,0,0]);
			break;
		default:
	}

	//Set the position of each layer in 3D space.
	myProperty = mySolid.property("position"); 
	switch(i)
	{
		case 1:
			myProperty.setValue ([offset, offset+(side_height/2) ,0]);
			break;
		case 2:
			myProperty.setValue ([side_size, offset+(side_height/2) ,offset]);
			break;
		case 3:
			myProperty.setValue ([0,offset+(side_height/2) , offset]);
			break;
		case 4:
			myProperty.setValue ([offset, offset+(side_height/2),side_size]);
			break;
		case 5:
			//Top.
			myProperty.setValue ([offset, 0,offset]);
			break;
		case 6:
			//Bottom.
			myProperty.setValue ([offset, cube_height ,offset]);
			break;
		default:
	}
}
//end for...

//Add null object, make it the parent of the solids
myNull = myComp.layers.addNull();
myNull.name = "Controller";			//Why doesn't this line of code work?
myNull.threeDLayer = true;			//Make 3D.

//Set the anchor point style for the cube.
switch(origin_index)
{
	case 1:
		//Anchor to bottom of cube.
		myNull.property("position").setValue([offset,0,offset]);
		writeLn ("Cube origin at top.");
		break;
	case 2:
		//Anchor to top of cube.
		myNull.property("position").setValue([offset,cube_height,offset]);
		writeLn ("Cube origin at bottom.");
		break;
	default:
		//Anchor to center of cube.
		myNull.property("position").setValue([offset,offset+(side_height/2),offset]);
		writeLn ("Cube origin at center.");
}

//Set the solids to be children of the null object.
for (c=2; c<=7; c++)
{
	myComp.layer(c).parent = myNull;
}

if (add_camera == true)
{
	//Add a camera.
	myCamera = myComp.layers.addCamera("Camera1",[360.0,243.0]);
	myCamera.moveToBeginning();
}
After generation, use the Null object to control the cube.
zold

I just couldn't let this sit any longer.
I'm planning on adding this to my site's collection.
Enjoy!
[update -- added missing semicolon ... pre-CS3 fix coming soon ... ]
[update -- does this work for pre-CS3?]
[update -- "group leveling" problem may be present using with early versions of AE, but probably just on Intel Macs (?) (my earlier assessment was in error)]

Code: Select all

//*********************************************************
//this is a script to make a 3d cube with a null object with which to control the cube
//to run, simply have an empty comp ready, select it in the project window,
//and run the script.
//thanks to dan ebberts and everyone at www.creativecow.net for their help.

//nicholas white
//vitamin_man@email.com
//ww.wemads.com

//Re-write to center cube and cube height by Atom.
//8-29-2007

// 12/2007 -- modified by CRGreen to include:
//             UI, formulae entry implementation for UI (just for kicks, to teach myself the ECMA try block), undo for entire process
//             also made camera not auto-orient (99.9999% of the time this is the way i want a camera), 
//             removed pixel aspect ratio stuff -- all square pixels now (but will warn of mismatch if user forgot to check comp setting).
//             making "Controller" null change to matching (square) p.a.r. after parenting makes shape work in any p.a.r. comp
//             made opacities of layers at 65% to show off box better
//             parenting stage now works with unique collection of solids ... so city-building now possible  :-)
//////////////////////////////////////

var w = buildUI();
if (w != null) {
	w.show();
}

function buildUI(thisObj) {
	//this is my first attempt at using a "Script UI Panel" implementation
	// on my machine, it doesn't seem to work (does not create a dockable panel with my stuff on it)
	//var win =   (thisObj instanceof Panel) ? thisObj : new Window('palette', 'Build 3D Cube',[300,100,670,270]);
	var win =  new Window('palette', 'Build 3D Cube',[300,100,670,270]);
	
	currentPA=1;
	/*
	if (app.project.activeItem != null) {
		if (app.project.activeItem instanceof CompItem) {
			var currentPA = app.project.activeItem.pixelAspect.toString();
		}
	}
	*/
	if (win != null) {
		win.originPnl = win.add('panel', [17,17,117,137], 'Style:');
		win.originCenRad = win.originPnl.add('radiobutton', [14,15,84,37], 'Center');
		win.originTopRad = win.originPnl.add('radiobutton', [14,45,84,67], 'Top');
		win.originBotRad = win.originPnl.add('radiobutton', [14,74,84,96], 'Bottom');
		win.originBotRad.value = true;
		
		win.sideSizLbl = win.add('statictext', [141,16,253,38], 'Side Size:');
		win.sideSizT = win.add('edittext', [258,13,348,35], '500');
		win.cubeHtLbl = win.add('statictext', [141,46,253,68], 'Cube Height:');
		win.cubeHtT = win.add('edittext', [258,43,348,65], '500');
		
		win.pixARLbl = win.add('statictext', [141,76,253,98], 'Pixel Aspect Ratio:');
		win.pixARLbl.enabled=false;
		win.pixART = win.add('edittext', [258,74,348,96], currentPA);
		win.pixART.enabled=false;
		
		win.camCheck = win.add('checkbox', [141,105,291,125], ' Add Camera');
		win.camCheck.value = true;
		
		win.okBtn = win.add('button', [273,136,353,158], 'Build', {name:'Build'});
		win.okBtn.onClick = function () {buildCube(win);};
	}
	return win
}

function checkNumberEntry(entree) {
	// see if we can evaluate the entry
	// if we can't, nullify it;
	try {
		rezult=eval(entree);
	} catch ( error ) {
		rezult=null;
	}
	// if we can, make sure it evals to a number; nullify it if it doesn't
	// this allows us to include formulae in our number entries (like "500*1200" for example) -- just like most of AE's number entry fields
	if ( isNaN(parseFloat(rezult)) ) { rezult=null; }
	return rezult;
}

function buildCube(windo) {
	
	entryError = "";
	
	side_size = checkNumberEntry(windo.sideSizT.text);
    if ( (side_size == null) || (side_size == 0) || (side_size == undefined) ) {
		entryError = "invalid entry for side size\r";
		windo.sideSizT.text = "";
	}
	cube_height = checkNumberEntry(windo.cubeHtT.text);
    if ( (cube_height == null) || (cube_height == 0) || (cube_height == undefined) ) {
		entryError = (entryError + "invalid entry for cube height\r");
		windo.cubeHtT.text = "";
	}
	side_height = cube_height-side_size;   //This number should not go negative!
	
	// left over:
	pixel_aspect = checkNumberEntry(windo.pixART.text);
	if ( (pixel_aspect == null) || (pixel_aspect == 0) || (pixel_aspect == undefined) ) {
		entryError = (entryError + "invalid entry for pixel aspect ratio\r");
		windo.pixART.text = "";
	}
	
	if (entryError == "") {
		if (windo.originCenRad.value) {
			origin_index = 0;
		} else if (windo.originTopRad.value) {
			origin_index = 1;
		} else if (windo.originBotRad.value) {
			origin_index = 2;
		}
		add_camera = windo.camCheck.value;
		
		side_size = side_size/1;
		offset = side_size*.5;
		
		if (app.project.activeItem != null) {
			if (app.project.activeItem instanceof CompItem) {
				
				myComp = app.project.activeItem;
				theCompPA = myComp.pixelAspect;
				var confirmedPA=true;
				
				if ( theCompPA != parseFloat(pixel_aspect) ) {
					confirmedPA=confirm("Pixel Aspect Ratio of the Cube's solids does not match your comp. Is this Okay?");
				}
				if (confirmedPA) {
					app.beginUndoGroup("Build Cube");
					//Create new 3d layers
					var sidesCollection = new Array();
					for (i=1; i<=6; i++)
					{
						//Construct a color and a name for each side.
						side_adjust = side_height;         //All other sides need side adjust to facilitate new height parameter.
						
						switch(i)
						{
						case 1:
							side_color = [1.0,0.5,0.3];
							side_name = "front";
							break;
						case 2:// R
							side_color = [1.0,0.3,0.5];
							side_name = "right";
							break;
						case 3:// L
							side_color = [0.5,1.0,0.3];
							side_name = "left";
							break;
						case 4:
							side_color = [0.3,1.0,0.5];
							side_name = "back";
							break;
						case 5:
							side_color = [0.3,0.5,1.0];
							side_name = "top";
							side_adjust = 0;         //Top needs no side adjust.
							break;
						case 6:
							side_color = [0.5,0.3,1.0];
							side_name = "bottom";
							side_adjust = 0;         //Bottom needs no side adjust.
							break;
						}
						mySolid = myComp.layers.addSolid(side_color, side_name, side_size, side_size+side_adjust , pixel_aspect);
						mySolid.threeDLayer = true;   //make 3d
						mySolid.property("opacity").setValue(65);
						
						//Set the orientation for each layer.
						myProperty = mySolid.property("orientation");
						switch(i)
						{
						case 1:
							myProperty.setValue ([0,0,0]);
							break;
						case 2:
							myProperty.setValue ([0,90,0]);
							break;
						case 3:
							myProperty.setValue ([0,90,0]);
							break;
						case 4:
							myProperty.setValue ([0,0,0]);
							break;
						case 5:
							myProperty.setValue ([90,0,0]);
							break;
						case 6:
							myProperty.setValue ([90,0,0]);
							break;
						default:
						}
						
						//Set the position of each layer in 3D space.
						myProperty = mySolid.property("position");
						switch(i)
						{
						case 1:
							myProperty.setValue ([offset, offset+(side_height*.5) ,0]);
							break;
						case 2:// R
							myProperty.setValue ([side_size, offset+(side_height*.5) ,offset]);
							break;
						case 3:// L
							myProperty.setValue ([0,offset+(side_height*.5) , offset]);
							break;
						case 4:
							myProperty.setValue ([offset, offset+(side_height*.5),side_size]);
							break;
						case 5:
							//Top.
							myProperty.setValue ([offset, 0,offset]);
							break;
						case 6:
							//Bottom.
							myProperty.setValue ([offset, cube_height ,offset]);
							break;
						default:
						}
						// build collection of solids here
						sidesCollection[(i-1)] = mySolid;
					}
					//end for...
					
					//Add null object, make it the parent of the solids
					myNull = myComp.layers.addNull();
					myNull.name = "Controller";
					myNull.threeDLayer = true;         //Make 3D.

					//Set the anchor point style for the cube.
					switch(origin_index)
					{
					case 1:
						//Anchor to bottom of cube.
						myNull.property("position").setValue([offset,0,offset]);
						writeLn ("Cube origin at top.");
						break;
					case 2:
						//Anchor to top of cube.
						myNull.property("position").setValue([offset,cube_height,offset]);
						writeLn ("Cube origin at bottom.");
						break;
					default:
						//Anchor to center of cube.
						myNull.property("position").setValue([offset,offset+(side_height*.5),offset]);
						writeLn ("Cube origin at center.");
					}
					
					// what if we want to make more than one box in a comp?
					// changed to earlier make a collection of new solids, then use that collection here
					//Set the solids to be children of the null object.
					for (c=0; c<=5; c++)
					{
						sidesCollection[c].parent = myNull;
					}
					
					//this corrects for left and right pixel aspect problem in non-square comps:
					myNull.source.pixelAspect = 1;

					if (add_camera == true)
					{
						//Add a camera.
						myCamera = myComp.layers.addCamera("Camera1",[myComp.width*.5,myComp.height*.5]);
						myCamera.moveToBeginning();
						myCamera.autoOrient = AutoOrientType.NO_AUTO_ORIENT;
						myCamera.property("position").setValue([offset,offset,0]);
					}
					app.endUndoGroup();
				}
			}
		}
	} else {
		alert("oops\r" + entryError);
	}
}
Last edited by zold on December 22nd, 2007, 12:03 am, edited 4 times in total.
User avatar
Atomic
Posts: 157
Joined: April 30th, 2007, 5:55 am
Location: United States, Ohio

Hmm...

It does not work on Ae 6.5 I get an error on line 31.
Panel Is Undefined

Code: Select all

var win =   (thisObj instanceof Panel) ? thisObj : new Window('palette', 'Build 3D Cube',[300,100,670,270]);
Is this for CS3 only?
zold

Atomic wrote: Is this for CS3 only?
Hi Atomic. Well, yes, it is for CS3 only, or whenever Panels were first introduced into the object model (although, as mentioned in my comments, it didn't actually work as a panel when I tried it -- could be a mac-only problem). When I get some time, I'll put an if/then for earlier versions, or maybe just ditch the Panel thing altogether. But I'll be relying on you to test it to see if it works in 6.5. :wink: I hope it will ...
zold

Hey Atom,
Made a simple adjustment up there to see if this works with earlier versions of AE. Let me know what it does...

cg
zold

um ... oops.
make sure you grab the whole script, as i had to correct a mistake.

-cg
User avatar
Atomic
Posts: 157
Joined: April 30th, 2007, 5:55 am
Location: United States, Ohio

Verified, it works with AE 6.5.

It did complain with some kind of layering message, but the cube did generate.
Stolichnaya
Posts: 4
Joined: August 24th, 2004, 9:48 am

I'm working with CS3 Mac/Intel (OS10.4.11) and took the latest version of the script (by Zold). When I want to use the script, the pixel aspect ratio box is greyed out so I can't enter a value. Also, I've found out that somehow the cube is leaking i.e. the solids are not 'watertight' placed against eachother so you can see just a fraction of the opposite layers behind. Is this due to the lack of the aspect ratio?
Stolichnaya
Posts: 4
Joined: August 24th, 2004, 9:48 am

Anyone? In the mean time I had to give the solids a stroke around the edges to fix the probelem. Not ideal but it was a quick fix.
User avatar
Atomic
Posts: 157
Joined: April 30th, 2007, 5:55 am
Location: United States, Ohio

Stolichnaya,

Yes, that is the reason why. You could try my original version (up a post or two) without the GUI and simply put in your comp size and match the ratio by hand.
"Up And Atom

No...No

Up And At Them!"
Post Reply