This is an outgrowth of an idea I originally floated in
http://www.hash.com/forums/index.php?showtopic=2410&st=15&#entry59814.
My objective is to create a sphere of randomly distributed stars 10 km
in radius, where each star is a one-patch object with a diameter
randomly ranging from 7.5 to 30 m. I also want to be able to control
the size of all stars simultaneously with a pose slider, to ensure that
the stars will always be rendered at about one pixel regardless of the
resolution of the render or the focal length of the camera.
After
Yves put me on the track of a bones-based solution, I first tried to
implement
http://www.hash.com/forums/index.php?showtopic=2410&view=findpost&p=59969
in which each star has two bones, one to position it randomly and one
to scale it, but I had to scrap it. First of all, the program hung when
I tried to go from 1024 stars to 2048. Second, I found that having to
evaulate an expression with a Rand() function on every bone made the
model load up very slowly in an action or choreography. What I'm
planning to do now is a two-stage approach: first, I create the
randomly distributed and scaled stars with expressions -- this time,
using only one bone per star -- then I bake the position of the bones
in place by opening it in an action window and exporting as a model.
After that, I'm going to create the pose slider that will scale each
bone uniformly.
The procedure goes like this: I made a single
circular patch consisting of two splines, 15 m in diameter and centered
on (0, 0, 10000 m). The CPs are assigned to a bone called Radius1
starting at the origin with a length of 10000 m. I replicated this
model by saving the file, importing the model into itself and repeating
11 times to give 2048 stars, with bones numbered from Radius1 to
Radius2048. What I need to do next is to apply these expressions to
each of the 2048 bones:
Transform.Rotate.X = 360*(-0.5+Rand())
Transform.Rotate.Y = 360*(-0.5+Rand())
(The
Rand() function returns values between 0 and 1, so this will orient the
bones randomly in a range of values between -180 and 180 degrees.)
Transform.Scale.X = 0.5+Rand()
Transform.Scale.Y = ..|X
(Scales each bone by X randomly between 50% and 150%, and sets the Y scale equal to the X scale.)
I
can generate the names of all the bones using a FOR loop, and I'm
choosing to do this using JavaScript, because I can very quickly use a
web browser to save the ouput to a text file, open the .mdl file in a
text editor, and paste the relationship into the right place. The
relationship container in the model file looks like this:
| CODE |
| [RELATION] Name=Relationship1 KeyDim=1 [OBJECTSHORTCUT] MatchName=Bones [ENDOBJECTSHORTCUT] [FileInfo] LastModifiedBy=Julian Fong [EndFileInfo] [ENDRELATION] |
| CODE |
| <script language="JavaScript"> var string1 = "[EMPTYDRIVER]<br>" string1 += "MatchName=Transform<br>" string1 += "[EMPTYDRIVER]<br>" string1 += "MatchName=Rotate<br>" string1 += "[EXPRESSION]<br>" string1 += "Value=360*(-0.5+Rand())<br>" string1 += "MatchName=X<br>" string1 += "[ENDEXPRESSION]<br>" string1 += "[EXPRESSION]<br>" string1 += "Value=360*(-0.5+Rand())<br>" string1 += "MatchName=Y<br>" string1 += "[ENDEXPRESSION]<br>" string1 += "[ENDEMPTYDRIVER]<br>" string1 += "[EMPTYDRIVER]<br>" string1 += "MatchName=Scale<br>" string1 += "[EXPRESSION]<br>" string1 += "Value=0.5+Rand()<br>" string1 += "MatchName=X<br>" string1 += "[ENDEXPRESSION]<br>" string1 += "[EXPRESSION]<br>" string1 += "Value=..|X<br>" string1 += "MatchName=Y<br>" string1 += "[ENDEXPRESSION]<br>" string1 += "[ENDEMPTYDRIVER]<br>" string1 += "[ENDEMPTYDRIVER]<br>" string1 += "[ENDOBJECTSHORTCUT]<br>" for(var i = 1; i <= 2048; i++) { document.write("[OBJECTSHORTCUT]<br>") document.write("MatchName=Radius" + i + "<br>") document.write(string1) } </script> |



Julian,
The
clustering you see is what you should expect. On a sphere, an arc
length is shorter close to the poles than around the equator, but your
algorithm places just as many bones at latitude 0 as it does at
latitude 89. The solution is to have a non uniform random distribution
for the latitude angle. It may be shown that this distribution should
have a frequency function as f(Lat) = cos(Lat)
This is an algorithm that might help you to solve your problem. It produces evenly random distributed points on a half sphere.
| CODE |
| N = 2048; for (int i=1, i < N, i++){ Lat = asin(rand()); // Latitude angle [0,pi/2). This is the "magic" line... Long = 2*pi*rand(); // Longitude angle [0,2*pi) X[i]= R*cos(Lat)*cos(Long); // X coordinate for the light source Y[i] = R*cos(Lat)*sin(Long); // Y coordinate for the light source Z[i] = R*sin(Lat); // Z coordinate for the light source } |
After some more thought, I think your problem will be solved if you simply change your line
| CODE |
| Transform.Rotate.X = 360*(-0.5+Rand()) |
| CODE |
| Transform.Rotate.X = 90 + 180/Pi()*ASin(2*Rand() - 1) |
Between the two solution suggested by Anders, I would prefer the first
one as it would be more efficient to generate the vectors this way
rather than rotating them.
Another faster variation of first Anders example would be:
| CODE |
N = 2048; for (int i=1, i < N, i++){ costheta = sqrt( Rand() ); sintheta = sqrt( 1.0 - costheta * costheta ); phi = Rand() * 2.0 * Pi(); X[i]= R*cos(phi)*sintheta; Y[i] = R*sin(phi)*sintheta; Z[i] = R*costheta; } |
| QUOTE (ypoissant @ Nov 29 2004, 04:30 PM) |
| [...]Another faster variation of first Anders example would be:[...] |
| CODE |
| N = 2048; for (int i=0, i < N, i++){ costheta = Rand(); sintheta = sqrt( 1.0 - costheta * costheta ); phi = Rand() * 2.0 * Pi(); X[i]= R*cos(phi)*sintheta; Y[i] = R*sin(phi)*sintheta; Z[i] = R*costheta; } |
Anders,
I know I can count on you for that sort of thing
You
are right. the first Sqrt is wrong. And, I also missed something else.
For a random distribution on the whole sphere (not only on half sphere)
the costheta should be:
| CODE |
costheta = 1.0 - 2.0 * Rand(); |
| QUOTE (ypoissant @ Nov 29 2004, 06:15 PM) | ||
|
Anders, Yves, thanks for the help. I can retool the model so that the
arrangement of bones depends on translation instead of rotation, which
would involve using a short bone for each star with an Aim At
constraint to a null at the origin. The necessity of reusing variables
means I would be better off computing the coordinates within the script
instead letting A:M do it with expressions.
In the SDK forum, I
asked about generating a normal distribution with the Rand() function,
and the thought occurs to me that if I used (Rand() + Rand()) /2, I
would be able to produce values close to 0.5 more often than 0 or 1, a
bit like rolling two dice. Anyway, I originally wanted to use an
expression like that to control the size variablilty among the stars,
but I probably won't be doing that now.
Success! I decided to do the arrangment of stars in an action instead
of a pose, because a translate driver in a pose always has two
keyframes, one for the pose turned off and one for it turned on,
whereas in an action I only need to use one keyframe. It keeps the file
size smaller and reduces processing time. I created a model called
StarSphere_1-repl2048.mdl which contains 2048 copies of a 15 meter star
centered on the origin, each with a 15 meter long bone (Bone1 to
Bone2048) starting at the origin. I also have a null called Origin at
the origin.
The HTML script for generating the action file looks like this:
| CODE |
| <pre> [ACTIONFILE] ProductVersion=11.1 [POSTEFFECTS] [ENDPOSTEFFECTS] [IMAGES] [ENDIMAGES] [SOUNDS] [ENDSOUNDS] [MATERIALS] [ENDMATERIALS] [POSTEFFECTS] [ENDPOSTEFFECTS] [OBJECTS] [ENDOBJECTS] [ACTIONS] [ACTION] StrideStartPosition=0 0 0 StrideEndPosition=0 0 0 DefaultModel=StarSphere_1-repl2048 PlayRange=0 0 [OBJECTSHORTCUT] MatchName=Bones <script> for (var i=1; i<=2048; i++) { with (Math) { costheta = 1.0 - 2.0 * random() sintheta = sqrt( 1.0 - costheta * costheta ) phi = random() * 2.0 * PI X = round( 1000000 * cos(phi) * sintheta ) Y = round( 1000000 * sin(phi) * sintheta ) Z = round( 1000000 * costheta ) } document.write("[OBJECTSHORTCUT]\n") document.write("MatchName=Bone" + i + "\n") document.write("[EMPTYDRIVER]\n") document.write("MatchName=Transform\n") document.write("[EMPTYDRIVER]\n") document.write("MatchName=Scale\n") document.write("[EXPRESSION]\n") document.write("Value=0.5+Rand()\n") document.write("Name=X\n") document.write("MatchName=X\n") document.write("[ENDEXPRESSION]\n") document.write("[EXPRESSION]\n") document.write("Value=..|X\n") document.write("Name=Y\n") document.write("MatchName=Y\n") document.write("[ENDEXPRESSION]\n") document.write("[ENDEMPTYDRIVER]\n") document.write("[EMPTYDRIVER]\n") document.write("MatchName=Translate\n") document.write("[TRANSFDRIVER]\n") document.write("Name=X\n") document.write("MatchName=X\n") document.write("[SPLINE]\n") document.write("CPs=1\n") document.write("1\n") document.write("0 " + X + "\n") document.write("[ENDSPLINE]\n") document.write("[ENDTRANSFDRIVER]\n") document.write("[TRANSFDRIVER]\n") document.write("Name=Y\n") document.write("MatchName=Y\n") document.write("[SPLINE]\n") document.write("CPs=1\n") document.write("1\n") document.write("0 " + Y + "\n") document.write("[ENDSPLINE]\n") document.write("[ENDTRANSFDRIVER]\n") document.write("[TRANSFDRIVER]\n") document.write("Name=Z\n") document.write("MatchName=Z\n") document.write("[SPLINE]\n") document.write("CPs=1\n") document.write("1\n") document.write("0 " + Z + "\n") document.write("[ENDSPLINE]\n") document.write("[ENDTRANSFDRIVER]\n") document.write("[ENDEMPTYDRIVER]\n") document.write("[ENDEMPTYDRIVER]\n") document.write("[AIMATCONSTRAINT]\n") document.write("BoneTarget=..|Origin\n") document.write("[ENDAIMATCONSTRAINT]\n") document.write("[ENDOBJECTSHORTCUT]\n") } </script>[ENDOBJECTSHORTCUT] [ENDACTION] [ENDACTIONS] [CHOREOGRAPHIES] [ENDCHOREOGRAPHIES] [ENDACTIONFILE] </pre> |

Well, it's pretty much done, but it's not very practical to use. Sure,
it renders really fast, but on my 1.5 GHz Mac it takes nearly six
minutes to load up the project. Basically, this is the point of the
whole exercise:
Focal length 35 mm, 320x240 resolution, star size 20 m:
Focal length 35 mm, 640x480 resolution, star size 12 m:
Focal length 35 mm, 1024x768 resolution, star size 8 m:
Focal length 100 mm, 640x480 resolution, star size 5 m:
What
I'm probably going to end up doing is to start with this sphere of
variable-size stars that I've got, and by exporting actions to models,
create different versions where the stars are fixed at particular
sizes, and delete all the bones from each of these versions to make
them load more efficiently.
Julian, Yves, aaver,
This looks like it is coming along quite well, it seems promising and I'm hoping you'll share it with the rest of us
This site: http://www.ap3d.com/betterspace/
Has a pretty decent starfied, it was done with Lightwave, but maybe there are somethings that apply (code is way beyond me)
My
question is how does it look with motion blur. I have a tough time
getting a good look with stars whenever I have the camera moving i.e.
spaceship flyby.
I hope all goes well.
Thank you for your comment! When no one else was replying to this topic, I thought nobody was interested.
I'd be willing to make this material available to download, but I'd
have to document how to use the star sphere, because it's a little
tricky.
I forgot to mention that I applied an action to the
original sphere of 2048 stars that created 15 duplicates of it as
action objects, for a total of 32768 stars. These duplicates all have
different rotations and are scaled -100% on 0, 1, 2, or all 3 axes.
I'll
try to render a test animation demonstrating motion blur soon. I'm also
going to produce the boneless fixed-size variants, and before I'm done
with the whole project, I want to investigate the possibility of using
an expression to automate changing the size of the stars based on the
focal length and output resolution of the camera.
I've been following this thread, but didn't have anything to say about
the technical aspect so left it alone. I still don't reall understand
the advantage of this? I don't do animation very much so would like to
know if it's something to with that.
| QUOTE (Zaryin @ Dec 14 2004, 01:26 PM) |
| I've been following this thread, but didn't have anything to say about the technical aspect so left it alone. I still don't reall understand the advantage of this? I don't do animation very much so would like to know if it's something to with that. |



Here's an animation test where I'm trying to focus on motion blur. In
case you're wondering, the TIE fighter is a 3DS prop that I downloaded
from http://scifi3d.theforce.net/. With the default A-buffer
antialiasing, the motion blur is confined to a narrow band of stars in
the middle of the picture. This is something I've observed on previous
versions of A:M, and I don't know why it happens. Is there something
that the Hash team can do to improve the default motion blur routines,
or do we have to use multipass if we want better results?
With 3x3 multipass, all the stars are motion blurred, but they look a little too aliased to me:
So
I went with 4x4 multipass, and it does look good, but these three
seconds of footage took me nearly 5 hours to render. This is one frame:
And here's the full scene: http://www.evilnet.net/~jhfong/animas/dl/starsphere/tiefighter-mp16.mov
(3.0 MB QuickTime, 640x480, Sorenson 3 codec.) Right at the end of the
scene, when the camera is moving slowly, you can see the stars
shimmering, and I'll have to try to find a way around that. Maybe I'll
have to make the stars bigger, or increase the number of passes.
What
really seems to be holding up the rendering time is the TIE fighter
itself, especially in the middle when it's close to the screen. I could
try to render the TIE fighter in A-buffer with no background and an
alpha channel, render just the starfield with multipass, and then
composite them together.
I totally agree with you on the motion blur thing. I'm hoping that your
star rig will help those of us who do a bunch of space scenes
I tend to get areas of the image that are motion-blurred and then areas
that aren't, it makes really hard to get a good fly-by.
I see now how that would help. For a guy who does only images this
wouldn't be that important, but I can see how this would be excellent
for animation. Great work.
I've had no luck with using an expression to automate the star size.
The size of the stars is controlled by a pose slider that I called
"Median star size in meters". I set the keyframes up so that the
percentage of the pose reflects the original size of the stars -- i.e.,
the stars were 15 m in diameter before I randomized the size, and the
default position of the slider is 15%. Right now, the slider goes
between 5 m and 30 m, but I think I'll reset the minimum down to 0
since I do actually have keyframes at 0.
Anyway, in the choregraphy I tried to set the position of the pose slider equal to this expression:
0.9*10000*Tan((2*ATan(17.5/..|..|..|Shortcut
to Camera1.Focal Length))/Max(..|..|..|Shortcut to Camera1.Output
Options.Resolution.Width, ..|..|..|Shortcut to Camera1.Output
Options.Resolution.Height))
...but trying to apply the
expression causes A:M to crash. (The 0.9 at the beginning is a fudge
factor to make the stars a little dimmer, and I left it there instead
of saying "9000*..." to make it easier to make adjustments.) I'm going
to give up on trying to automate the process, and I'll just leave it up
to the user to keyframe the pose slider at the same time that the
camera's focal length changes.
*This thread made me feel stupid and lonely*
Aw, don't feel bad about it. I feel pretty stupid and lonely myself for
getting sidetracked for a month working on something that may be too
complicated for most people to use.
I
made a little mistake on the math in the expression in my previous
post. The 2 is in the wrong place, but considering how much smaller the
stars are compared to the distance to them, the error only affects the
sixth decimal place and beyond, so it has no real effect.
Attached
is a proof that shows how to determine how big the stars need to be.
I'm probably going to include this graphic in the documentation when I
release this project, because it's crucial to the understanding of how
the star sphere works.
Assume that the camera is located at the origin, inside a star sphere of radius R meters. The camera's focal length is f millimeters, and it is set to render an image whose largest dimension is W pixels. We want to solve for the diameter s of a star which will occupy one pixel in the render. Let angle A be the angle of the camera's field of view, and angle C be the angle subtended by the star.
Attached image(s)
The thing that needs to be kept in mind is that the formula I derived:
s = 2R tan [atan (17.5 / f) / W]
shouldn't be used as an exact measure of the size you want to set the stars at. For instance, plugging in the values R = 10000 m, f = 35 mm and W = 640 gives me the value s
= 14.49 meters. However, because I made the star size vary randomly
between 50% and 150% of the median, it would actually look better if
you set the star size to 12 meters instead, which is what I did in my
previous examples.
I was just thinking of how useful this will be. Being able to maintain
the same star size is crucial to having multiple shots in a scene flow
together seamlessly. I might be getting too far ahead, but being able
to control the brightness of the stars would be cool too.
I've done one more animation test in which the camera zooms in and the
stars shrink at the same rate. To try to save time, I rendered the
stars with multipass and the TIE fighter with A-buffer antialiasing,
and composited them together in After Effects.
Here's one frame as the camera is zooming and panning simultaneously:
This is the movie: http://www.evilnet.net/~jhfong/animas/dl/starsphere/tiefighter-zoom.mov.
Immediately after this post, I'm going to make the star sphere model available to download in the Showcase forum.
You can find the files http://www.hash.com/forums/index.php?showtopic=10528 in the Showcase forum.
Wow, Julian;
That star sphere is pretty cool. Thanks for making it available to the whole community.
Martin Hash
Bumping this up as not only the Star Sphere is cool but so is the coding (javascript) behind it.
We are talking about how much we love the A:M file formats http://www.hash.com/forums/index.php?showtopic=11633.
I had a try:
http://www.hash.com/forums/index.php?showtopic=15940&st=15&#
The stars are too small I think. Where to alter the size?
I cannot find the expression you are talking about. And there is the script hiding?
Thanks for a little help - a little summary.
Note:
I did not say WINK it - but you are free to do it - telling the steps in doing it.
Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)