利用者:Sionix/SummerOfCode2006/Clouds

提供: wiki
移動先: 案内検索

Clouds

[ Back to the project ] [ http://sionix.pbwiki.com/SummerOfCode2006_Screenshots ]


How it works and User interface

Cloud building is based on modelling cloud shapes via closed meshes.

Basic steps are:

1. Create cloud shape

2. Fill shape with particles


Usage examples

Go to tutorials

Programming interface

Integration into pipeline

Cloud part of SkyGen is integrated into three Blender areas:

  • 3D browser
  • UI
  • convertblender

3D browser is provided with draw_cloud function that displays draft view of the cloud.

void draw_cloud(Object *ob, CloudEff *clf)

draw_cloud:

@param[in] ob Mesh object.
@param[in] clf Cloud effect, attached to the mesh.

UI - buttons_object is provided with cloud panel

void object_panel_clouds(Object *ob)

object_panel_clouds:

@param[in] ob Mesh object.

convertblender is the place where all cloud conversion processes are playing their roles. render_cloud converts CloudEff to the particle set.

void render_cloud(Render *re, Object *ob, CloudEff *clf)

render_cloud:

@param[in] re Main Render database.
@param[in] ob Mesh object with cloud.
@param[in] clf Cloud effect attached to the mesh.

Objects and relations

DNA objects

The following structure represents a single cloud object attached to the mesh. It behaves almost the same as PartEff.

First fields are for general effect purposes.

typedef struct CloudEff {
	struct CloudEff *next, *prev;
	short type, flag, buttype, stype, vertgroup, userjit;

Following are for particle control.

	int totpart, totkey, seed;
	float imat[4][4];	

Next fields are pure cloud-specific:

	// Cell size in world metrics.
	float cell_size;
	// Possibilities for vertical dissolving.
	float pos_solid, pos_vapor, pos_none;	
	// Particle density at top and bottom layers.
	float dens_top, dens_bottom;			
	// Scattering params.	
	float scat_start, scat_end, scat_width;	
	// Texture mapping type and texture id.
	short eff_type, tex_id;
	// Blur multiplicitier.
	short blur_cnt, pad1;
	// Build check - mesh "hash" value based on geometry.
	float build_check; 

Last ones represent particle data itself.

	Particle *keys;
	struct Group *group;
	
} CloudEff;

Interface functions

Library C interface functions for using in other Blender modules.

void BSG_prepareCloudParticles(struct Object *ob, struct Object *camera, 
	struct World *wrld, struct CloudEff *clf, short stages);

BSG_prepareCloudParticles:

@param[in] ob Mesh object - cloud shape.
@param[in] camera Current scene camera.
@param[in] wrld Current World object.
@param[in, out] clf Cloud effect object to be processed.
@param[in] stages Build stages to perform.

Flags to define cloud build stages:

// Perform only creation and arrangement step.
#define BUILD_STAGES_BUILD			1
// Perform light tracing and setup particles colors.
#define BUILD_STAGES_LIT			2
// Perform all stages.
#define BUILD_STAGES_ALL			0xff

Auxiliary templates

Ref<T> - Class-holder for smart pointers system. Used for automatic control for object destruction.

Array<T> - Helper dynamic array class, similar to STL's.

Auxiliary mathematics

Classes for geometry calculations.

ConvexMesh class provides functionality for mesh processing.

Note 1: 'ConvexMesh' name is not fully correct now, class does not represents a convex mesh.

Note 2: There is some rudimentary functionality, that was used during several implementation tests and is not deleted while (I am not including TrgOctree class into this description, because it is not used in the pipeline now)

class ConvexMesh
{
public:
	ConvexMesh();

	void BuildMesh(TArray<Vect3f> *new_verts, float *verts, 
		unsigned int *trgs, int numv, int numt);
	bool PointContains(const Vect3f &p);
	void GetAABB(Vect3f &vmin, Vect3f &vmax);
	inline Vect3f GetCenter();

	const ConvexMesh &operator =(const ConvexMesh &cvm);

	static void SplitToConvexMeshes(TArray<ConvexMesh> &cvms, float *_verts, 
		unsigned int *_trgs, int _num_verts, int _num_trgs, 
		bool only_closed_sep = false);

	void GetOwnData(TArray<float> &v, TArray<unsigned int> &t);

	inline float *Vertices();
	inline unsigned int *Triangles();
	inline int VerticesLength();
	inline int TrianglesLength();

	int GetIntersectionsCount(const Vect3f &sp, const Vect3f &ep);

protected:
	static void BuildNeighbourGraph();
	static int TraceNeighbour(int cur, int set_val);
	static void TestAndGetConvex(TArray<ConvexMesh> &cvms, 
		TArray<Vect3f> *new_verts, int cur_marker, int mark_len);
	static void TraceConvex(TArray<int> &conv_mark_trgs, 
		TArray<int> &border_trgs, int curt, int cur_marker);

private:
	Ref<TArray<Vect3f> > m_verts;
	TArray<unsigned int> m_trgs;
	TArray<Vect3f> m_normals;
	Vect3f m_center;

	Ref<TrgOctree> m_octree;

	// Temp data
	static float *verts;
	static unsigned int *trgs;
	static int num_verts;
	static int num_trgs;
	static TArray<int> neigh_trgs;
	static TArray<int> mark_trgs;
};

Public methods:


/// Default constructor.
ConvexMesh::ConvexMesh()

/// Assign vertex and triangles data to the object.
/// @param[in, out] new_verts Pointer to the vertex cache - shared
///    between several ConvexMesh objects parent data.
/// @param[in] verts Pointer to the vertices data - length is 3 * numv.
/// @param[in] trgs Pointer to the triangles data - length is numt.
/// @param[in] numv Number of vertices.
/// @param[in] numt Number of triangles * 3.
void ConvexMesh::BuildMesh(TArray<Vect3f> *new_verts, float *verts, 
	unsigned int *trgs, int numv, int numt)

/// Detect whether convex object contains a point.
/// @param[in] p A point.
/// @return True if point is inside of a convex object.
bool ConvexMesh::PointContains(const Vect3f &p)

/// Get axis aligned bounding box for the object.
/// @param[out] vmin Lower-left-near corner's coordinates.
/// @param[out] vmax Upper-right-far corner's coordinates.
void ConvexMesh::GetAABB(Vect3f &vmin, Vect3f &vmax)

/// Get object's center of mass.
/// @return Center location.
Vect3f ConvexMesh::GetCenter()

/// Assignment operator.
/// @param[in] cvm Object to copy from.
/// @return Constant reference to this object.
const ConvexMesh &ConvexMesh::operator =(const ConvexMesh &cvm)

/// The main function. Constructs array of ConvexMeshes from initial geometry
/// data.
/// @param[out] cvms Resulting array of ConvexMesh objects.
/// @param[in] _verts Pointer to vertices data, length is _num_verts * 3
/// @param[in] _trgs Pointer to triangles data.
/// @param[in] _num_verts Number of vertices.
/// @param[in] _num_trgs Number of triangles * 3.
/// @param[in] only_closed_sep Split only by closed parts.
static void ConvexMesh::SplitToConvexMeshes(TArray<ConvexMesh> &cvms, float *_verts, 
	unsigned int *_trgs, int _num_verts, int _num_trgs, 
	bool only_closed_sep)

/// Get geometry data.
/// @param[out] v Vertices.
/// @param[out] t Triangles.
void ConvexMesh::GetOwnData(TArray<float> &v, TArray<unsigned int> &t)

/// Quick access to data.
float *ConvexMesh::Vertices()
unsigned int *ConvexMesh::Triangles()
int ConvexMesh::VerticesLength()
int ConvexMesh::TrianglesLength()

/// Calculate ConvexMesh vs segmet intersections count.
/// @param[in] sp Segment start point.
/// @param[in] ep Segment end point.
/// @return Count of intersections.
int ConvexMesh::GetIntersectionsCount(const Vect3f &sp, const Vect3f &ep)



Class CellBox provides voxelization functionality.

It has three-dimensional matrix to hold particles' ids.


class CellBox
{
public:
	CellBox();
	~CellBox();

	bool Allocate(int _x, int _y, int _z);
	void Clear();
	void Set(int v);
	inline int &operator ()(int i, int j, int k);
	inline float &Height(int i, int j);

	inline int X();
	inline int Y();
	inline int Z();
	inline int DataSize();

private:
	int *data;
	float *height;
	int x, y, z;
};

Methods description:

/// Default constructor.
CellBox::CellBox()

/// Destructor.
~CellBox::CellBox()

/// Allocate memory for a cellbox with given dimensions.
/// @param[in] _x Size by X axis.
/// @param[in] _y Size by Y axis.
/// @param[in] _z Size by Z axis.
/// @return True if allocation succeeded.
bool CellBox::Allocate(int _x, int _y, int _z)

/// Clear data, free memory.
void CellBox::Clear()

/// Set all the elements to given value.
/// @param[in] v Value to set.
void CellBox::Set(int v);

/// Get an access to the specified cell.
/// @param[in] i Coordinate by X axis.
/// @param[in] j Coordinate by Y axis.
/// @param[in] k Coordinate by Z axis.
/// @return Reference to element.
int &CellBox::operator ()(int i, int j, int k)

/// Get cellbox height (by Z axis) in range [0; 1].
/// @param[in] i Coordinate by X axis.
/// @param[in] j Coordinate by Y axis.
/// @return Reference to height value.
float &CellBox::Height(int i, int j)

/// Get cellbox's sizes.
int CellBox::X()
int CellBox::Y()
int CellBox::Z()
int CellBox::DataSize()

Cloud engine

Class CloudEngine is a main class in Cloud modelling system. Used for forming and maintaining single scene cloud object (CloudEff).

class CloudEngine
{
public:
	CloudEngine();
	~CloudEngine();

public:
	struct Particle
	{
		Vect3f v;
		float a, r, g, b;
		float size;
	};

	struct ScatParams
	{
		enum Type
		{
			LINEAR = 0,		
			QUAD = 1,		
			POLY_05 = 2		
		};

		Type type;
		float a, b, c;
		float width;
	};

	enum HorMapType  // bits
	{
		HEIGHT = 1,
		POSSIBILITY = 2
	};

public:
	// Get cell size
	inline float &CellSize();
	// Get result particles count
	inline int NumData();
	// Get result particles positions
	inline Particle *GetData();

	inline ScatParams &GetScatParams();

	// Set proper cell size before call
	inline void SetBlurFactor(float val);

	// Arrange particles inside of mesh.
	void BuildParticles(float *verts, unsigned int *trgs, 
		int num_verts, int num_trgs);
	// Rebuild particles from array.
	void RebuildParticles(const TArray<Vect3f> &parts);
	// Remove invisible particles.
	void ClearupParticles();
	// Apply light settings to shade particles.
	void ApplyLighting(const Vect3f &dir, const Vect3f &view_dir, 
		const Vect3f &color, 
		const Vect3f &back_color, const Vect3f &sun_color);
	// Dissolve particles vertically.
	void DissolveVerticalLayers(const ScatParams &pps, 
		const ScatParams &height_density);
	// Apply height map.
	void ApplyHorDissolveMap(const ScatParams &col, unsigned int *cmap, 
		short map_w, short map_h, unsigned int type);

protected:
	void ClearData();

	float TraceRayFromCell(const Vect3f &dir, int i, int j, int k);
	void TraceCollectFromCell(TArray<Vect3f> &res, const Vect3f &dir, 
		int i, int j, int k);
	float Scattering(float dist, const ScatParams &sp);

	float CalcDensity(int i, int j, int k);
	float GetDensity(int imax, int i, int j, int k);
	float DensityWeightFunc(int di, int dj, int dk);
	float DensityFieldFunc(float distr, float maxr);

private:
	// Cell size in world units
	float m_cell_size;
	// Max radius used in density calculations
	float m_max_rad;
	// Particles
	TArray<Particle> m_parts;
	// AABB
	Vect3f bbmin, bbmax;
	CellBox cell_box;
	ScatParams scat_params;

	// Working array (for speedup)
	TArray<float> part_density;
};

Public functionality:


/// Constructor.
CloudEngine::CloudEngine()

/// Destructor.
CloudEngine::~CloudEngine()

/// Get cell size member.
/// @return Reference to cellsize member.
float &CloudEngine::CellSize()

/// Get result particles count.
/// @return Particles count.
int CloudEngine::NumData()

/// Get result particles positions.
/// @return Pointer to the result data.
Particle *CloudEngine::GetData()

/// Get access to scattering params.
/// @return Reference to scat_params member.
ScatParams &CloudEngine::GetScatParams()

/// Set blur multiplicier. 
/// Note: Set proper cell size before call.
/// @param[in] val New value.
void CloudEngine::SetBlurFactor(float val)

/// Arrange particles inside of mesh. 
/// @param[in] verts Mesh vertices.
/// @param[in] trgs Mesh triangles.
/// @param[in] num_verts Vertices count.
/// @param[in] num_trgs Triangles count * 3.
void CloudEngine::BuildParticles(float *verts, unsigned int *trgs, 
	int num_verts, int num_trgs)

/// Rebuild particles from array. Avoid full list rebuild.
/// @param[in] parts Particles positions.
void CloudEngine::RebuildParticles(const TArray<Vect3f> &parts)

/// Remove invisible particles.
void CloudEngine::ClearupParticles();

/// Apply light settings to shade particles.
/// @param[in] dir Direction to the sun.
/// @param[in] view_dir Current observer's viewing direction.
/// @param[in] color Cloud color.
/// @param[in] back_color Background color.
/// @param[in] sun_color Sun color.
void CloudEngine::ApplyLighting(const Vect3f &dir, const Vect3f &view_dir, 
	const Vect3f &color, const Vect3f &back_color, const Vect3f &sun_color)

/// Dissolve particles vertically.
/// @param[in] pps Scattering params.
/// @param[in] height_density Params for height density.
void CloudEngine::DissolveVerticalLayers(const ScatParams &pps, 
	const ScatParams &height_density)

/// Apply height map.
/// @param[in] col Scattering for color.
/// @param[in] cmap Color map.
/// @param[in] map_w Map width.
/// @param[in] map_h Map height.
/// @param[in] type Map type (HEIGHT or POSSIBILITY).
void CloudEngine::ApplyHorDissolveMap(const ScatParams &col, unsigned int *cmap, 
	short map_w, short map_h, unsigned int type)

Folders structure

soc-blender/
   projectfiles_vc7/
      blender/
         BSG_SkyGen/
            BSG_SkyGen.vcproj
   source/
      blender/
         BSG_SkyGen/
            BSG_SkyGen.h       // Interface header
            intern/
               BSG_SkyGen.cpp  // Interface functions implementation

               // Common modules
               sky_math.h          // Auxiliary math
               sky_math.cpp 

               ref.h               // Auxiliary templates
               array.h

               // Cloud module
               CloudEngine.h
               CloudEngine.cpp

               ...