[Closed] Scripting a Planet and Star
Hey all, I’ve recently been trying to build a planet and star system in max as a way of improving my knowledge of maxscript, and having a bit of fun.
I managed to model 3 objects (a star, planet and moon) which orbit around their correct parent, but when i tried to change the speed at which each rotated to add more realism to the scene, they stopped rotating.
Here’s what i have so far
if (classof $ != ObjectSet) then (
messagebox ("need at least 2 selected objects")
) else ( --we have at least 2 objects
for obj_id in 2 to $.count do (
$[obj_id].parent = $[obj_id-1]
)
ang=360.0 / (animationRange.end - animationRange.start)
animate on (
$Sphere001 do (
for keytime in animationRange.start to animationRange.end do (
at time keytime (
rotate obj (angleAxis ang[0,0,1])
)
)
)
$Sphere002 do (
for keytime in animationRange.start to animationRange.end do (
at time keytime (
rotate obj (angleAxis ang[0,0,1])
)
)
)
$Sphere003 do (
for keytime in animationRange.start to animationRange.end do (
at time keytime (
rotate obj (angleAxis ang[0,0,1])
)
)
)
)
)
what i tried to do was to triplicate the rotation code, and edit it so that it would effect each of the spheres separately, so i could make the rotations more akin to that of the sun, earth and moon.
…But it didn’t work =/
Could anybody give me a kick in the right direction so i can (hopefully) go on to model a full solar system model
cheers guys
-Designasaur
Sounded like fun so I whipped this up. You can change the values around to suit your needs. Someone can surely make this way better but I got tired and must now sleep.
fn orbitit n pl p therad =
(
local c=circle radius:(therad) pos:p.pos steps:16 --the orbit
local par = point name:("p_" + pl.name) size:3 --the planet/moons parent
local pc = path_constraint() --the path constraint controller
pc.follow = true --child orientation will follow path normal
par.position.controller = pc
pc.path = c --assign the path
pc.percent = random 1 100 --random position around the orbit
pl.pos = par.pos --move the planet to the parent
pl.parent = par --assign the planet parent
return #(c,par) --return the orbit and the parent
)
fn moonit nm ther o =
(
local ch = Sphere radius:ther --moon
local thep = orbitit nm ch o (o.radius+5) --do the orbit thing, return the orbit and parent
ch.parent = thep[2] --assign the point as the planets parent
thep[1].parent = o --assign the planet as the orbit's parent
)
(
local thesun = $sphere001 --sun object
local objs = for i = 1 to 5 collect s = sphere radius:(random 5 11) --create planets
for o = 1 to objs.count do
(
local rad= thesun.radius*5 --the orbit size
local mrad = random 1 5 --the moon radius/orbit
local nmoons = random 1 5 --number of moons
orbitit o objs[o] thesun ((rad*o)+mrad) --do the orbit thing
for n = 1 to nmoons do moonit n (mrad*.1) objs[o] --make moons
rot = random 1 60 --tilt
with animate on at time (animationrange.start) objs[o].rotation.controller[3].value = objs[o].rotation.controller[3].value --animate at first frame
with animate on at time (animationrange.end) in coordsys local rotate objs[o] 3 [0,0,(random 720 1540)] --animate at last frame
)
)
-
Reply to original poster with functional script written specifically for poster
-
Expect nothing in return
-
Get nothing in return
…well played karma, well played
em3-
I didnt post it but Ill give ya a big thank you. Its great when you get to see other take on solving a problem. So, you effort is certainly appreciated.
-Michael
haha thanks Michael! It was fun to try. Though I make a conscious effort not to do it now, I have not replied to a few posts I initiated in my day. I thought karma deserved a little recognition.
here is how i would do it. CA + Transform Script…
OrbitAttribute = attributes OrbitAttribute attribid:#(0x00001967,0x12121200) version:1
(
fn getNode =
(
owner = custattributes.getowner this
refs.dependentnodes owner firstonly:on
)
parameters params rollout:params
(
target type:#node ui:ui_target
orbit_radius1 type:#float default:100 ui:ui_orbit_radius1
orbit_radius2 type:#float default:50 ui:ui_orbit_radius2
orbit_speed type:#float default:10 ui:ui_orbit_speed
orbit_yaw type:#float default:0 ui:ui_orbit_yaw
orbit_pinch type:#float default:0 ui:ui_orbit_pinch
orbit_roll type:#float default:0 ui:ui_orbit_roll
on target set val do
(
if isvalidnode val and isvalidnode (node = getNode()) do
(
c = node.transform.controller
if c.VariableExists "target" then c.setNode "target" val else c.addNode "target" val
)
notifydependents this partid:#tm
)
on orbit_radius1 set val do notifydependents this partid:#tm
on orbit_radius2 set val do notifydependents this partid:#tm
on orbit_speed set val do notifydependents this partid:#tm
on orbit_yaw set val do notifydependents this partid:#tm
on orbit_pinch set val do notifydependents this partid:#tm
on orbit_roll set val do notifydependents this partid:#tm
)
rollout params "Parameters" category:1
(
group "Target: "
(
pickbutton ui_target "None" autoDisplay:on width:144 align:#left offset:[-4,0]
)
group "Orbit: "
(
spinner ui_orbit_radius1 "Radius 1: " fieldwidth:54 range:[0,1e9,100] align:#right offset:[4,0]
spinner ui_orbit_radius2 "Radius 2: " fieldwidth:54 range:[0,1e9,50] align:#right offset:[4,-2]
spinner ui_orbit_speed "Speed: " fieldwidth:54 range:[0,1e9,10] align:#right offset:[4,4]
spinner ui_orbit_yaw "Yaw: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,4]
spinner ui_orbit_pinch "Pinch: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,-2]
spinner ui_orbit_roll "Roll: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,-2]
)
)
)
delete objects
t = sphere name:"target" pos:[0,0,0] radius:20 wirecolor:yellow
p = sphere name:"planet" pos:[100,0,0] radius:10 wirecolor:green
custattributes.add p OrbitAttribute baseobject:on
(
c = p.transform.controller = Transform_Script()
c.addtarget "params" p.baseobject.OrbitAttribute
p.baseobject.OrbitAttribute.target = t
ss = ""
ss += "ptm = if (this.VariableExists \"target\") and isvalidnode (target = this.getnode \"target\") then target.transform else (Matrix3 1)
"
ss += "tm = transmatrix [params.orbit_radius1*(cos (f*params.orbit_speed)), params.orbit_radius2*(sin (f*params.orbit_speed)), 0]
"
ss += "rotate tm (rotateYPRMatrix params.orbit_yaw params.orbit_pinch params.orbit_roll)
"
ss += "tm *= ptm
"
c.setexpression ss
--format ">> %
" (p.baseobject.OrbitAttribute.getNode())
)
setTrajectoryOn p on
select p
all parameters are animatable as you see…
using this snippet you can Add any other astronomical parameters, multiple targets, or/and real physics formulas as well…
enjoy!
The “Speed” setting minimum needs to be set to 3.6 as the orbit seems to be linked to the degrees of rotation. If any of that makes sense.
My only problem now is understanding any of the math in this script lol
lol I meant that the 3.6 is the same as a rotation of 360 degrees if you set the speed to 3.6. You don’t get a full rotation of the planet around the sun it will only travel 150 degrees if set to 1.5 for example. So it will travel part of the distance around the sun and then jump back to the start of the orbit.
So the speed is tied to the distance around the sun.
No you’re not missing anything, my mistake sorry. We’ll blame it on my Oxycontin for my muscle strain shall we
new, better, and more correct:
OrbitAttribute = attributes OrbitAttribute attribid:#(0x00001967,0x12121200) version:1
(
fn getNode =
(
owner = custattributes.getowner this
refs.dependentnodes owner firstonly:on
)
fn update = notifydependents this partid:#tm
parameters params rollout:params
(
target type:#node ui:ui_target
orbit_radius1 type:#float default:100 ui:ui_orbit_radius1
orbit_radius2 type:#float default:50 ui:ui_orbit_radius2
orbit_speed type:#float default:10 ui:ui_orbit_speed
orbit_yaw type:#float default:0 ui:ui_orbit_yaw
orbit_pinch type:#float default:0 ui:ui_orbit_pinch
orbit_roll type:#float default:0 ui:ui_orbit_roll
on target set val do
(
if isvalidnode val and isvalidnode (node = getNode()) do
(
c = node.transform.controller
if c.VariableExists "target" then c.setNode "target" val else c.addNode "target" val
)
update()
)
on orbit_radius1 set val do update()
on orbit_radius2 set val do update()
on orbit_speed set val do update()
on orbit_yaw set val do update()
on orbit_pinch set val do update()
on orbit_roll set val do update()
planet_velocity type:#float default:20 ui:ui_planet_velocity
planet_tiltX type:#float default:0 ui:ui_planet_tiltX
planet_tiltY type:#float default:0 ui:ui_planet_tiltY
on planet_velocity set val do update()
on planet_tiltX set val do update()
on planet_tiltY set val do update()
)
rollout params "Parameters" category:1
(
group "Target: "
(
pickbutton ui_target "None" autoDisplay:on width:144 align:#left offset:[-4,0]
)
group "Orbit: "
(
spinner ui_orbit_radius1 "Radius 1: " fieldwidth:54 range:[0,1e9,100] align:#right offset:[4,0]
spinner ui_orbit_radius2 "Radius 2: " fieldwidth:54 range:[0,1e9,50] align:#right offset:[4,-2]
spinner ui_orbit_speed "Angular Speed: " fieldwidth:54 range:[-1e9,1e9,10] align:#right offset:[4,4]
spinner ui_orbit_yaw "Yaw: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,4]
spinner ui_orbit_pinch "Pinch: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,-2]
spinner ui_orbit_roll "Roll: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,-2]
)
group "Planet: "
(
spinner ui_planet_velocity "Rot. Velocity: " fieldwidth:54 range:[-1e9,1e9,20] align:#right offset:[4,4]
spinner ui_planet_tiltX "Axis Tilt X: " fieldwidth:54 range:[-1,1,0] scale:0.01 align:#right offset:[4,4]
spinner ui_planet_tiltY "Axis Tilt Y: " fieldwidth:54 range:[-1,1,0] scale:0.01 align:#right offset:[4,-2]
)
)
)
delete objects
t = sphere name:"target" pos:[0,0,0] radius:20 wirecolor:yellow
p = sphere name:"planet" pos:[100,0,0] radius:10 wirecolor:green
custattributes.add p OrbitAttribute baseobject:on
(
c = p.transform.controller = Transform_Script()
c.addtarget "params" p.baseobject.OrbitAttribute
p.baseobject.OrbitAttribute.target = t
ss = ""
ss += "ptm = if (this.VariableExists \"target\") and isvalidnode (target = this.getnode \"target\") then target.transform else (Matrix3 1)
"
ss += "tm = transmatrix [params.orbit_radius1*(cos (f*params.orbit_speed)), params.orbit_radius2*(sin (f*params.orbit_speed)), 0]
"
ss += "rotate tm (rotateYPRMatrix params.orbit_yaw params.orbit_pinch params.orbit_roll)
"
ss += "tm *= ptm
"
ss += "otm = matrixfromnormal (normalize (point3 params.planet_tiltX params.planet_tiltY 1))
"
ss += "otm = prerotateZ otm (f*params.planet_velocity)
"
ss += "translate (otm as matrix3) tm.pos
"
c.setexpression ss
--format ">> %
" (p.baseobject.OrbitAttribute.getNode())
)
setTrajectoryOn p on
select p
some bugs were fixed and the code was cleaned up:
OrbitAttribute = attributes OrbitAttribute attribid:#(0x00001967,0x12121200) version:1
(
fn getNode =
(
owner = custattributes.getowner this
refs.dependentnodes owner firstonly:on
)
fn update = notifydependents this partid:#tm
local script =
(
script = ""
script += "ptm = if (this.VariableExists \"target\") and isvalidnode target then target.transform else (Matrix3 1)
"
script += "ptm = transmatrix ptm.position
"
script += "tm = translate (matrix3 1) [params.orbit_radius1*(cos (f*params.orbit_speed)), params.orbit_radius2*(sin (f*params.orbit_speed)), 0]
"
script += "rotate tm (rotateYPRMatrix params.orbit_yaw params.orbit_pinch params.orbit_roll)
"
script += "tm *= ptm
"
script += "otm = matrixfromnormal (normalize (point3 params.planet_tiltX params.planet_tiltY 1))
"
script += "otm = prerotateZ otm (f*params.planet_velocity)
"
script += "translate (otm as matrix3) tm.pos
"
)
parameters params rollout:params
(
target type:#node ui:ui_target
orbit_radius1 type:#float default:100 ui:ui_orbit_radius1
orbit_radius2 type:#float default:50 ui:ui_orbit_radius2
orbit_speed type:#float default:10 ui:ui_orbit_speed
orbit_yaw type:#float default:0 ui:ui_orbit_yaw
orbit_pinch type:#float default:0 ui:ui_orbit_pinch
orbit_roll type:#float default:0 ui:ui_orbit_roll
on target set val do
(
if isvalidnode val and isvalidnode (node = getNode()) do
(
c = node.transform.controller
if c.VariableExists "target" then c.setNode "target" val else c.addNode "target" val
)
update()
)
on orbit_radius1 set val do update()
on orbit_radius2 set val do update()
on orbit_speed set val do update()
on orbit_yaw set val do update()
on orbit_pinch set val do update()
on orbit_roll set val do update()
planet_velocity type:#float default:20 ui:ui_planet_velocity
planet_tiltX type:#float default:0 ui:ui_planet_tiltX
planet_tiltY type:#float default:0 ui:ui_planet_tiltY
on planet_velocity set val do update()
on planet_tiltX set val do update()
on planet_tiltY set val do update()
)
rollout params "Parameters" category:1
(
group "Target: "
(
pickbutton ui_target "None" autoDisplay:on width:144 align:#left offset:[-4,0]
)
group "Orbit: "
(
spinner ui_orbit_radius1 "Radius 1: " fieldwidth:54 range:[0,1e9,100] align:#right offset:[4,0]
spinner ui_orbit_radius2 "Radius 2: " fieldwidth:54 range:[0,1e9,50] align:#right offset:[4,-2]
spinner ui_orbit_speed "Ang. Speed: " fieldwidth:54 range:[-1e9,1e9,10] align:#right offset:[4,4]
spinner ui_orbit_yaw "Yaw: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,4]
spinner ui_orbit_pinch "Pinch: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,-2]
spinner ui_orbit_roll "Roll: " fieldwidth:54 range:[-1e9,1e9,0] align:#right offset:[4,-2]
)
group "Planet: "
(
spinner ui_planet_velocity "Rot. Velocity: " fieldwidth:54 range:[-1e9,1e9,20] align:#right offset:[4,4]
spinner ui_planet_tiltX "Axis Tilt X: " fieldwidth:54 range:[-1,1,0] scale:0.01 align:#right offset:[4,4]
spinner ui_planet_tiltY "Axis Tilt Y: " fieldwidth:54 range:[-1,1,0] scale:0.01 align:#right offset:[4,-2]
)
)
)
delete objects
t = sphere name:"target" pos:[0,0,0] radius:20 wirecolor:yellow
p = sphere name:"planet" pos:[100,0,0] radius:10 wirecolor:green
s = sphere name:"satellite" pos:[110,0,0] radius:2 wirecolor:yellow
custattributes.add p OrbitAttribute baseobject:on
(
attr = p.baseobject.OrbitAttribute
c = p.transform.controller = Transform_Script()
c.addtarget "params" attr
c.addnode "target" t
attr.target = t
c.setexpression attr.script
)
custattributes.add s OrbitAttribute baseobject:on
(
attr = s.baseobject.OrbitAttribute
c = s.transform.controller = Transform_Script()
c.addtarget "params" attr
c.addnode "target" p
attr.target = p
attr.orbit_speed = 20
attr.orbit_radius1 = 30
attr.orbit_radius2 = 30
attr.orbit_yaw = 90
c.setexpression attr.script
)
setTrajectoryOn p on
setTrajectoryOn s on
select p
my physics theoretic background is pushing me to make the true physics algorithm but i’m too lazy now to listen it … mass, gravity, angular speed, and “everything else”… any one who wants to play with it is welcome.