Notifications
Clear all

[Closed] please help auto rotate

hi all i need help with something
i got this code somewhere here on the forum , don’t remember where
but i love it , works wonderfully on a rotation script controller

i need to do the same thing only on a single axis to auto turn a wheel
and im failing at converting it to work for my needs
any an all help would be greatly appreciated

here is the code
obj = $ – change this
timeres = 1f – time resolution

fn getrot t =
(
if t<=0f then return quat 0 0 0 1 – t=0 => no rotation
t0 = t-timeres – previous frame time
t1 = t – current time

rot0 = getrot(t0)           -- previous rotation:

p0 = at time t0 obj.position-- previous position
p1 = at time t1 obj.position-- current position
if(p0==p1) then return rot0 -- no distance is traveled

dif = p1-p0                 -- difference in positions
len = Length(dif)           -- distance that's traveled  
vec = dif / len             -- normalized movement vector.

r0 = at time t0 obj.radius  -- previous radius
r1 = at time t1 obj.radius  -- current radius

rotax = cross vec [0, 0, 1] -- rotation axis
angle = 360*len/((r0+r1)*pi)-- rotation amount (in degs) 
rotdif = quat angle rotax   -- rotation from t0 to t1
rot1 = rot0 + rotdif        -- total rotation

)

getrot(currentTime)

15 Replies

what does this script have to do? a better description, a picture, a video might help

hey denis
well this script i posted once paced in a rotation script controller on a sphere
will make the sphere rotate in the direction of the movement , it works well and its no heavy on the system like other ones i found

what i need is a code to rotate a wheel on one axis lets say Z
according to the movement , i found a few that are working well
but are a bit heavy on the system cause they are live and use a few extra helpers to determine
the distance and direction of the wheel in compare to the previous or next frame

i was hoping to get to a solution without any extra helpers like in the code i posted
but instead of rotating in all directions , just on Z
then ill add a bake function if it gets to sluggish to work with in real time

i still don’t understand what you want but here is how to wire a wheel radius, traveling distance, and wheel rotation angle… run this snippet and move the wheel in X direction.

delete objects
wh = cylinder name:"wheel" radius:10 height:2 heightsegs:1 capsegs:1 sides:24 slice:on sliceFrom:355 sliceTo:5 wirecolor:orange rotation:(eulerangles 90 0 0)
c = wh.rotation.controller[2].controller = float_script()
c.addtarget "radius" wh.baseobject[#radius]  
c.addtarget "distance" wh[#transform][#position][1]
c.setexpression "degtorad(180*distance/(pi*radius))" 

it’s pretty simple to make an opposite rig where we specify rotation speed, and get a position at specified time. but it’s for anyone else how want to practice in this kind of things.

let’s continue the fun:

delete objects
 with redraw off
 (
 	wh = cylinder name:"wheel" radius:10 height:2 heightsegs:1 capsegs:1 sides:24 slice:on sliceFrom:355 sliceTo:5 wirecolor:orange pos:[100,-60,0] rotation:(eulerangles 90 0 0)
 	sp = converttosplineshape (circle name:"path" radius:100 wirecolor:green)
 	setknotpoint sp 1 1 [100,0,50]
 	setknotpoint sp 1 3 [-100,0,50]
 	updateshape sp
 	p = wh.position.controller = path path:sp follow:on bank:on bankamount:0.2 relative:on
 	c = wh.rotation.controller[2].controller = float_script()
 	c.addtarget "radius" wh.baseobject[#radius]  
 	c.addtarget "percent" p[#percent]
 	c.addnode "path" sp
 	c.setexpression "degtorad(180*(curveLength path)*(pathToLengthParam path ((mod (percent/100) 1.0))/(pi*radius)))"
 	ok
 )

thanks denis
both examples are cool
here is the problem , and its defiantly because i didn’t explain myself well enough
im dealing with a wheel chair
and the script is for the back , large wheels
so
when i parent the wheel from your example to a master object
change the “distance” variable to the master x position
the wheel will turn on a linear x motion , but if i turn the master in place, nothing happens.

and while the path option works well , it doesn’t really support wheel chair motion
with back and forth motions and pivot turning.

thank you again for taking the time to do this , sorry for the lack of proper explanation

one of the scripts i was playing with was this one by clovis gay:
http://www.scriptspot.com/3ds-max/scripts/auto-wheel

it works well , but has extra helpers and is a bit heavy
i would like to avoid the extra helpers like in the first script i posted

example:

delete objects
testsphere = sphere name:"testsphere" radius:10
testsphere.rotation.controller = rotation_script ()
testsphere.rotation.controller.script ="obj = $       -- change this
timeres = 1f             -- time resolution
-----------------------------------------------------
fn getrot t =
(
    if t<=0f then return quat 0 0 0 1 -- t=0 => no rotation
    t0 = t-timeres        -- previous frame time 
    t1 = t            -- current time 

    rot0 = getrot(t0)           -- previous rotation:

    p0 = at time t0 obj.position-- previous position
    p1 = at time t1 obj.position-- current position
    if(p0==p1) then return rot0 -- no distance is traveled

    dif = p1-p0                 -- difference in positions
    len = Length(dif)           -- distance that's traveled  
    vec = dif / len             -- normalized movement vector.

    r0 = at time t0 obj.radius  -- previous radius
    r1 = at time t1 obj.radius  -- current radius

    rotax = cross vec [0, 0, 1] -- rotation axis
    angle = 360*len/((r0+r1)*pi)-- rotation amount (in degs) 
    rotdif = quat angle rotax   -- rotation from t0 to t1
    rot1 = rot0 + rotdif        -- total rotation
)

getrot(currentTime)"--set the expression
select $testsphere
with animate on 
(
move $ [-26.0613,30.8188,0]
sliderTime = 22f
move $ [70.3739,-44.9102,0]
sliderTime = 46f
move $ [-64.9319,-31.4269,0]
sliderTime = 73f
move $ [-12.5718,68.2618,0]
sliderTime = 0f
)

so basically i want to get to a similar functionality like in clovis gay’s wheel script
but without all the extra helpers and “arrows” and stuff like that
and also the sphere rotate script appears to preform faster on animation

thanks again

enjoy this Wheel Chair

with redraw off
(
	delete objects

	rotAttr = attributes "rotAttr"
	(
		parameters main 
		(
			timeAngle type:#point3 animatable:off
		)
	)

	fn makeWheel name: radius: pos: wirecolor: = 
	(
		w = cylinder name:name sides:24 segments:1 radius:radius height:3 slice:on sliceFrom:350 sliceTo:10 pos:pos wirecolor:wirecolor
		w.objectOffsetRot = eulerangles 0 90 0
		CenterObject w
		w
	)
		
	body = 
	(
		b =  (box name:"Wheel_chair" width:20 length:25 height:25 pos:[0,-5,17] wirecolor:blue) - (c = box width:25 length:30 height:25 pos:[0,0,25])
		delete c
		b
	)

	in body
	(
		w1 = makeWheel name:"LF_wheel" radius:5 pos:[-10,10,5] wirecolor:red
		w2 = makeWheel name:"RF_wheel" radius:5 pos:[10,10,5] wirecolor:red
		w3 = makeWheel name:"LR_wheel" radius:15 pos:[-13,-10,15] wirecolor:orange
		w4 = makeWheel name:"RR_wheel" radius:15 pos:[13,-10,15] wirecolor:orange
	)	
	mapped fn makeScript node body ss =
	(
		c = node[#transform][#rotation][1].controller = float_script()
		custattributes.add c rotAttr
		c.addconstant "radius" node.radius
		c.addnode "body" body
		c.addtarget "p0" body[#transform][#position] offset:0
		c.addtarget "p1" body[#transform][#position] offset:1
		c.setexpression ss
		c
	)
	
	ss  = "sign = if dot (p1 - p0) body.transform[2] > 0 then -1 else 1
" 
	ss += "a = this.timeAngle[2] + degtorad(180*(distance [p0.x,p0.y] [p1.x,p1.y])*(f-this.timeAngle[1])*sign/(pi*radius))
"
	ss += "this.timeAngle = [f,a,0]
"
	ss += "a
"

	makeScript body.children body ss
	
	in coordsys local with animate on
	(
		at time 30 move body [0,60,0]
		at time 30 rotate body (eulerangles 0 0 0)
		at time 40 rotate body (eulerangles 0 0 40)
		at time 40 move body [5,15,0]
		at time 70 move body [0,80,0]
		at time 100 move body [0,-100,0]
	)
	
	select body
) 

i left a chance to add ‘auto follow’ for front wheels to any enthusiast.

1 Reply
(@gazybara)
Joined: 11 months ago

Posts: 0

Very interesting example

nice chair
but when the chair rotates in place the wheels still don’t rotate the way they should

with redraw off
(
	delete objects

	rotAttr = attributes "rotAttr"
	(
		parameters main 
		(
			timeAngle type:#point3 animatable:off
		)
	)

	fn makeWheel name: radius: pos: wirecolor: = 
	(
		w = cylinder name:name sides:24 segments:1 radius:radius height:3 slice:on sliceFrom:350 sliceTo:10 pos:pos wirecolor:wirecolor
		w.objectOffsetRot = eulerangles 0 90 0
		CenterObject w
		w
	)
		
	body = 
	(
		b =  (box name:"Wheel_chair" width:20 length:25 height:25 pos:[0,-5,17] wirecolor:blue) - (c = box width:25 length:30 height:25 pos:[0,0,25])
		delete c
		b
	)

	in body
	(
		w1 = makeWheel name:"LF_wheel" radius:5 pos:[-10,10,5] wirecolor:red
		w2 = makeWheel name:"RF_wheel" radius:5 pos:[10,10,5] wirecolor:red
		w3 = makeWheel name:"LR_wheel" radius:15 pos:[-13,-10,15] wirecolor:orange
		w4 = makeWheel name:"RR_wheel" radius:15 pos:[13,-10,15] wirecolor:orange
	)	
	mapped fn makeScript node body ss =
	(
		c = node[#transform][#rotation][1].controller = float_script()
		custattributes.add c rotAttr
		c.addconstant "radius" node.radius
		c.addnode "body" body
		c.addtarget "p0" body[#transform][#position] offset:0
		c.addtarget "p1" body[#transform][#position] offset:1
		c.setexpression ss
		c
	)
	
	ss  = "sign = if dot (p1 - p0) body.transform[2] > 0 then -1 else 1
" 
	ss += "a = this.timeAngle[2] + degtorad(180*(distance [p0.x,p0.y] [p1.x,p1.y])*(f-this.timeAngle[1])*sign/(pi*radius))
"
	ss += "this.timeAngle = [f,a,0]
"
	ss += "a
"

	makeScript body.children body ss
	select $Wheel_chair
with animate on
	(
		rotate $ (angleaxis 158.655 [0,0,1])
		sliderTime = 60f
		rotate $ (angleaxis -169.208 [0,0,1])

	)
	
	select body
) 

when turning left
the left wheel should rotate back
and the right wheel should rotate forward

do you want me to do your laundry too?

Page 1 / 2