I've been trying to something working but I think I've reached the LIMITS of my current abilities. Ha ha.
Basically:
At a weight of zero, the target has no effect on the object, and the object can be rotated freely within its constraints. At a weight of 100, the object cannot be rotated manually, and follows the target (again, within the limits that have been set).
Here's what I've put together so far. To make it simpler to test, I've stuck a custom attribute on the target object to adjust the weight of the lookAt effect.
It gets generally the effect I am trying to accomplish, but the objects in the scene can still end up rotating beyond the desired limits. (Also, I tend to get this guy while testing out the scene: http://i.gyazo.com/350ae6bdc912780dc0421eaa9b1a7613.png
I would be really happy if someone could make this work! At the moment I can't afford a bounty, but a donation at some point in the future would not be out of the question.
----
EDIT:
Okay, I don't know why I was trying to put the script controller after the Euler XYZ controller. It's much simpler to do it this way. I've also removed the custom attribute from the target object as the "weighted" part should be relatively easy once I get the other part working. So, the test case to look at:
delete objects
s = geoSphere name:"Target" radius:10
parentPoint = point pos:[50,50,0]
lookObjects = for i = 1 to 5 collect (
rot = 15
pyramid width:10 depth:10 pos:[random 0 100, random 0 100, random 0 100] rotation:(eulerAngles (random rot -rot) (random rot -rot) (random rot -rot))
)
(
lookTarget = s
for i = 1 to lookObjects.count do (
o = lookObjects[i]
o.objectOffsetRot = eulerAngles 90 0 90
o.parent = parentPoint
orc = o.rotation.controller = rotation_List()
orc.setName 1 "Initial Rotation"
p = point axisTripod:on box:on cross:off parent:o.parent transform:o.transform
prc = p.rotation.controller = rotation_List()
prc[2].controller = lookAt_Constraint lookAt_Vector_Length:0 --upNode_World:false --relative:true
prc[2].controller.appendTarget lookTarget 100
prc.setActive 2
prc.weight = #(100, 50 + (i * 10))
orc = lookObjects[i].rotation.controller
orc[2].controller = orientation_Constraint()
orc[2].controller.appendTarget p 50
orc[3].controller = rotation_Script()
orc[3].controller.addObject "lookRot" orc[2].controller
ss = stringStream ""
format "a = lookRot.value as eulerAngles\n" to:ss
format "eulerAngles (amin (amax -15 a.x) 15) (amin (amax -30 a.y) 30) (amin (amax -45 a.z) 45)" to:ss
orc[3].controller.script = ss
orc[4].controller = euler_XYZ()
orc.weight = #(0, 0, 100, 100)
rotLimits = #(15, 30, 45)
ax = #("x", "y", "z")
for j = 1 to 3 do (
o[3][2][4][j].controller = float_Limit()
uls = o[3][2][4][j][2][1].controller = float_Script()
uls.addObject "scriptRot" orc[3]
uls.script = "degToRad (" + rotLimits[j] as string + " - (scriptRot.value as eulerAngles)." + ax[j] + ")"
lls = o[3][2][4][j][2][2].controller = float_Script()
lls.addObject "scriptRot" orc[3]
lls.script = "degToRad (-" + rotLimits[j] as string + " - (scriptRot.value as eulerAngles)." + ax[j] + ")"
)
orc.setActive 4
)
)
--------
OLD VERSION:
global lookControls = attributes lookControls attribID:#(0x58ae9e8e, 0x5b3c35a0) (
parameters params rollout:RO_Look (
maxObjectTab type:#maxObjectTab tabSizeVariable:on
str type:#float ui:sld_Str default:50
)
fn adjustLookWeights = (
c = this.maxObjectTab.count
for i = 1 to c do (
n = this.maxObjectTab[i].node
if classof n == point then (
val = (i as float / c) * this.RO_Look.sld_Str.value
n.rotation.controller.weight[2] = val
)
else
n.rotation.controller.weight[2] = 100 - this.RO_Look.sld_Str.value
)
)
rollout RO_Look "Look Controls" (
slider sld_Str "" pos:[18, 30]
on sld_Str changed val do adjustLookWeights()
)
)
delete objects
s = geoSphere name:"Target" radius:10
parentPoint = point pos:[50,50,0]
lookObjects = for i = 1 to 5 collect (
rot = 15
pyramid width:10 depth:10 pos:[random 0 100, random 0 100, random 0 100] rotation:(eulerAngles (random rot -rot) (random rot -rot) (random rot -rot))
)
(
lookTarget = s
custAttributes.add lookTarget lookControls
for i = 1 to lookObjects.count do (
o = lookObjects[i]
o.objectOffsetRot = eulerAngles 90 0 90
o.parent = parentPoint
orc = o.rotation.controller = rotation_List()
orc[2].controller = euler_XYZ()
for j = 1 to 3 do (
o[3][2][2][j].controller = float_Limit()
o[3][2][2][j][2][1].value = degToRad 30
o[3][2][2][j][2][2].value = degToRad -30
)
orc.setName 1 "Initial Rotation"
orc.setActive 2
p = point parent:o.parent transform:o.transform axisTripod:true
prc = p.rotation.controller = rotation_List()
prc[2].controller = lookAt_Constraint lookAt_Vector_Length:0 --upNode_World:false --relative:true
prc[2].controller.appendTarget lookTarget 50
prc.setActive 2
prc.weight = #(100, 50 + (i * 10))
orc = lookObjects[i].rotation.controller
orc[3].controller = orientation_Constraint()
orc[3].controller.appendTarget p 50
orc[4].controller = rotation_Script()
orc[4].controller.addObject "parent" o.parent
orc[4].controller.addObject "initRot" orc[1].controller
orc[4].controller.addObject "eulerRot" orc[2].controller
orc[4].controller.addObject "lookRot" orc[3].controller
orc[4].controller.addConstant "weights" orc[6]
ss = stringStream ""
format "a = (lookRot.value * inverse parent.transform.rotation) as eulerAngles\n" to:ss
format "w2 = weights[2].value / 100\n" to:ss
format "xL = radToDeg eulerRot[1].lower_Limit - (eulerRot[1].value * w2)\n" to:ss
format "xU = radToDeg eulerRot[1].upper_Limit - (eulerRot[1].value * w2)\n" to:ss
format "yL = radToDeg eulerRot[2].lower_Limit - (eulerRot[2].value * w2)\n" to:ss
format "yU = radToDeg eulerRot[2].upper_Limit - (eulerRot[2].value * w2)\n" to:ss
format "zL = radToDeg eulerRot[3].lower_Limit - (eulerRot[3].value * w2)\n" to:ss
format "zU = radToDeg eulerRot[3].upper_Limit - (eulerRot[3].value * w2)\n" to:ss
format "eulerAngles ((amin (amax xL a.x) xU) - initRot[1].value) ((amin (amax yL a.y) yU) - initRot[1].value) ((amin (amax zL a.z) zU) - initRot[1].value)" to:ss
ss = ss as string
orc[4].controller.script = ss
orc.weight = #(100, 50, 0, 100)
append lookTarget.maxObjectTab (nodeTransformMonitor node:o forwardTransformChangeMsgs:false)
append lookTarget.maxObjectTab (nodeTransformMonitor node:p forwardTransformChangeMsgs:false)
)
)
barigazy · 2014-08-06