Script Help on Ordering 845 Bricks

Script Help on Ordering 845 Bricks

Byteman
Collaborator Collaborator
1,198 Views
14 Replies
Message 1 of 15

Script Help on Ordering 845 Bricks

Byteman
Collaborator
Collaborator

I have built a wall of 845 bricks manually as in the sample video. After building the wall, I moved on to next parts of the animation including the collapse of the wall with Mass Fx. After the tedious physics work, achieved the look I want, but the client wanted a more random building of the wall and in a shorter time period. (Current organizing of bricks take 275 frames [11secs.] in 25FPS) 

I need script help to randomly build this wall without spoiling the rest of the brick animation handled with Mass Fx. We can delete entire organizing animation and set a final (ordered state) key to frame 125.
(125 is not a precise value- can be set to any number around 125, according to the divisibility with the number of lines to keep the equality in ordering speed. 

Note: Bricks are not instanced, their pivots at their base. Bricks should start from an out of view area, above.Falling down from above 430 cm's is ok as the wall is 4 meters

 

I Appreciate the help, and without a script I'll manually reorder the bricks in a separate file, trying to keep everthing the same and compose afterwards.

0 Likes
Accepted solutions (1)
1,199 Views
14 Replies
Replies (14)
Message 2 of 15

denisT.MaxDoctor
Advisor
Advisor

what do you want to randomize? animation or brick placement? or brick size?

0 Likes
Message 3 of 15

denisT.MaxDoctor
Advisor
Advisor

let me give you one piece of advice based on personal experience... it is much more difficult to "assemble" something beautifully than to "take it apart"... that is, you need to take apart the wall beautifully, and then repeat assembling just in reverse order.

0 Likes
Message 4 of 15

Byteman
Collaborator
Collaborator

@denisT.MaxDoctor wrote:

that is, you need to take apart the wall beautifully, and then repeat assembling just in reverse order.


That is exactly what I did to place in the current assembly order manually. 

If you view the animation, bricks are assembled exactly the same way for every line. Client wants bricks to fall (fly) and form the wall, but not like the current "Printing like" line-by-line assembly. They may fly like a flock of bricks.

 

I thought it might be possible and easy by a script to,

1. Set a frame for all bricks at frame (let's say) 25 in the assembled state, (Otherwise total anim. will be too long)

2. Move all bricks to some coordinate around the world center at z=430 (Above the wall's center out of safe area) and set a key at frame 0 at that position. All bricks will be assembled from 0 to 25 at the same time.

3. Then slide the two keys of each brick like 5 frames but by a name order. First line contains Bricks from Brick_00 to Brick_32. 

There is a tricky part though which I didn't think about much:

With each brick travelling for 25 frames and a sliding of 5 frames Animation length will be 845x5 +25 😄

Total formation should not be that long. I thought something no more than 10 seconds.

The only way to handle this is, assembling one line like all together, then the next line and slide it 5 frames, then 26 total lines x5 will make  130 frames + 50 frames .

If possible each brick on single line might assemble with a 2 frame delay (which makes a total delay of 66 frames for 33 bricks)

 

The only concern is bricks should come to the final position in their name orders otherwise some bricks will rest in the air without a brick present under it.

 

Any way to handle this? 

Right now I'm dealing with other parts of the project. If I find time to do the assembly manually from scratch, I'll post it back. 

0 Likes
Message 5 of 15

leeminardi
Mentor
Mentor

When I think of the sequence for laying a brick wall the process starts at an end and goes up several courses before the brick span the entire length.  Similar to this sequence I found on the web.

leeminardi_0-1645025722821.png

Your animation never has more than two active courses.  I suggest going up 4 or 5 levels at an end  before completing a full row.  To give a more random appearance a script that allows you to point to brick in the order of construction (or better yet,  deconstruction) and then creates keys based on that sequence might provide the results you need. In this process you would start with the completed wall that you have and going backwards in time remove bricks for several courses in the middle and randomly work to each end but making sure you go down several courses before moving on to the next area.    If you are happy with the current trajectory of the bricks the script could just move the keys of the bricks based on their current timing and the timing imposed by the selection order.    

 

lee.minardi
Message 6 of 15

denisT.MaxDoctor
Advisor
Advisor
Accepted solution

it was a fun to play with ... 

 

 

 

delete objects
gc()

max create mode
-- seed 0

/************ brick size ***********/
height = 6.5
width = 25
depth = 12
fillet = 0.2

_brick = chamferbox name:"brick" length:depth width:width height:height fillet:fillet smooth:0 wirecolor:red ishidden:on

fn firstOdd id count: = ( mod id (2*count) == 1 )
fn lastEven id count: = ( mod id (2*count) == 0 )

fn shuffleArr list seedvalue: = 
(
	if seedvalue != unsupplied do seed seedvalue
		
	for k = 1 to list.count do 
	(
		i = random 1 k
		swap list[k] list[i]
	)
	list
)

fn makeFreeFallController node offset_z:0 offset_t: id:0 bits: = 
(
	pos = node.pos
	
	x = createinstance float_list
	c = x.available.controller = bezier_float()
	c.value = pos.z + offset_z
	x.setname 1 "Initial Z"

	s = x.available.controller = float_script()
	s.addconstant #g (-9.8*100)
	s.addconstant #id id
	s.addconstant #offset offset_z
	s.addconstant #time offset_t
	s.setexpression "if (t = s - time) > 0 then (amax -offset (g*t*t/2)) else 0"

	x.setname 2 "Free Fall"
	
	x.setactive 2
	
	node.pos.controller[3].controller = x
)	

numrows = 20		-- number brick rows
numcols = 10		-- number bricks in row 

/**************** define picking condition ****************/

_bits = #()
for v = 0 to (numrows - 1) do
(
	i = 1 - (mod v 2)
	for u = 0 to (numcols - 1) do
	(
		id = v*numcols + u + 1
		bits = #{}
		if id > numcols do
		(
			if not (firstodd id count:numcols) do append bits (id - numcols - i) 
			if not (lasteven id count:numcols) do append bits (id - numcols + 1 - i) 
		)
		append _bits bits 
	)
)	

/**************** define picking order ****************/

_set = #{1..numrows*numcols} as array
_order = #()
_taken = #{}

while _set.count > 0 do
(
	shuffleArr _set
	for k = _set.count to 1 by -1 do
	(
		i = _set[k]
		bits = _bits[i]
		if (bits - _taken).isempty do 
		(
			append _order i
			append _taken i
			deleteitem _set k
		)
	)
)

/**************** build brick formation ****************/

_bricks = #()
_t_delta = 0.01 	-- time offset for next going brick
_gap = [0,0,0] 		-- gat between bricks x - columns, z - rows; can be randomized
_z = 250			-- initial start level for brick formation

with redraw off
(
	_t = 0
	for v = 0 to (numrows - 1) do
	(
		sx = (mod v 2) * ((width + _gap.x)/2) 
		z = v * (height + _gap.z)
		for u = 0 to (numcols - 1) do
		(
			col = random red orange
			
			x = u * (width +_gap.x) + sx
			p = [x, 0, z]
			b = instance _brick pos:p wirecolor:col
			id = v*numcols + u + 1
						
			n = finditem _order id
			
			makeFreeFallController b id:id offset_z:_z offset_t:(_t_delta*n)
			append _bricks b
		)
	)	
)

 

 

 

 

hope this helps or gives useful tips and tricks

Message 7 of 15

Swordslayer
Advisor
Advisor

Looks like choice and even functions are missing, I'd expect them to be something like this:

fn even nr = nr = bit.and 1L nr == 0
fn choice bool x y = if bool then x else y

 

0 Likes
Message 8 of 15

denisT.MaxDoctor
Advisor
Advisor
Haha... I try not to put my mxs methods, but sometimes I do it automatically
0 Likes
Message 9 of 15

denisT.MaxDoctor
Advisor
Advisor

i fixed it. thanks

0 Likes
Message 10 of 15

Byteman
Collaborator
Collaborator

 

I couldn't get back any earlier.

 

This is beautiful. This falling speed and order is more than what I imagined. 😄

Thank you very much indeed.👍👏

 

0 Likes
Message 11 of 15

Byteman
Collaborator
Collaborator

How can I make this start falling at a frame other than zero? This script does everything automatically.

And my next question will be, whether I can add physics controlled animation to these bricks?

 

0 Likes
Message 12 of 15

denisT.MaxDoctor
Advisor
Advisor

@Byteman wrote:

How can I make this start falling at a frame other than zero? This script does everything automatically.

And my next question will be, whether I can add physics controlled animation to these bricks?

 


How can I make this start falling at a frame other than zero?

 

(
	start_frame = 50.0f
	t = start_frame/frameRate -- time in seconds
	for id in _order do
	(
		s = _tracks[id]
		t += (random 0.01 0.02)
		s.setconstant #time t
	)
)

 

 

I can add physics controlled animation to these bricks?

- what kind of physics do you want to add? (please provide video or picture for clarity)

 

 

This script does everything automatically...

 

It's a code snippet, not a tool. But it has everything to organize it like a tool with a user interface.

0 Likes
Message 13 of 15

denisT.MaxDoctor
Advisor
Advisor

here is a new advanced snippet:

delete objects
gc()

max create mode
-- seed 0

/************ brick size ***********/
height 	= 6.5
width 	= 25.0
depth 	= 12.0
fillet 	= 0.2

slidertime = 0

_brick = chamferbox name:"brick" length:depth width:width height:height fillet:fillet smooth:0 wirecolor:red ishidden:on

fn firstOdd id count: = ( mod id (2*count) == 1 )
fn lastEven id count: = ( mod id (2*count) == 0 )
fn freeEdge id count: = ( mod id count < 2 )

fn shuffleArr list seedvalue: = 
(
	if seedvalue != unsupplied do seed seedvalue
		
	for k = 1 to list.count do 
	(
		i = random 1 k
		swap list[k] list[i]
	)
	list
)

fn makeFreeFallController node offset_z:0 offset_t:0 id:0 bits: = 
(
	pos = node.pos
	
	x = createinstance float_list
	c = x.available.controller = bezier_float()
	c.value = pos.z + offset_z
	x.setname 1 "Initial Z"

	s = x.available.controller = float_script()
	s.addconstant #g (-9.8*100)
	s.addconstant #id id
	s.addconstant #offset offset_z
	s.addconstant #time offset_t
	s.setexpression "if (t = s - time) > 0 then (amax -offset (g*t*t/2)) else 0"

	x.setname 2 "Free Fall"
	
	x.setactive 2
	
	node.pos.controller[3].controller = x
	s
)	

numrows = 20		-- number brick rows
numcols = 10		-- number bricks in row 

/**************** define picking condition ****************/

_bits = #()

for v = 0 to (numrows - 1) do
(
	i = 1 - (mod v 2)
	for u = 0 to (numcols - 1) do
	(
		id = v*numcols + u + 1
		bits = #{}
		if id > numcols do
		(
			if not (firstodd id count:numcols) do append bits (id - numcols - i) 
			if not (lasteven id count:numcols) do append bits (id - numcols + 1 - i) 
		)
		append _bits bits 
	)
)	

/**************** define picking order ****************/

_set = #{1..numrows*numcols} as array
_order = #()
_taken = #{}

while _set.count > 0 do -- and not esc_ 
(
	shuffleArr _set
	for k = _set.count to 1 by -1 do
	(
		id = _set[k]
		bits = _bits[id]
		if (bits - _taken).isempty do
		(
			if (freeedge id count:numcols) or (random 0 4 == 1) do -- here you can randomize and control edge-to-center brick distribution
			(
				append _order id
				append _taken id
				deleteitem _set k
			)
		)
	)
)

/**************** build brick formation ****************/

_bricks = #()
_tracks = #()

_t_delta 	= 0.01 			-- time offset for next going brick
_gap 		= [0.1,0,0.1] 	-- gat between bricks x - columns, z - rows; can be randomized
_z 			= 250			-- initial start level for brick formation

with redraw off
(
	h = height + _gap.z
	w = width + _gap.x

	for v = 0 to (numrows - 1) do
	(
		sx = (mod v 2) * (w/2) 
		z = v * h
		for u = 0 to (numcols - 1) do
		(
			col = random red orange
			
			x = u * w + sx
			y = 0 --random -5 5
			p = [x, y, z]
			b = instance _brick pos:p wirecolor:col
			id = v*numcols + u + 1
						
			n = finditem _order id
			
			t = makeFreeFallController b id:id offset_z:_z 
			append _bricks b
			append _tracks t
		)
	)	
)

(
	start_frame = 50.0f
	t = start_frame/frameRate -- time in seconds
	for id in _order do
	(
		s = _tracks[id]
		t += (random 0.01 0.02) -- here you can randomize brick start delay
		s.setconstant #time t
	)
)
0 Likes
Message 14 of 15

Byteman
Collaborator
Collaborator
After the bricks are organized, I just think of collapsing the wall with MassFx. Convert them to rigid bodies and a few collisions.
I haven't tried it yet, but as the bricks are script controlled I just presume I may have problems.
0 Likes
Message 15 of 15

denisT.MaxDoctor
Advisor
Advisor

 


@Byteman wrote:
After the bricks are organized, I just think of collapsing the wall with MassFx. Convert them to rigid bodies and a few collisions.
I haven't tried it yet, but as the bricks are script controlled I just presume I may have problems.

There are no problems with this. These may not be the same bricks. You can "collapse" another set of bricks that is assembled and looks the same.
Another solution is to use the parent dummies for the scripted "falling down" animation, and use the bricks themselves for the physics.

 

0 Likes