Examples

Solar System

This example is the same as the tutorial.

11 Solar System.celsrc
-.--------------------------------------------------------------------------------------
	Solar system
	
	This example is not very different from the rotating cubes example. It serves only to show
	that with the ( fairly basic ) integration of Direct X in CellSpeak, it is easy to build
	animated models. There is a lot of room to add sophistication to this program, 
	both in its graphics and its behaviour, but 	
-.--------------------------------------------------------------------------------------

use Math, Strings, Editor, Windows
use D3D11, Camera, Light, Color, Material, Shape

--	A sphere - based on the shared mesh shape (see shape.cellsrc in packages\d3dgraphics)
design Sphere(float Radius, MeshClass cppMesh) like SharedMesh( cppMesh ) is
	
	-- originaly the sphere is positioned at the origin (see Shape.SharedMesh)
	-- A sphere has a simple world matrix 
	WorldMatrix = [
			Radius,	0,		0,		Position.x,
			0,		Radius,	0,		Position.y,
			0,		0,		Radius,	Position.z,
			0,		0,		0,		1
		]
						
	-- we create a function variable that will be used to calculate a new frame for the cube
	var function FrameAction (word Interval) to do
	
	-- when a new frame has to be calculated the camera sends the message NewFrame
	on NewFrame(word Interval) do
		
		-- ..just execute the frame action for the sphere
		FrameAction( Interval )
	end
	
	-- Note that the camera also sends the message 'draw', but that message is handled by the 
	-- ancestor design SharedMesh, because processing is the same for all mesh types( sphere, cube etc.)
	
	-- A message that sets the particular frame action for the sphere (in this case to advance along its orbit)
	on SetOrbit( xyz Axis, float AngularSpeed) do
	
		-- define the body for FrameAction
		body FrameAction with
		
			-- Calculate the rotation matrix to use (this is done now, at initialisation)
			matrix4 RotationMatrix =  Rotate.Axis( Axis , AngularSpeed)
		end is 		
			
			-- Calculate the world matrix - this is done each time the function is called
			WorldMatrix = RotationMatrix * WorldMatrix 	
		end
	end
end

-.-
	The solar system
	
	A simple table with the basic parameters of each planet serves as the starting point
	for creating the planets. In this model the ratio's of the planet sizes and the orbit 
	sizes are correct, but the size of the planets is not to scale wrt to the orbit, 
	otherwise the small spheres would be far apart.
	
	The sun itself is set at 10% of its actual size compared to the planets, because 
	otherwise the sun would be bigger then the orbits of the inner planets.
-.-
-- these are multipliers for distance, diameter and period that are based on the earth value.
const float AU = 149.597871	* 3	-- astronomical unit is 149 597 871 km - x 3 to spread the planets out 
const float ER = 12.756			-- the earth radius is 12 756 km
const float EY = 3.65			-- the duration of an earth year in seconds - 1 day = 10 msec

design SolarSystemDesign is

	-- The name of the planets
	type PlanetEnum is [Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto]
	
	-- The mesh for a sphere (shared by all spheres, so we only create it once)
	Mesh.PolarSphere SphereMesh	-- Mesh for a sphere

	-- The data for a planet
	type PlanetRecord is record
		cell			Cell
		float 			Diameter 	-- in Earth diameters
		float			Mass		-- In Earth Masses
		float 			Distance	-- From Sun, in AU = distance earth sun
		float			Period		-- in earth years
		Material.rgba 	Material 	-- material of the planet
	end
	
	-- The list of data for the planets (straight from Wikipedia - except for the material)
	PlanetRecord PlanetList[ PlanetEnum ] = [
	--	cell   Diameter	Mass   Distance Period	Material
		[null,	0.382,	0.06, 	0.39,	0.24,	Material.White],							-- Mercury
		[null,	0.949, 	0.82,	0.72,	0.62,	Material.White * 0.3],						-- Venus
		[null,	1.0,	1.0,	1.0,	1.0,	Material.Blue + Material.White*0.2],		-- Earth
		[null,	0.532,	0.11, 	1.52,	1.88,	Material.Red],								-- Mars
		[null,	11.209,	317.8,	5.2,	11.86,	Material.Red*0.4 + Material.Green*0.25],	-- Jupiter
		[null,	9.449,	95.2,	9.54,	29.46,	Material.Red*0.2 + Material.Green*0.2],		-- Saturn
		[null,	4.007,	14.6, 	19.22,	84.01,	Material.Aqua],								-- Uranus
		[null,	3.883,	17.2,	30.06,	164.8,	Material.Blue],								-- Neptune
		[null,	0.1863,	0.00218,39.54,	248.25,	Material.Fuschia]							-- Pluto, rehabilitated	
	]
	
	-- There is only one record for the sun - we do not define a separate type
	var Sun is record	
		cell 	Cell = null
		float 	Diameter = 109
		float 	Mass = 333000
		Material.rgba Stuff = Material.Yellow * 2.0
	end
		
	-- Constructing the solar system
	constructor is 

		-- Build a sphere mesh
		SphereMesh.Build(16,8)
				
		-- create the sun (at 10% of its relative size !)
		Sun.Cell = create Sphere( Sun.Diameter*ER/10, SphereMesh.cppMesh ) <- SetMaterial( Sun.Stuff )
			
		for each Planet in PlanetList do			
			-- create planet - set color, distance and orbit parameters 
			-- 1 year is 360° in 3.65 second @ 25 fps 
			Planet.Cell = create Sphere(Planet.Diameter*ER , SphereMesh.cppMesh) 	
					<- 	SetMaterial( Planet.Material  ), 
						MoveTo( [Planet.Distance*AU, 0, 0]),
						SetOrbit([0,1,0], 2*pi_f / ( 25 * EY * Planet.Period) ) 
		end
	end 
	
	-- pass the messages to the children
	on ? => all <- (same)
	
end -- SolarSystemDesign

-- This is the design that we will instatiate to get the program going
design HelloEarth is

	cell Camera								-- We need a camera
	cell Light								-- We need a light
	cell Window								-- A text output window 
	cell Timer 								-- we need a timer 
	CanvasWindowClass CameraWindow			-- The camera needs a window to display into
	Hwnd CameraWindowHandle					-- The window handle
	RectangleType Rectangle					-- The window rectangle	
	cell SolarSystem						-- Our scene
	
	constructor is
		
		-- The 'from' and 'to' vectors for the camera
		xyz From = [0,0,10*AU]
		xyz To = [0,0,0]
		
		-- We create the output window
		Window = create MenuWindow("The Solar System")
		
		-- set it also as stdout 
		system <- stdout.Set( Window )
	
		-- Create a camera that looks at the origin - we use a version with some more settings here then in the cubes example
		Camera 	= create FromTo(From,To, [0,1,0], 100*AU, 0.1, pi_f/4)
		
		-- The camera needs a window to display in - the rectangle defines the size of the window	
		Rectangle = [500,0,2000,1000]		
		
		-- Create the camera window class (calls a C++ method)
		CameraWindow = CameraWindow.Create("Camera",&Rectangle, 0, 0,null )
		
		-- Tell the window about the camera - the window will send keyboard and mouse events to the camera
		-- CameraWindow is a C++ object, so SetCamera is a C++ object method call.
		CameraWindow.SetCamera(Camera)
	
		-- Create a light for the scene - to simulate the sun we use a pointlight in the center 
		Light = create Point( Color.White, Color.White, Color.White, [10,10,10], 50*AU, 0.0)
		
		-- and build the solar system
		SolarSystem = create SolarSystemDesign
		
		-- Tell the camera about the window, the light and the scene (which starts at the world = self)
		Camera <- SetWindow(CameraWindow), SetLight(Light), SetScene(SolarSystem)
			
		-- Request a timer service from the system
		system <- Service.Get("Timer")
		
		-- We start the camera - we request a delivery notification for this message
		Camera <+- Roll
		
		-- and we print some feedback
		Window <- print("\nScene was created - Camera = [Camera] and Light = [Light] ") 

	end

	-- The delivery notification from the camera - just for info
	on Roll.DN do
		Window <- print("\nReceived Delivery Notification from Camera [sender]")
	end
	
	-- The timer service
	on Service.Provider( ansi Name, cell Provider) do
	
		-- check that the service is for a timer
		Name is "Timer" ? Timer = Provider	: yield
		
		-- every 3.65 seconds we will change the action ( 10msec is a day )
		Timer <- Subscribe.Interval( (EY * 1000) ,"ReportYears")
	end
	
	int YearCount = 0
	on ReportYears( word Time ) do	
		system <- println("[YearCount += 1] earth years have passed")		
	end
end -- HelloEarth