Jump to content

Solar system simulation


israeldavid
Go to solution Solved by srek,

Recommended Posts

Do you want the real elliptical paths planets follow or circles? If you want ellipses you need to work out the math to describe each path.

What data do you have and what degree of realism do you want to achieve? This can be anything from very simple hierarchical circle paths up to n body problems and anything in between. 

Link to comment
11 minutes ago, srek said:

Do you want the real elliptical paths planets follow or circles? If you want ellipses you need to work out the math to describe each path.

What data do you have and what degree of realism do you want to achieve? This can be anything from very simple hierarchical circle paths up to n body problems and anything in between. 

i've gotta learn the easiest first haha, so in circles would be fine. i have the epherimerides from Nasa's site (in CSV files) but i don't know how to setup in c4d.. it don't need to be realistic, i'd be happy if it only works with the right positions 😁 like this animation if you ask 

 

Link to comment

I woul start with the average radius (distance to sun) of each object and either work in km scene units or scale everything down by the same factor. Place a Null for each object in the scene center (Sun) and place the object at the given radius. Then adjust the angle of the center null to the orbital inclination of each object. If you want to do the moon or moons of other planets just add them with the planet instead of the sun as center.

Then you have to decide if you want to keyframe the rotation or control it via an expression. Personally i would go for an expression but both should work.

Via Xpresso i would use three User Data fields to provide the starting angle (position on the path at a given start time, you should be able to get that from the ephemeris table), the angular velocity and a time scale factor to map the velocity to animation time. The expression itself is just the adding up of the velocity over time with a special case to set the angle back to start on frame 0.

Good luck 🙂

Link to comment

Hi @israeldavid, hi @srek,

 

I think that is a fun topic 😄 . But I also think you underestimate a bit the size of our solar system ^^ Neptune, the last planet in our system (sorry, Pluto 😞 ), has a radius of about 25,000 km but is about 4.5 billion kilometers away from the sun. So its not hard to imagine that when you work with real data, that you won't see much except the sun and maybee a planet when you are close enough. So you will need some sort of scaling when you want to show the whole solar system.

 

Srek's approach of animating stuff more or less manually is probably much more production focused, but I thought I'd give it a go with a Python generator. It took me surprisingly only about 90 lines of code to do a somewhat working solar system. You can find the code and a scene file below. Please keep in mind that I mostly did this as a "fun thing", so it will likely not be exactly what you want, but maybe you can still borrow bits from it (for example to do the expressions Srek talked about). My approach is deliberately data driven, since this is what I thought to be fun 😉

 

A little animation done with the generator, the little blue pixel is earth. The solar system is at 1% distance scale of the real solar system, so 1km is 10m in this system.

 

 

Cheers,

Ferdinand

 

The code:

"""Summary

Attributes:
    ORBITAL_SYSTEM (TYPE): Description
"""
import c4d
import math

INVERSE_EARTH_PERIOD = 1. / 365.

# The solar system as a hierarchical data structure. Distances and radii are
# measured in kilometers, orbital periods are measured in (earth) days. You
# can extend the system easily by just adding satellites (technically you
# could also let the sun orbit something). The code below is however setup in
# such fashion that you can only have one root in the system, i.e., you cannot
# have two primaries in the data structure at level zero.
ORBITAL_SYSTEM = {
    "Sun": {                            # The name of the primary
        "radius": 696340,               # The radius of the primary
        "distance": 0,                  # The distance to its primary
        "color": c4d.Vector(1, .75, 0), # The viewport color of the primary
        "period": 0,                    # The orbital period of the primary
        "satellites": {                 # The satellites of the primary
            "Mercury": {
                "radius": 2439.7,
                "distance": 57.91E6,    # i.e., 57.91 million kilometers
                "color": c4d.Vector(.55, .55, .55),
                "period": 88,
                "satellites": {},
            },
            "Venus": {
                "radius": 6051.8,
                "distance": 108.2E6,
                "color": c4d.Vector(.9, .9, .9),
                "period": 225,
                "satellites": {},
            },
            "Earth": {
                "radius": 6371,
                "distance": 148.55E6,
                "color": c4d.Vector(.1, .5, .9),
                "period": 365,
                "satellites": {
                    "Moon": {
                        "radius": 1737.1,
                        "distance": 384400,
                        "color": c4d.Vector(.3, .3, .3),
                        "period": 27,
                        "satellites": {}
                    },
                },
            },
            "Mars": {
                "radius": 3389.5,
                "distance": 240.16E6,
                "color": c4d.Vector(.85, .35, .1),
                "period": 687,
                "satellites": {},
            },
            "Jupiter": {
                "radius": 69911,
                "distance": 778.5E6,
                "color": c4d.Vector(.85, .7, .1),
                "period": 4380,
                "satellites": {},
            },
            "Saturn": {
                "radius": 58232,
                "distance": 1489.6E6,
                "color": c4d.Vector(.55, .4, .25),
                "period": 10585,
                "satellites": {},
            },
            "Uranus": {
                "radius": 25362,
                "distance": 2871E6,
                "color": c4d.Vector(.65, .85, .95),
                "period": 30660,
                "satellites": {},
            },
            "Neptune": {
                "radius": 24622,
                "distance": 4495E6,
                "color": c4d.Vector(.05, .45, .65),
                "period": 60225,
                "satellites": {},
            },
        },
    },
}

TWO_PI = math.pi * 2.

def build_system(name, data, settings):
    """Builds a system from a fragment of an ORBITAL_SYSTEM data structure.

    This function builds recursively all the sub-systems of a system.

    Args:
        name (str): The name of the primary.
        data (dict): Its data dictionary taken from ORBITAL_SYSTEM.
        settings (dict): The user data parameters.

    Returns:
        c4d.BaseObject: The system fragment.
    """
    # The primary as a sphere object.
    primary = c4d.BaseList2D(c4d.Osphere)
    primary.SetName("body")
    primary.MakeTag(c4d.Tphong)

    # Write its node data.
    combined_scale = settings["global_scale"] * settings["distance_scale"]
    xpos = data["distance"] * combined_scale
    primary[c4d.PRIM_SPHERE_SUB] = 32
    primary[c4d.PRIM_SPHERE_RAD] = data["radius"] * settings["global_scale"]
    primary[c4d.ID_BASEOBJECT_REL_POSITION, c4d.VECTOR_X] = xpos
    primary[c4d.ID_BASEOBJECT_USECOLOR] = 2
    primary[c4d.ID_BASEOBJECT_COLOR] = data["color"]

    # And build its satellites.
    for satellite_name, satellite_data in data["satellites"].items():
        satellite = build_system(satellite_name, satellite_data, settings)
        satellite.InsertUnder(primary)

    # A null so that we can easily animate the orbit arround its primary.
    root = c4d.BaseList2D(c4d.Onull)
    root.SetName(name)
    primary.InsertUnder(root)

    # The current document time.
    t = doc.GetTime().Get()
    # Animation period of of that primary in relation to earth period.
    p = data["period"] * settings["orbit_duration"] * INVERSE_EARTH_PERIOD
    # Bails if the object has no period.
    if p == 0.0:
        return root

    # The rotational value as the fraction of period remainder of the
    # document time. We then have to multiply by 2π since Cinema handles
    # roatation in radians.
    theta = TWO_PI * (t % p / p)
    # Set the heading of the null.
    root[c4d.ID_BASEOBJECT_REL_ROTATION, c4d.VECTOR_X] = theta

    return root



def main():
    """Entry point for Cinema 4D to evaluate the Python generator object.
    """
    settings = {
        # Out input data is in real world units, we have to scale this
        # a bit down.
        "global_scale": op[c4d.ID_USERDATA, 1],
        # Just our solar system alone is fricking huge, so we propbably want 
        # to scale down distances a bit, so that we can actually see 
        # something.
        "distance_scale": op[c4d.ID_USERDATA, 2],
        # The time in seconds on year takes, i.e., one full earth orbit.
        "orbit_duration": op[c4d.ID_USERDATA, 4],
    }

    # The root element.
    root_name = list(ORBITAL_SYSTEM.keys())[0]
    root_data = ORBITAL_SYSTEM[root_name]

    # Build the system.
    root = build_system(root_name, root_data, settings)

    # This is only needed for when the user collapses the Python generator via
    # CSTO, so that we get then a nice hierarchy.
    system = c4d.BaseList2D(c4d.Onull)
    system.SetName(op.GetName())
    root.InsertUnder(system)

    return system


 

solar_system.c4d

Link to comment
16 hours ago, srek said:

I woul start with the average radius (distance to sun) of each object and either work in km scene units or scale everything down by the same factor. Place a Null for each object in the scene center (Sun) and place the object at the given radius. Then adjust the angle of the center null to the orbital inclination of each object. If you want to do the moon or moons of other planets just add them with the planet instead of the sun as center.

Then you have to decide if you want to keyframe the rotation or control it via an expression. Personally i would go for an expression but both should work.

Via Xpresso i would use three User Data fields to provide the starting angle (position on the path at a given start time, you should be able to get that from the ephemeris table), the angular velocity and a time scale factor to map the velocity to animation time. The expression itself is just the adding up of the velocity over time with a special case to set the angle back to start on frame 0.

Good luck 🙂

@sreki have the scale in km and already did everything you told me to, i've created the nulls objects, placed them in the center, put the planets at place as well but i'm having a hard time to insert the data in xpresso (sorry i'm a beginner in C4D and i'm really challenging myself, spent the whole afternoon trying to get it done haha), could you help me out on this? here's the file 

Solar_System.c4d

Link to comment
5 hours ago, zipit said:

Hi @israeldavid, hi @srek,

 

I think that is a fun topic 😄 . But I also think you underestimate a bit the size of our solar system ^^ Neptune, the last planet in our system (sorry, Pluto 😞 ), has a radius of about 25,000 km but is about 4.5 billion kilometers away from the sun. So its not hard to imagine that when you work with real data, that you won't see much except the sun and maybee a planet when you are close enough. So you will need some sort of scaling when you want to show the whole solar system.

 

Srek's approach of animating stuff more or less manually is probably much more production focused, but I thought I'd give it a go with a Python generator. It took me surprisingly only about 90 lines of code to do a somewhat working solar system. You can find the code and a scene file below. Please keep in mind that I mostly did this as a "fun thing", so it will likely not be exactly what you want, but maybe you can still borrow bits from it (for example to do the expressions Srek talked about). My approach is deliberately data driven, since this is what I thought to be fun 😉

 

A little animation done with the generator, the little blue pixel is earth. The solar system is at 1% distance scale of the real solar system, so 1km is 10m in this system.

 

 

Cheers,

Ferdinand

 

The code:


"""Summary

Attributes:
    ORBITAL_SYSTEM (TYPE): Description
"""
import c4d
import math

INVERSE_EARTH_PERIOD = 1. / 365.

# The solar system as a hierarchical data structure. Distances and radii are
# measured in kilometers, orbital periods are measured in (earth) days. You
# can extend the system easily by just adding satellites (technically you
# could also let the sun orbit something). The code below is however setup in
# such fashion that you can only have one root in the system, i.e., you cannot
# have two primaries in the data structure at level zero.
ORBITAL_SYSTEM = {
    "Sun": {                            # The name of the primary
        "radius": 696340,               # The radius of the primary
        "distance": 0,                  # The distance to its primary
        "color": c4d.Vector(1, .75, 0), # The viewport color of the primary
        "period": 0,                    # The orbital period of the primary
        "satellites": {                 # The satellites of the primary
            "Mercury": {
                "radius": 2439.7,
                "distance": 57.91E6,    # i.e., 57.91 million kilometers
                "color": c4d.Vector(.55, .55, .55),
                "period": 88,
                "satellites": {},
            },
            "Venus": {
                "radius": 6051.8,
                "distance": 108.2E6,
                "color": c4d.Vector(.9, .9, .9),
                "period": 225,
                "satellites": {},
            },
            "Earth": {
                "radius": 6371,
                "distance": 148.55E6,
                "color": c4d.Vector(.1, .5, .9),
                "period": 365,
                "satellites": {
                    "Moon": {
                        "radius": 1737.1,
                        "distance": 384400,
                        "color": c4d.Vector(.3, .3, .3),
                        "period": 27,
                        "satellites": {}
                    },
                },
            },
            "Mars": {
                "radius": 3389.5,
                "distance": 240.16E6,
                "color": c4d.Vector(.85, .35, .1),
                "period": 687,
                "satellites": {},
            },
            "Jupiter": {
                "radius": 69911,
                "distance": 778.5E6,
                "color": c4d.Vector(.85, .7, .1),
                "period": 4380,
                "satellites": {},
            },
            "Saturn": {
                "radius": 58232,
                "distance": 1489.6E6,
                "color": c4d.Vector(.55, .4, .25),
                "period": 10585,
                "satellites": {},
            },
            "Uranus": {
                "radius": 25362,
                "distance": 2871E6,
                "color": c4d.Vector(.65, .85, .95),
                "period": 30660,
                "satellites": {},
            },
            "Neptune": {
                "radius": 24622,
                "distance": 4495E6,
                "color": c4d.Vector(.05, .45, .65),
                "period": 60225,
                "satellites": {},
            },
        },
    },
}

TWO_PI = math.pi * 2.

def build_system(name, data, settings):
    """Builds a system from a fragment of an ORBITAL_SYSTEM data structure.

    This function builds recursively all the sub-systems of a system.

    Args:
        name (str): The name of the primary.
        data (dict): Its data dictionary taken from ORBITAL_SYSTEM.
        settings (dict): The user data parameters.

    Returns:
        c4d.BaseObject: The system fragment.
    """
    # The primary as a sphere object.
    primary = c4d.BaseList2D(c4d.Osphere)
    primary.SetName("body")
    primary.MakeTag(c4d.Tphong)

    # Write its node data.
    combined_scale = settings["global_scale"] * settings["distance_scale"]
    xpos = data["distance"] * combined_scale
    primary[c4d.PRIM_SPHERE_SUB] = 32
    primary[c4d.PRIM_SPHERE_RAD] = data["radius"] * settings["global_scale"]
    primary[c4d.ID_BASEOBJECT_REL_POSITION, c4d.VECTOR_X] = xpos
    primary[c4d.ID_BASEOBJECT_USECOLOR] = 2
    primary[c4d.ID_BASEOBJECT_COLOR] = data["color"]

    # And build its satellites.
    for satellite_name, satellite_data in data["satellites"].items():
        satellite = build_system(satellite_name, satellite_data, settings)
        satellite.InsertUnder(primary)

    # A null so that we can easily animate the orbit arround its primary.
    root = c4d.BaseList2D(c4d.Onull)
    root.SetName(name)
    primary.InsertUnder(root)

    # The current document time.
    t = doc.GetTime().Get()
    # Animation period of of that primary in relation to earth period.
    p = data["period"] * settings["orbit_duration"] * INVERSE_EARTH_PERIOD
    # Bails if the object has no period.
    if p == 0.0:
        return root

    # The rotational value as the fraction of period remainder of the
    # document time. We then have to multiply by 2π since Cinema handles
    # roatation in radians.
    theta = TWO_PI * (t % p / p)
    # Set the heading of the null.
    root[c4d.ID_BASEOBJECT_REL_ROTATION, c4d.VECTOR_X] = theta

    return root



def main():
    """Entry point for Cinema 4D to evaluate the Python generator object.
    """
    settings = {
        # Out input data is in real world units, we have to scale this
        # a bit down.
        "global_scale": op[c4d.ID_USERDATA, 1],
        # Just our solar system alone is fricking huge, so we propbably want 
        # to scale down distances a bit, so that we can actually see 
        # something.
        "distance_scale": op[c4d.ID_USERDATA, 2],
        # The time in seconds on year takes, i.e., one full earth orbit.
        "orbit_duration": op[c4d.ID_USERDATA, 4],
    }

    # The root element.
    root_name = list(ORBITAL_SYSTEM.keys())[0]
    root_data = ORBITAL_SYSTEM[root_name]

    # Build the system.
    root = build_system(root_name, root_data, settings)

    # This is only needed for when the user collapses the Python generator via
    # CSTO, so that we get then a nice hierarchy.
    system = c4d.BaseList2D(c4d.Onull)
    system.SetName(op.GetName())
    root.InsertUnder(system)

    return system


 

solar_system.c4d 242.34 kB · 2 downloads

Tried to open it and nothing appears in the hud i can only see the python tag, this way is much more difficult to me i don't know anything about programming haha. But thank you very much for trying to help. by the way my aproach also is a data driven project to simulate eclipses and stuff

Link to comment
On 3/13/2021 at 5:17 AM, srek said:

Do you really use R14? Please make sure to set the correct version. If you like you can send me your file and i add the Xpresso stuff i described. 

Yeah I use R14 version. I've sent the file at the previous reply, if it is not working let me know

Link to comment
On 3/13/2021 at 2:00 AM, israeldavid said:

Tried to open it and nothing appears in the hud i can only see the python tag, this way is much more difficult to me i don't know anything about programming haha. But thank you very much for trying to help. by the way my aproach also is a data driven project to simulate eclipses and stuff

 

Hi,

 

the file contains a Python Generator object and not a Python (Programming) tag. I actually see just now that you are on R14, I digged up a R14 license and made the modifications necessary to run the file in principle on R14, the object color thing won't work there though. About the programming thing: I was under the impression that this a programming question since this is a programming forum 😉

 

But my little file might be useful in the sense that it could be helpful to find a good scaling factor for a hand crafted system, because when you use real world values, you won't be able to see much.

 

edit: almost forgot the file 😉 Its attached at the end.

 

Cheers,
Ferdinand 

solar_system_14.c4d

Link to comment
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • LATEST ACTIVITIES

    1. 7

      CORE 4D Youtube channel

    2. 7

      Draw primitives on surface of existing objects?

    3. 0

      Nodes Modifier result isn't updated anymore

    4. 220

      Scene Nodes | Capsules file pit

    5. 3

      Flipped clones in multi-segments curve

×
×
  • Create New...

Copyright Core 4D © 2023 Powered by Invision Community