proc float raySphereIntersect(string $objName,float $positionX,float $positionZ,float $directionX,float $directionZ) { float $sphereCenterX, $sphereCenterZ, $sphereRadius; float $A, $B, $C, $D, $tp, $tm; float $avoidDistance = 16.0; float $minDistance = $avoidDistance + 1.0; global string $sphereName; //print("object location = " + $positionX + "," + $positionZ + " direction = " + $directionX + "," + $directionZ + "\n"); string $temp; string $objects[] = `ls -type "transform" "obstacle*"`; //print($objects); for($i=0;$i= 0.0) { $tp = ((-1.0 * $B) + sqrt($D)) / (2.0 * $A); $tm = ((-1.0 * $B) - sqrt($D)) / (2.0 * $A); float $t = -1.0; if($tp > 0.0 && $tm > 0.0) { if($tp < $tm) { $t = $tp; } else { $t = $tm; } } else { if($tp > 0.0) { $t = $tp; } else { $t = $tm; } } if( $t >= 0.0 && $t < $avoidDistance ) { if($t < $minDistance) { $minDistance = $t; $sphereName = $objects[$i]; } } } } } return $minDistance; } global proc float[] obstacleAvoidance(string $objName) { float $maxDistance = 16.0; float $objectSize = 1.5; float $weightFactor = 10.0; float $positionX, $positionZ, $directionX, $directionZ, $rotateY; float $maxSpeed = 0.125; float $minSpeed = 0.05; float $repulseForce = 0.01; global string $sphereName; float $directionXAccum, $directionZAccum, $velocityAccum; $directionXAccum = 0.0; $directionZAccum = 0.0; $velocityAccum = 0.0; int $influence = 0; $positionX = `getAttr ($objName + ".tx")`; $positionZ = `getAttr ($objName + ".tz")`; $rotateY = `getAttr ($objName + ".rotateY")`; $directionX = sind($rotateY); $directionZ = cosd($rotateY); float $velocity; $velocity = `getAttr ($objName + ".Velocity")`; float $perpDir[3] = crossProduct({$directionX,0,$directionZ},{0,1,0},0,1); $positionX1 = $positionX + $perpDir[0] * $objectSize; $positionZ1 = $positionZ + $perpDir[2] * $objectSize; $positionX2 = $positionX + $perpDir[0] * -1.0 * $objectSize; $positionZ2 = $positionZ + $perpDir[2] * -1.0 * $objectSize; float $distance1,$distance2,$distance; string $sphereName1,$sphereName2; $distance1 = raySphereIntersect($objName,$positionX1,$positionZ1,$directionX,$directionZ); $sphereName1 = $sphereName; $distance2 = raySphereIntersect($objName,$positionX2,$positionZ2,$directionX,$directionZ); $sphereName2 = $sphereName; $distance3 = raySphereIntersect($objName,$positionX,$positionZ,$directionX,$directionZ); $sphereName3 = $sphereName; float $sphereRadius, $sphereCenterX, $sphereCenterZ; // if both distances are over the maximum distance, then there is no collision to worry about. if($distance1 < $maxDistance || $distance2 < $maxDistance || $distance3 < $maxDistance) { string $temp; if($distance1 < $distance2) { $temp = $sphereName1; $distance = $distance1; } else { $temp = $sphereName2; $distance = $distance2; } if($distance3 < $distance) { $temp = $sphereName3; $distance = $distance3; } if(abs($distance1 - $distance2) < 0.5) { $sphereCenterX1 = `getAttr ($sphereName1 + ".tx")`; $sphereCenterZ1 = `getAttr ($sphereName1 + ".tz")`; $sphereRadius1 = `getAttr ($sphereName1 + ".sx")`; $sphereCenterX2 = `getAttr ($sphereName2 + ".tx")`; $sphereCenterZ2 = `getAttr ($sphereName2 + ".tz")`; $sphereRadius2 = `getAttr ($sphereName2 + ".sx")`; $sphereDistance = calcDistance($sphereCenterX1,$sphereCenterX2,$sphereCenterZ1,$sphereCenterZ2); $sphereRadius = ($sphereDistance + $sphereRadius1 + $sphereRadius2) / 2.0; $sphereCenterX = ($sphereCenterX1 + $sphereCenterX2) / 2.0; $sphereCenterZ = ($sphereCenterZ1 + $sphereCenterZ2) / 2.0; } else { $sphereCenterX = `getAttr ($temp + ".tx")`; $sphereCenterZ = `getAttr ($temp + ".tz")`; $sphereRadius = `getAttr ($temp + ".sx")`; } float $forwardDistance = $distance; // distance at this point is the absolute distance from the object to the sphere. $distance = calcDistance($positionX,$positionZ,$sphereCenterX,$sphereCenterZ); $distance -= $sphereRadius; float $dirToSphereX = $sphereCenterX - $positionX; float $dirToSphereZ = $sphereCenterZ - $positionZ; float $crossProduct[3]; $crossProduct = crossProduct({$directionX,0,$directionZ},{$dirToSphereX,0,$dirToSphereZ},0,1); float $perpAway[3]; $perpAway = crossProduct({$directionX,0,$directionZ},$crossProduct,0,1); float $pointAwayX,$pointAwayZ; if($distance >= $objectSize) { $distance = $objectSize; } $pointAwayX = $sphereCenterX + ($perpAway[0] * ($sphereRadius + $distance * 2.0)); $pointAwayZ = $sphereCenterZ + ($perpAway[2] * ($sphereRadius + $distance * 2.0)); float $finalDirectionX,$finalDirectionZ; $finalDirectionX = $pointAwayX - $positionX; $finalDirectionZ = $pointAwayZ - $positionZ; float $weight = (1.0 / pow($distance,2.0)); $weight /= $weightFactor; //float $weight = (1.0 / $distance); //float $weight = 0.1; $influence++; if($forwardDistance < ($objectSize * 2.0)) { $velocityAccum += (0.0 - $velocity) * $weight * 100.0; } else { $velocityAccum += ($maxSpeed - $velocity) * $weight * 10.0; } if($velocityAccum < 0.0) { $velocityAccum = 0.0; } if($velocityAccum > $maxSpeed) { $velocityAccum = $maxSpeed; } if($distance >= 0.0) { $directionXAccum += $finalDirectionX * $weight; $directionZAccum += $finalDirectionZ * $weight; float $mag = sqrt(($directionX * $directionX) + ($directionZ * $directionZ)); $directionXAccum /= $mag; $directionZAccum /= $mag; float $newY = atan2d($directionX,$directionZ); } else // you have penetrated the bounding sphere, so a repulsive force is applied. { // repulse away from the center of the sphere float $repulseX, $repulseZ; $repulseX *= -1.0 * $dirToSphereX * $repulseForce * ($sphereRadius - $distance) * ($sphereRadius - $distance); $repulseZ *= -1.0 * $dirToSphereX * $repulseForce * ($sphereRadius - $distance) * ($sphereRadius - $distance); move -r $repulseX 0 $repulseZ ($objName); $velocity = 0; } } float $returnValue[3]; $mag = sqrt(($directionXAccum * $directionXAccum) + ($directionZAccum * $directionZAccum)); if($mag == 0) { $directionXAccum = 0; $directionZAccum = 0; } else { $directionXAccum /= $mag; $directionZAccum /= $mag; } $returnValue[0] = $directionXAccum; $returnValue[1] = $directionZAccum; if($influence == 0) { $velocityAccum = -1.0; } $returnValue[2] = $velocityAccum; return ($returnValue); }