// Duplicate surface curve
proc string[] dup_surf_curves(string $uv, float $from, float $to, int $step, int $dup_first_curve, string $obj_name)
{
if ($uv == "u" || $uv == "v")
{
string $curve_name[];
int $flag = 0;
int $count = 0;
if ($dup_first_curve == 0) $flag = 1;
for ($i = $flag; $i <= $step; $i++)
{
string $dup_curve[] = `duplicateCurve -ch 1 -rn 0 -local 0 ($obj_name + "." + $uv + "[" + ($from + ($to - $from)/$step*$i) + "]")` ;
$curve_name[$count] = $dup_curve[0];
$count++;
}
return $curve_name;
}
else error("Invailed valuable!: select u or v.");
}
// This proc returns distance of two objects
proc float distance(string $obj1, string $obj2)
{
float $obj1_center[] = `xform -q -sp $obj1`;
float $obj2_center[] = `xform -q -sp $obj2`;
float $dif_x = $obj1_center[0] - $obj2_center[0];
float $dif_y = $obj1_center[1] - $obj2_center[1];
float $dif_z = $obj1_center[2] - $obj2_center[2];
float $dist = sqrt($dif_x*$dif_x + $dif_y*$dif_y + $dif_z*$dif_z);
return $dist;
}
// Tweak curve scale by time
proc tweak_curve_scale(string $obj_name, float $curve_scale, float $dist)
{
float $a = 10.0;
float $b = 2.0;
float $wich_of_agnesi = ($b*$b*$b/(($a*$dist)*($a*$dist) + $b*$b))/$b;
float $scale_value = 1 - (1 - $curve_scale)*$wich_of_agnesi;
scale -a $scale_value $scale_value $scale_value $obj_name;
}
global proc string[] cell_division(string $cell_name[], int $curve_step, float $div_time)
{
// Duplicate curves on two spheres
string $cell_1_curve[] = dup_surf_curves("u", 0.0, 0.5, $curve_step, 1, $cell_name[0]);
string $cell_2_curve[] = dup_surf_curves("u", 0.5, 1.0, $curve_step, 1, $cell_name[1]);
// Exitract boundary curve from two cell spheres
string $boundary_curve[] = `intersect -ch 0 -fs 1 -cos 0 -tol 0.01 $cell_name[0] $cell_name[1]`;
xform -cp $boundary_curve[0];
// Get a radius of the boundary curve
float $boundary_curve_bb[] = `xform -q -bb $boundary_curve[0]`;
float $max_y = $boundary_curve_bb[4];
// Get radiuses of two cells
float $cell_1_radius = `sphere -q -r $cell_name[0]`;
float $cell_1_scale = `getAttr ($cell_name[0] + ".sy")`;
$cell_1_radius *= $cell_1_scale;
float $cell_2_radius = `sphere -q -r $cell_name[1]`;
float $cell_2_scale = `getAttr ($cell_name[1] + ".sy")`;
$cell_2_radius *= $cell_2_scale;
// Find out the UV range where surface curves need to be duplicated
float $boundary_uv_range_1 = ((acosd(($max_y/$cell_1_radius))) / 90.0) * 0.5;
float $boundary_uv_range_2 = ((acosd(($max_y/$cell_2_radius))) / 90.0) * 0.5;
float $general_curve_space = 0.5/$curve_step;
// Duplicate curves around the boundary of two cells
int $boundary_uv_step_1 = $boundary_uv_range_1 / $general_curve_space;
int $boundary_uv_step_2 = $boundary_uv_range_2 / $general_curve_space;
string $cell_1_b_curve[];
string $cell_2_b_curve[];
if($boundary_uv_step_1 != 0)
$cell_1_b_curve = dup_surf_curves("u", 0.5, (0.5 + ($boundary_uv_range_1*(1.0 - 1.0/$boundary_uv_step_1))), ($boundary_uv_step_1 - 1), 0, $cell_name[0]);
if($boundary_uv_step_2 != 0)
$cell_2_b_curve = dup_surf_curves("u", (0.5 - $boundary_uv_range_2), (0.5 - ($boundary_uv_range_2/$boundary_uv_step_2)), ($boundary_uv_step_2 - 1), 0, $cell_name[1]);
xform -cp $cell_1_curve $cell_2_curve $cell_1_b_curve $cell_2_b_curve;
// Tweak curve scale by time
float $current_time = `currentTime -q`;
float $curve_scale;
if($current_time <= $div_time)
$curve_scale = 1 - `pow ($current_time/$div_time) 2`;
else $curve_scale = 0.0;
// Put all curve names into one array
string $curves[];
appendStringArray($curves, $cell_1_curve, `size($cell_1_curve)`);
appendStringArray($curves, $cell_1_b_curve, `size($cell_1_b_curve)`);
appendStringArray($curves, $boundary_curve, 1);
appendStringArray($curves, $cell_2_b_curve, `size($cell_2_b_curve)`);
appendStringArray($curves, $cell_2_curve, `size($cell_2_curve)`);
// Tweak all curves' scale
string $scaled_curve;
for($scaled_curve in $curves)
{
float $dist = distance($boundary_curve[0], $scaled_curve);
tweak_curve_scale($scaled_curve, $curve_scale, $dist);
}
string $cell[];
if ($curve_scale > 0)
{
string $cell_temp[] = `loft $curves`;
$cell[0] = $cell_temp[0];
delete $curves;
}
else
{
string $cell_1_last_curve[];
string $cell_2_first_curve[];
// Duplicate last curve of cell 1 to be used to close loft surface
if((size($cell_1_b_curve)) != 0)
$cell_1_last_curve = `duplicate -rr $cell_1_b_curve[(size($cell_1_b_curve) - 1)]`;
else
$cell_1_last_curve = `duplicate -rr $cell_1_curve[(size($cell_1_curve) - 1)]`;
scale -a 0 0 0 $cell_1_last_curve;
move -r 0.25 0 0 $cell_1_last_curve;
// Duplicate fist curve of cell 2 to be used to close loft surface
if((size($cell_2_b_curve)) != 0)
$cell_2_first_curve = `duplicate -rr $cell_2_b_curve[0]`;
else
$cell_2_first_curve = `duplicate -rr $cell_2_curve[0]`;
scale -a 0 0 0 $cell_2_first_curve;
move -r -0.25 0 0 $cell_2_first_curve;
// Loft cell 1 surface
string $cell_1[];
appendStringArray($cell_1, $cell_1_curve, `size($cell_1_curve)`);
appendStringArray($cell_1, $cell_1_b_curve, `size($cell_1_b_curve)`);
appendStringArray($cell_1, $cell_1_last_curve, 1);
string $cell_temp[] = `loft $cell_1`;
$cell[0] = $cell_temp[0];
// Loft cell 2 surface
string $cell_2[];
appendStringArray($cell_2, $cell_2_first_curve, 1);
appendStringArray($cell_2, $cell_2_b_curve, `size($cell_2_b_curve)`);
appendStringArray($cell_2, $cell_2_curve, `size($cell_2_curve)`);
$cell_temp = `loft $cell_2`;
$cell[1] = $cell_temp[0];
delete $cell_1;
delete $cell_2;
delete $boundary_curve[0];
}
return $cell;
}
global proc cell_div_seq()
{
int $end_frame = 120;
int $frame_count = 1;
int $curve_step = 8;
float $div_time = 60.0;
// Keep the names of cell spheres
string $cell_name[] = `ls -sl`;
// To make each UV span 0 to 1
rebuildSurface -ch 1 -rpo 1 -rt 0 -end 1 -kr 0 -kcp 0 -kc 0 -su 8 -du 3 -sv 8 -dv 3 -tol 0.01 -fr 0 -dir 2 $cell_name[0];
rebuildSurface -ch 1 -rpo 1 -rt 0 -end 1 -kr 0 -kcp 0 -kc 0 -su 8 -du 3 -sv 8 -dv 3 -tol 0.01 -fr 0 -dir 2 $cell_name[1];
for($frame_count = 1; $frame_count <= $end_frame; $frame_count++)
{
currentTime $frame_count;
string $new_cells[] = cell_division($cell_name, $curve_step, $div_time);
string $temp;
for($temp in $new_cells)
{
setAttr ($temp + ".v") 1;
setKeyframe ($temp + ".v");
}
currentTime ($frame_count - 1);
for($temp in $new_cells)
{
setAttr ($temp + ".v") 0;
setKeyframe ($temp + ".v");
}
currentTime ($frame_count + 1);
for($temp in $new_cells)
{
setAttr ($temp + ".v") 0;
setKeyframe ($temp + ".v");
}
}
select -r $cell_name[0] ;
select -tgl $cell_name[1] ;
HideSelectedObjects;
currentTime 1 ;
}
cell_div_seq;