This addition simulates decrease of reactive chemicals in film emulsion during exposure. The areas that have received more light react less than other areas. Useful for high contrast scenes as it brings up the dark areas and limit bright areas.
There are two new keywords in the global_settings block:
exposure FLOAT exposure_gain FLOAT
where exposure_gain is optional and has default value 1. Both parameters have to be greater than 0 to influence rendering.
exposure can be thought as film speed, aperture and exposure time multiplied together. The value is not absolute. If the light source intensities in the scene are multiplied by 10 and exposure value is divided by 10 the resulting image will be the same.
exposure_gain can be used to brighten scenes with low maximum intensity when also low exposure value is used.
The equation for such behavior of color used in MegaPOV is:
color = exposure_gain * (1 - exp( - exposure * color )).
Example 2.10. Various values for film exposure simulations
Examples which map range 0-1 to range 0-1 with increasing amount of compression:
exposure 0.05 exposure_gain 20 // almost linear exposure 0.2 exposure_gain 5.5 exposure 0.5 exposure_gain 2.5 exposure 1 exposure_gain 1.6 exposure 10 exposure_gain 1 exposure 100 exposure_gain 1 // high compression
In POV-Ray™ 3.5 and earlier temporary files with cache of radiosity were named the same for every frame in the animation rendering. Since MegaPOV 1.0 the name of this file is concatenated from the name of the currently rendered image. Together with Frame_Step (see Section 2.1.1, “Frame_Step”) and this addition it is finally possible to start two parallel processes with radiosity rendering over one source.
The radiosity function in POV-Ray™ 3.5 uses an internal table of directions for the rays that are traced from a sampling point to determine the irradiance at that point. This patch allows to select alternative sets of sample ray directions. This can help both to overcome the limit for maximum count of 1600 as well as improve the quality of results at lower count values.
The syntax description of this feature is:
RADIOSITY_ITEMS: ... [ samples SAMPLES_ITEMS ] SAMPLES_ITEMS: INT_SAMPLES_TYPE | { SAMPLES_COUNT, VECTOR_DIRECTION, ... [weight INT_WEIGHT_TYPE] }
MegaPOV contains an internal generator for sample direction using the halton sequence written by
. It is activated by adding:samples 1
to the radiosity{} block. The default value (0) uses the old internal direction table.
The sample ray directions can also be defined directly in the scene file:
samples { 300, // number of directions given <0.78080, -0.36618, 0.50622>, <-0.26409, -0.01064, 0.96444>, ... }
A number of sample direction sets is coming with MegaPOV as include files.
The coordinate system for these sample ray directions is relative to the surface at the sample position. The z-Axis points in normal direction. All directions should be in the upper hemisphere (z coordinate >0).
An optional weight parameter allows to weight the sample intensity with cos(theta) where theta is the angle between the normal vector and the ray direction. The sample ray directions should have a density distribution according to this function. If a uniform distribution is used instead weight 1 would weight the sample rays to compensate this. The default is 0 which turns off special weighting.
This patch is based on an idea by
. Normally the distribution of radiosity rays is identical for all sample points. This patch rotates the sample set around the vertical axis by a random angle for each sample taken. This can help to reduce artefacts in some cases.This patch is activated the following way:
radiosity { ... randomize on }
Note | |
---|---|
Since this feature uses a random number for the sample direction rotation it is not safe to use it in animations. Also a partial render of a scene will produce different results than rendering the whole scene. |
The mechanics simulation system is integrated into the POV-Ray™ rendering system. The simulation parameters are set in the global_settings{} block of the scene file. While parsing the scene MegaPOV calculates the simulation exactly where it occurs in the file. This way the simulation can interact with the scene by using objects, functions and values set before the mechsim{} block in the scene file. But additionally the simulation data can also be used in the scene later on for placing objects according to the simulation results.
This patch introduces a new block in the global_settings{} section of the POV-Ray™ scene file.
The complete syntax description of this block is:
MECHSIM: mechsim { [MECHSIM_ITEMS...] } MECHSIM_ITEM: method INTEGER | bounding INTEGER | gravity VECTOR | time_step FLOAT | step_count INTEGER | time FLOAT | start_time FLOAT | end_time FLOAT environment { ENVIRONMENT_DEFINITION [ENVIRONMENT_ITEMS...] } | interaction { INTERACTION_DEFINITION ... } | field { FIELD_DEFINITION ... } | attach { ATTACH_DEFINITION ... } | collision { COLLISION_TOGGLE [COLLISION_ITEMS...] } | topology { [GROUP_DEFINITIONS...] [TOPOLOGY_ITEMS...] [save_file FILE_NAME [Type]] } ENVIRONMENT_DEFINITION: function [(IDENT_LIST)] { FUNCTION_ITEMS } | object OBJECT ENVIRONMENT_ITEM: stiffness FLOAT | damping FLOAT | friction FLOAT [, FLOAT] | method INTEGER INTERACTION_DEFINITION: function [(IDENT_LIST)] { FUNCTION_ITEMS } FIELD_DEFINITION: function { SPECIAL_COLOR_FUNCTION } ATTACH_DEFINITION: function { SPLINE } COLLISION_TOGGLE: [INT_MASS_MASS [, INT_MASS_FACE [, INT_CONNECTION_CONNECTION]]] COLLISION_ITEM: stiffness FLOAT | damping FLOAT | friction FLOAT [, FLOAT] GROUP_DEFINITION: group [(INT_GROUP_INDEX)] { TOPOLOGY_ITEMS... } TOPOLOGY_ITEM: mass { V_POSITION, V_VELOCITY, F_RADIUS mass FLOAT | density FLOAT [attach INTEGER] [fixed BOOL] } | connection { INDEX1, INDEX2 [stiffness FLOAT] [damping FLOAT] [length FLOAT] } | face { INDEX1, INDEX2, INDEX3 } | load_file FILE_NAME
Some general parameters can be given in the top level of the mechsim{} section.
The default values are:
method : 1
bounding : 0
gravity : <0, 0, 0>
time_step : 0.1
step_count : 10
Selects the integration method used for solving the equations of movement.
Possible values are:
Method 1 is a first order integration method also known as explicit Euler method. With the differential equations of movement written as:
y being the state of the system (positions and velocities) and the initial conditions y(t0)=y0 the Euler method can be written as:
Method 2 is a second order integration method known as Heun's method. Its formula is:
Method 3 is a fourth order integration method known as the classical Runge-Kutta method:
Selects the bounding method to speed up collision detections.
Possible values are:
The bounding techniques have been implemented by Daniel Jungmann and are in an experimental state. The internal workings as well as the use are likely to change in future versions.
Applies an overall constant gravitational force to all masses.
A vector is expected, the unit is m/s².
Standard earth gravity (with y=up coordinates) is:
gravity <0, -9.81, 0>
With field functions (see Section 2.7.3.1.6, “Field forces”) non constant gravity can be simulated
All simulation methods use discrete time steps for calculating the simulation. There are three parameters to steer this but only two are needed to correctly define the stepping. The formula for calculating the third is:
Step_Count = Time / Time_Step
An optional start_time value allows to specify a starting time different from 0. Changing this can influence the attach and environment function. (see Section 2.7.3.1.7, “Attaching masses” and Section 2.7.3.1.2, “The environments”) Specifying an end_time value instead of time is also possible.
Important | |
---|---|
Using too large time steps can lead to instability in the simulation. MegaPOV will recognize this in most cases and stop simulation with an error message but this does not mean the simulation is correct as long as no error is reported. Simulation results should always be checked for plausibility. |
Environments are shapes the simulated masses are supposed to interact with. Several of them can be created with environment{} blocks.
An environment is defined either by a user defined function or an object. If both are given the function is preferred.
Apart from the default parameters (x, y and z) the function can have a fourth parameter supplying a time index. This way moving environment objects can be simulated.
#declare fn_Env=function(x, y, z, tim) { z-tim } global_settings { ... mechsim { ... environment { function(x, y, z, tim) { fn_Env(x, y, z, tim) } ... } } }
There are three parameters defining the properties of the environment:
stiffness The elasticity parameter of the surface. The unit is N/m or kg/s².
damping Depending on the environment calculation method (see below) this is either a diminishing factor (<1) applied to the mass velocities at each collision or a damping constant (unit kg/s)
friction The friction factor controls the amount of friction during collisions. An optional second parameter, the friction excess value should usually be slightly larger than 1 and causes the friction to occur already slightly above the surface. This can be helpful to obtain realistic results.
There are currently two methods how the environment collisions can be calculated:
Method 1 (MECHSIM_ENV_METHOD_FORCE) is force based. When a mass collides with the environment a force is applied in direction of the function gradient (with function based environments) or the surface normal (with objects). The stiffness, damping and friction parameters influence this force. friction defines the ratio between the tangential force and the normal force.
Method 2 (MECHSIM_ENV_METHOD_IMPACT) is based on impact laws. The velocity is inverted at the surface and diminished by the damping factor in normal direction and by the friction value in tangential direction. stiffness does not have any influence in this case.
Since this method directly modifies the velocity rather than applying forces it should only be used with the first order (Euler) integration method.
With the gradient descent simulation method the method parameter does not have any effect.
The collisions referred to here are not environment collisions but collisions between the simulation elements. Since detecting this kind of collision is quite computationally intensive it is turned off by default.
With three numbers at the beginning of the collision{} section collision can be toggled for mass-mass-collisions, mass-face-collisions and connection-connection-collisions. All these parameters are optional, the meaning of the possible values is:
Internal collisions are always calculated with forces. The same three parameters like in the environment settings can be used to specify the properties
Example 2.11. An example for a complete collision{} section:
global_settings { ... mechsim { ... collision { 2, /* mass-mass collisions between elements of different groups */ 0, /* no mass-face collisions */ 0 /* no connection-connection collisions */ stiffness 20000 damping 4000 friction 0.2, 1.01 } } }
The topology{} section is the central part of the whole simulation settings. Here the simulation elements, their positions and properties, can be defined.
There are three topology items: masses, connections and faces. Each of them has several parameters that can be set.
The mass block defines a point mass. These are the central elements of the simulation. Their movement is calculated by the simulation system.
The mass block contains the following elements:
In addition either the mass (unit: kg) or the density (unit: kg/m³) of the element has to be given. If density is specified the resulting mass is calculated automatically. An optional boolean parameter (fixed) prevents the mass from moving if set to true.
A complete example for a mass definition:
mass { <0, 0, 1>, /* position */ <1, 0, 0>, /* velocity */ 0.1 /* radius */ density 600 // mass 2 // fixed true }
The connection block defines a connection between two point masses. It can have elastic and dissipative properties.
The first two elements of this block are integer numbers specifying the indices of the masses to connect.
There are three optional parameters: The stiffness value specifies the elasticity of the connection (unit N/m or kg/s²). damping the velocity proportional damping factor (unit kg/s). The default value for both of these is zero. The third parameter allows to specify a relaxed length of the connection. If it is not specified the distance of the two masses is used for this property.
A complete example for a connection definition:
global_settings { ... mechsim { ... topology { mass { ... } /* mass with index 0 */ mass { ... } /* mass with index 1 */ connection { 0, /* index of the first mass */ 1 /* index of the second mass */ stiffness 10000 damping 2000 // length 0.5 } ... } } }
The face block defines a triangular face between three point masses. It is used for collision calculations (see Section 2.7.3.1.3, “The collision settings”) and can be useful for generating a mesh from the simulation data for display.
There are three integer numbers in the block, the indices of the masses forming the face.
A complete example for a face definition:
global_settings { ... mechsim { ... topology { mass { ... } /* mass with index 0 */ mass { ... } /* mass with index 1 */ mass { ... } /* mass with index 2 */ face { 0, /* index of the first mass */ 1, /* index of the second mass */ 2 /* index of the third mass */ } ... } } }
Simulation elements can be categorized into groups. The main purpose of this is to speed up collision tests. The group keyword can be followed by an integer number in parentheses to explicitly specify the group. Otherwise the group index is determined automatically.
global_settings { ... mechsim { ... topology { mass { ... } /* these elements are group index 0 */ ... group { mass { ... } /* these elements are group index 1 */ } group { mass { ... } /* these elements are group index 2 */ } group (1) { mass { ... } /* these elements are group index 1 */ } ... } } }
The topology data can be written to and loaded from files. For the format of these files see Section 2.7.3.3, “The simulation data file format”.
save_file can only be added to the main topology{} block. It saves the complete data after the simulation to the specified file.
load_file can be placed anywhere in the topology{} section. If placed in a group the elements in the file are added to that group. Otherwise they are are placed in groups according to group index information in the file.
The same file name can be specified for both loading and saving the data. This is especially useful for animation when the following frame simulation should start with the result of the last frame:
global_settings { ... mechsim { ... topology { load_file "mechsim_data.dat" save_file "mechsim_data.dat" } } }
Masses can be set to exert forces on each other depending on the distance and the position in space. Phenomena like gravity in space and electrostatic fields can be simulated this way.
The interaction{} block can contain one or more user defined functions. Apart from the default parameters (x, y and z) the functions can have a fourth parameter that is used for the distance between the masses. The function return value defines the force exerted on both masses in opposite directions. Positive values mean attractive forces and negative values repulsion.
#declare fn_Force=function(x, y, z, dist) { 1/(dist*dist) } global_settings { ... mechsim { ... interaction { function(x, y, z, dist) { fn_Force(x, y, z, dist) } ... } } }
General field like forces can be simulated using the field{} block. One example for such a field force is gravity although the simulation system has a special parameter for specifying such a simple constant gravity force. Much more complicated fields can be set up using this function.
The field{} block expects a pigment function defining the force components in the different directions. The red component of the pigment for the x direction, the green component for the y direction and blue for z. The mechsim include file contains a macro generating an appropriate pigment function from three float functions.
Example 2.12. Constant downward force in Mechanics simulation
A function for a constant downward force (in y direction) would look like:
#include "mechsim.inc" global_settings { ... mechsim { ... field { function { Vector_Function( function {0}, function {-1}, function {0} ) } ... } } }
Note that in contrast to the gravity parameter the fields define a force and not an acceleration. Large masses will be influenced less than small masses.
Apart from adding the fixed flag to masses and thereby fixing them to a certain position we can also constrain them to a certain predefined movement. Those movements are described with spline functions in the attach{} block.
global_settings { ... mechsim { ... attach { function { spline { linear_spline 0.0, <0,0,0> 0.5, <1,0,0> 1.0, <2,0,0> } } } ... } } }
These functions are automatically numbered starting from zero. To attach a mass to a function the attach parameter has to be set in the mass definition. The following mass is attached to the attach function with the number two:
mass { <0, 0, 1>, <0, 0, 0>, 0.1 density 600 attach 2 }
During the simulation the spline is evaluated at the current time value and the returned vector describes the movement of the attached masses. Note that the spline does not describe an absolute position for the masses, just their movement relative to their starting position. Attaching several masses to the same spline makes them perform a parallel movement.
The whole simulation data can be accessed anywhere in the POV-Script. This is achieved by adding new float/vector functions:
The complete syntax description of this block is:
FLOAT_FUNCTION: ... | mechsim : MECHSIM_ELEMENTS MECHSIM_ELEMENTS: mass_count | connection_count | face_count | mass( INTEGER ) : MASS_FLOAT_ELEMENT | connection( INTEGER ) : CONNECTION_FLOAT_ELEMENT | face( INTEGER ) : FACE_FLOAT_ELEMENT MASS_FLOAT_ELEMENT: radius | mass CONNECTION_FLOAT_ELEMENT: index1 | index2 | length | stiffness | damping FACE_FLOAT_ELEMENT: index1 | index2 | index3 VECTOR_FUNCTION: ... | mechsim : MECHSIM_ELEMENTS MECHSIM_ELEMENTS: mass( INTEGER ) : MASS_VECTOR_ELEMENT MASS_VECTOR_ELEMENT: position | velocity
These elements correspond to those set in the mechsim{} block in global_settings{}. The mass position and velocity are the ones that are modified during simulation. The mass_count connection_count and face_count values are especially useful inside the mechsim{} block to determine the current index:
global_settings { ... mechsim { ... topology { /* part 1 */ mass { ... } mass { ... } connection { ... } ... #declare Start_Mass_Part2=mechsim:mass_count; #declare Start_Connection_Part2=mechsim:connection_count; /* part 2 */ mass { ... } mass { ... } connection { ... } ... } } }
The Start_Mass_Part2 and Start_Connection_Part2 variables can later be used to display the different parts of the simulation in different forms.
The file format used by the load_file and save_file options is a text format compatible to the POV-Ray™ #read and #write directives.
The different fields in the file (referred to as elements here) are separated by commas (,) and each contain either a string, an integer or float value or a vector.
The first element is a four character string ('MSIM') identifying the mechanics simulation file format. The second element is an integer number specifying the subformat of the file. Subformat 2 was used in Sim-POV 0.1.0 and Sim-POV 0.2.0 allows to write subformat 2 and 3.
The main difference is that type 3 files contain the attach index (see Section 2.7.3.1.7, “Attaching masses”) for each mass. In addition the subformat value is followed by a float for the start time in subformat 3. When the simulation data is saved after the simulation the time index at the beginning is increased by the simulation duration. This way environments and attachments are correctly moved during animations. The subformat can be specified with an additional number after the file name string in save_file. The default subformat is 2.
The following three integer numbers are the numbers of masses, connections and faces in the file. After them follows the data of all masses, connections and faces in that order.
For each mass there are the following elements:
For each connection:
For each face:
The files written by MegaPOV contain a line break after the subformat value, the mass count, connection count and face count value and after each mass, connection and face.
Example 2.13. The simulation data file format
A short sample file looks like this:
MSIM, 2, 3, 3, 1, <-2, -2, 0>, <0, 0, 0>, 2.0, 0.05, 0, 0, <2, -2, 0>, <0, 0, 0>, 2.0, 0.05, 0, 0, <0, 2, 1>, <0, 0, 0>, 2.0, 0.05, 0, 0, 0, 1, 0.8, 12000, 6000, 0, 1, 2, 0.8, 12000, 6000, 0, 0, 2, 0.8, 12000, 6000, 0, 0, 1, 2, 0,
Post processing allows manipulation of the color of the pixels after the rendering step is completed.
In the past, post processing of images required some third-party software (such as PhotoShop, Paint Shop Pro, or the GIMP) or older versions of MegaPOV that had implemented a few predefined effects.
MegaPOV 1.1 introduces a more generic approach to the post processing. Instead of being limited to a few predefined effects, access to the content of the rendered image through internal functions is now available for the user. By mixing these functions, any imaginable effect is possible. As an example of using these functions, some basic effects (in the form of macros) are provided with a similar syntax to the postprocessing effects included in older MegaPOV versions.
Post processing data is stored during rendering. This data contains several components: color of the pixel, intersection point, depth, normal - in other words all the information the raytracer receives for each of the pixels. For anti-aliased images only the data from the first ray is gathered. The storage is automatically turned on after the explicit call to one of predefined macros:
#version unofficial megapov 1.1; #include "pprocess.inc" // store data of the color and transparency PP_Init_Alpha_Colors_Outputs() // store data of the intersection point coordinates or <0,0,0> PP_Init_IPoint_Outputs() // store data of the normal at the intersection point or <0,0,0> PP_Init_INormal_Outputs() // store data of the perturbed normal at the intersection point or <0,0,0> PP_Init_PNormal_Outputs() // store the distance between camera and intersection point PP_Init_Depth_Output() // store the uv coordinates at the intersection point PP_Init_UV_Outputs() // allow access to intermediate post processing stages // (color and transparency received from a previous post process stage) PP_Init_PP_Alpha_Colors_Outputs()
Important | |
---|---|
When using post_process { }, do not forget to include the file "pprocess.inc" because this include file is needed to access the internal data. |
Note | |
---|---|
If you do not need to store all the data mentioned in the macros listed above, you can pick one ore more of the dedicated internal functions mentioned further down. For example: store only the red component and the x coordinate of the intersection point for further usage. Check the content of the listed macros in the include file to find how to turn on only specific component storage. |
Macros listed in the previous section enables internal functions with the following syntax:
// functions to access the color components and transparency f_output_red(x,y) f_output_green(x,y) f_output_blue(x,y) f_output_alpha(x,y) // access to the intersection point coordinates f_output_ipoint_x(x,y) f_output_ipoint_y(x,y) f_output_ipoint_z(x,y) // access to the normal vector at the intersection point f_output_inormal_x(x,y) f_output_inormal_y(x,y) f_output_inormal_z(x,y) // access to the perturbed normal vector at the intersection point f_output_pnormal_x(x,y) f_output_pnormal_y(x,y) f_output_pnormal_z(x,y) // access to the distance between camera and intersection point f_output_depth(x,y) // access to the uv coordinates at the intersection point f_output_u(x,y) f_output_v(x,y) // access to color and transparency of an earlier post processing stage f_pp_red(x,y,Ref) f_pp_green(x,y,Ref) f_pp_blue(x,y,Ref) f_pp_alpha(x,y,Ref)
The majority of the listed functions only need x and y parameters. These parameters are the location in the area of the rendered image. Not defined in pixels but in the range <0,1>.
Example 2.14. The internal post process function asking for red color at the middle of image
f_output_red(0.5,0.5)
Note that <0,0> is not the value of the most top-left pixel, but the value at the top left corner of the most top left _pixel_. You have to shift it about <0.5/image_width,0.5/image_size> to hit the center of the most top left pixel. If you are not happy with the need of expressing coordinates in decimal form you can always express them in relation to the image size.
Some of the functions contain an additional Ref parameter. These are functions which refer to the result of the earlier calculated post processing stage. This parameter specifies to which stage we refer: 0 means output of rendering, 1 means output of first post processing, 2 means output of second postprocessing, etc.
Numbering depends on the order of appearence in the sources.
Postprocessing should be defined in the global_settings section of the scene file like this:
global_settings { post_process { function { ... } // calculation of red component function { ... } // calculation of green component function { ... } // calculation of blue component function { ... } // calculation of transparency component [ save_file FILENAME ] } }
Example 2.15. Post processing which does nothing (only duplicate the original image)
global_settings { post_process { function { f_output_red(x,y) } // calculation of red component function { f_output_green(x,y) } // calculation of green component function { f_output_blue(x,y) } // calculation of blue component function { f_output_alpha(x,y) } // calculation of transparency component save_file "duplication.png" } }
The post_process block can appear a few times in the global_settings block. Note that saving to file is optional but only the saved blocks will be calculated. Also note that saving is always done in the same file format as the render output (regardless of the file extension).
Example 2.16. Post processing which turns the rendered image into a gray scale image
#declare F_gray = function(r,g,b){0.297*r + 0.589*g + 0.114*b}; global_settings { post_process { function { F_gray(f_output_red(x,y),f_output_green(x,y),f_output_blue(x,y)) } function { F_gray(f_output_red(x,y),f_output_green(x,y),f_output_blue(x,y)) } function { F_gray(f_output_red(x,y),f_output_green(x,y),f_output_blue(x,y)) } function { f_output_alpha(x,y) } save_file "grayed.png" } }
Because it could be difficult using functions to define your own post processing effects, some macros with user-friendly syntax have been added to the "pprocess.inc" include file. For an overview and some explanation on the parameters, (see Section 3.5.1, “Macros with effects”).