(C++) Metaball Scene Node

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

(C++) Metaball Scene Node

Post by killthesand »

I've created a metaball scene node, not for any particular purpose, just something new to learn. Someone might be able to find some use for it.

Create a scene node:

Code: Select all

MetaballSceneNode *meta = (MetaballSceneNode *)smgr->addSceneNode("MetaballSceneNode", 0);
add metaballs:

Code: Select all

meta->addMetaball(vector3df(0, 0, 0), SColor(255, 255, 255, 255));
and then convert to polygons:

Code: Select all

meta->triangulateVolume();
So far the metaballs can't be individually animated. I don't think it's necessary because creating the actual mesh takes a second or two. Trying to recalculate it every frame sounds like a bad idea to me.

Most of the algorithm was taken from http://local.wasp.uwa.edu.au/~pbourke/g ... source.cpp

* Edit *
Since the code below is annoyingly split apart, I thought I try out one of those free file sharing sites. You can download the 3 files in a zip from http://mihd.net/k4qarpc (the download link is hidden, looks like a title) click on Request Ticket the Download
Last edited by killthesand on Fri May 09, 2008 7:11 pm, edited 2 times in total.
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

Post by killthesand »

and finally here is the code:

MetaballSceneNode.h

Code: Select all

#ifndef MetaballSceneNode_h
#define MetaballSceneNode_h

#include <deque>
using namespace std;

#include <irrlicht.h>
using namespace irr;

using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#pragma comment(lib, "Irrlicht.lib")

class MetaballSceneNodeFactory : public ISceneNodeFactory {
	public:
		MetaballSceneNodeFactory(ISceneManager *mgr);
		virtual ISceneNode *addSceneNode(ESCENE_NODE_TYPE type, ISceneNode *parent = 0);
		virtual ISceneNode *addSceneNode(const c8 *typeName, ISceneNode *parent = 0);
		virtual u32 getCreatableSceneNodeTypeCount() const;
		virtual const c8 *getCreateableSceneNodeTypeName(u32 idx) const;
		virtual ESCENE_NODE_TYPE getCreateableSceneNodeType(u32 idx) const;
		virtual const c8 *getCreateableSceneNodeTypeName(ESCENE_NODE_TYPE type) const;

	private:
		ESCENE_NODE_TYPE getTypeFromName(const c8 *name) const;
		struct SSceneNodeTypePair {
			SSceneNodeTypePair(ESCENE_NODE_TYPE type, const c8 *name) : Type(type), TypeName(name){}
			ESCENE_NODE_TYPE Type;
			stringc TypeName;
		};
		array<SSceneNodeTypePair> SupportedSceneNodeTypes;
		ISceneManager *Manager;
};

class MetaballSceneNode : public ISceneNode {
	public:
		MetaballSceneNode(ISceneManager *mgr, ISceneNode *parent = 0, s32 id = -1);
		virtual void OnRegisterSceneNode();
		virtual void render();

		virtual void addMetaball(vector3df position, SColor color);
		virtual void triangulateVolume();

		virtual void setThreshold(f64 threshold);
		virtual void setBound(f32 bound);
		virtual void setSampleWidth(f32 width);

		virtual const aabbox3d<f32> &getBoundingBox() const;
		virtual u32 getMaterialCount();
		virtual SMaterial &getMaterial(u32 i);
		virtual ESCENE_NODE_TYPE getType() const;

		virtual void serializeAttributes(IAttributes *out, SAttributeReadWriteOptions *options = 0) const;
		virtual void deserializeAttributes(IAttributes *in, SAttributeReadWriteOptions *options = 0);

	protected:
		aabbox3d<f32> Box;
		SMaterial Material;
		array<S3DVertex> Vertices;
		array<u16> Indices;
		deque<vector3df> Balls;
		deque<SColor> Colors;
		f64 Threshold;
		f32 Bound;
		f32 SampleWidth;

		void triangulate(vector3df position, f64 scale);
		f64 calculateValue(vector3df position);
		SColor calculateColor(vector3df position);
		f64 valueFunction(vector3df position, vector3df center);
};

#endif
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

Post by killthesand »

Sorry, the forum keeps timing out while submitting the post. This file will be split apart.

MetaballSceneNode.cpp - Part 1

Code: Select all

#include "MetaballSceneNode.h"

const s32 edgeFlags[256] = {
	0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00, 
	0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90, 
	0x230, 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30, 
	0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0, 
	0x460, 0x569, 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60, 
	0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0, 
	0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x055, 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950, 
	0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc, 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0, 
	0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0, 
	0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x055, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650, 
	0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0, 
	0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x066, 0x76a, 0x663, 0x569, 0x460, 
	0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0, 
	0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x033, 0x339, 0x230, 
	0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190, 
	0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000
};
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

Post by killthesand »

MetaballSceneNode.cpp - Part 2

Code: Select all

const s32 triangleConnections[256][16] = {
	{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
	{3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
	{3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
	{3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1},
	{9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
	{1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
	{9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
	{2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
	{8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
	{9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
	{4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
	{3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1},
	{1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
	{4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1},
	{4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
	{9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
	{1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
	{5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1},
	{2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
	{9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
	{0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
	{2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
	{10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1},
	{4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
	{5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1},
	{5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
	{9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
	{0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1},
	{1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1},
	{10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
	{8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1},
	{2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
	{7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1},
	{9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
	{2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1},
	{11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
	{9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1},
	{5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
	{11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1},
	{11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
	{1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
	{9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1},
	{5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
	{2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
	{0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
	{5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
	{6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1},
	{0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
	{3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1},
	{6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
	{5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
	{1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
	{10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
	{6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1},
	{1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
	{8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1},
	{7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
	{3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
	{5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
	{0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1},
	{9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
	{8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1},
	{5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
	{0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1},
	{6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
	{10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
	{10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1},
	{8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
	{1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1},
	{3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
	{0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
	{10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1},
	{0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
	{3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1},
	{6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
	{9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1},
	{8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
	{3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1},
	{6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1},
	{0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
	{10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1},
	{10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
	{1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1},
	{2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
	{7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1},
	{7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1},
	{2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
	{1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1},
	{11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
	{8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1},
	{0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1},
	{7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
	{10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
	{2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
	{6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
	{7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
	{2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1},
	{1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
	{10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1},
	{10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
	{0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1},
	{7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
	{6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
	{8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1},
	{9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
	{6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1},
	{1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
	{4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1},
	{10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
	{8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1},
	{0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1},
	{1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
	{8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1},
	{10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
	{4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1},
	{10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
	{5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
	{11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
	{9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
	{6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
	{7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1},
	{3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
	{7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
	{9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
	{3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1},
	{6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
	{9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1},
	{1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
	{4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1},
	{7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
	{6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1},
	{3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
	{0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1},
	{6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
	{1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1},
	{0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
	{11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1},
	{6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
	{5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1},
	{9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
	{1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1},
	{1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1},
	{10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
	{0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
	{5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
	{10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
	{11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1},
	{0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
	{9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1},
	{7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
	{2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1},
	{8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
	{9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1},
	{9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
	{1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
	{9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
	{9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1},
	{5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
	{0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1},
	{10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
	{2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1},
	{0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
	{0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1},
	{9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1},
	{5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
	{3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1},
	{5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
	{8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
	{0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1},
	{9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1},
	{0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
	{1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1},
	{3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
	{4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1},
	{9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
	{11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1},
	{11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
	{2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1},
	{9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
	{3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1},
	{1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1},
	{4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
	{4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
	{0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1},
	{3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1},
	{3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
	{0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1},
	{9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1},
	{1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
	{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
};
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

Post by killthesand »

MetaballSceneNode.cpp - Part 3

Code: Select all

const f32 vertexOffsets[8][3] = {
	{0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}, {0, 0, 1}, {1, 0, 1}, {1, 1, 1}, {0, 1, 1}
};

const u32 edgeConnections[12][2] = {
	{0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 5}, {5, 6}, {6, 7}, {7, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7}
};

const f32 edgeDirections[12][3] = {
	{1, 0, 0}, {0, 1, 0}, {-1, 0, 0}, {0, -1, 0}, {1, 0, 0}, {0, 1, 0}, {-1, 0, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}
};

const int METABALLSCENENODE_ID = MAKE_IRR_ID('m','e','t','a');
const char *MetaballSceneNodeTypeName = "MetaballSceneNode";

MetaballSceneNodeFactory::MetaballSceneNodeFactory(ISceneManager *mgr): Manager(mgr) {}

ISceneNode *MetaballSceneNodeFactory::addSceneNode(ESCENE_NODE_TYPE type, ISceneNode *parent) {
	if (!parent)
		parent = Manager->getRootSceneNode();

	if (type == METABALLSCENENODE_ID) {
		MetaballSceneNode *node = new MetaballSceneNode(Manager, parent, -1);
		node->drop();
		return node;
	}

	return 0;
}

ISceneNode *MetaballSceneNodeFactory::addSceneNode(const c8 *typeName, ISceneNode *parent) {
	return addSceneNode(getTypeFromName(typeName), parent);
}

u32 MetaballSceneNodeFactory::getCreatableSceneNodeTypeCount() const {
	return 1;
}

ESCENE_NODE_TYPE MetaballSceneNodeFactory::getCreateableSceneNodeType(u32 idx) const {
	if (idx == 0)
		return (ESCENE_NODE_TYPE)METABALLSCENENODE_ID;

	return ESNT_UNKNOWN;
}

const c8 *MetaballSceneNodeFactory::getCreateableSceneNodeTypeName(u32 idx) const {
	if (idx == 0)
		return MetaballSceneNodeTypeName;

	return 0;
}

const c8 *MetaballSceneNodeFactory::getCreateableSceneNodeTypeName(ESCENE_NODE_TYPE type) const {
	if (type == METABALLSCENENODE_ID)
		return MetaballSceneNodeTypeName;

	return 0;
}

ESCENE_NODE_TYPE MetaballSceneNodeFactory::getTypeFromName(const c8 *name) const {
	if (!strcmp(name, MetaballSceneNodeTypeName))
		return (ESCENE_NODE_TYPE)METABALLSCENENODE_ID;

	return ESNT_UNKNOWN;
}
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

Post by killthesand »

MetaballSceneNode.cpp - Part 4

Code: Select all

MetaballSceneNode::MetaballSceneNode(ISceneManager *mgr, ISceneNode *parent, s32 id) : ISceneNode(parent, mgr, id) {
	Material.Wireframe = false;
	Material.Lighting = false;

	SampleWidth = .125;
	Bound = 2;
	Threshold = 1;
}

void MetaballSceneNode::OnRegisterSceneNode() {
	if (IsVisible)
		SceneManager->registerNodeForRendering(this);

	ISceneNode::OnRegisterSceneNode();
}

void MetaballSceneNode::render() {
	IVideoDriver *driver = SceneManager->getVideoDriver();

	driver->setMaterial(Material);
	driver->setTransform(ETS_WORLD, AbsoluteTransformation);
	driver->drawIndexedTriangleList(Vertices.const_pointer(), Vertices.size(), Indices.const_pointer(), Indices.size() / 3);
}

void MetaballSceneNode::addMetaball(vector3df position, SColor color) {
	Balls.push_back(position);
	Colors.push_back(color);
}

void MetaballSceneNode::triangulateVolume() {
	Vertices.clear();
	Indices.clear();
	Box.reset(vector3df(0, 0, 0));
	for (f32 x = -Bound; x <= Bound; x += SampleWidth)
		for (f32 y = -Bound; y <= Bound; y += SampleWidth)
			for (f32 z = -Bound; z <= Bound; z += SampleWidth)
				triangulate(vector3df(x, y, z), SampleWidth);
}

void MetaballSceneNode::setThreshold(f64 threshold) {
	Threshold = threshold;
}

void MetaballSceneNode::setBound(f32 bound) {
	Bound = bound;
}

void MetaballSceneNode::setSampleWidth(f32 width) {
	SampleWidth = width;
}

const aabbox3d<f32> &MetaballSceneNode::getBoundingBox() const {
	return Box;
}

u32 MetaballSceneNode::getMaterialCount() {
	return 1;
}

SMaterial &MetaballSceneNode::getMaterial(u32 i) {
	return Material;
}   

ESCENE_NODE_TYPE MetaballSceneNode::getType() const {
	return (ESCENE_NODE_TYPE)METABALLSCENENODE_ID;
}

void MetaballSceneNode::serializeAttributes(IAttributes *out, SAttributeReadWriteOptions *options) const {
	out->addString("Name", Name.c_str());
	out->addInt("Id", ID );

	out->addVector3d("Position", getPosition());
	out->addVector3d("Rotation", getRotation());
	out->addVector3d("Scale", getScale());

	out->addBool("Visible", IsVisible);
	out->addEnum("AutomaticCulling", AutomaticCullingState, AutomaticCullingNames);
	out->addInt("DebugDataVisible", DebugDataVisible);
	out->addBool("IsDebugObject", IsDebugObject);

	out->addFloat("Threshold", Threshold);
	out->addFloat("Bound", Bound);
	out->addFloat("SampleWidth", SampleWidth);

	out->addInt("MetaballCount", Balls.size());
	for (u32 i = 0; i < Balls.size(); i++) {
		out->addVector3d("MetaballPosition", Balls[i]);
		out->addColor("MetaballColor", Colors[i]);
	}
}

void MetaballSceneNode::deserializeAttributes(IAttributes *in, SAttributeReadWriteOptions *options) {
   Name = in->getAttributeAsString("Name");
   ID = in->getAttributeAsInt("Id");

   setPosition(in->getAttributeAsVector3d("Position"));
   setRotation(in->getAttributeAsVector3d("Rotation"));
   setScale(in->getAttributeAsVector3d("Scale"));

   IsVisible = in->getAttributeAsBool("Visible");
   AutomaticCullingState = (E_CULLING_TYPE ) in->getAttributeAsEnumeration("AutomaticCulling", AutomaticCullingNames);

   DebugDataVisible = (E_DEBUG_SCENE_TYPE ) in->getAttributeAsInt("DebugDataVisible");
   IsDebugObject = in->getAttributeAsBool("IsDebugObject");

   Threshold = in->getAttributeAsFloat("Threshold");
   Bound = in->getAttributeAsFloat("Bound");
   SampleWidth = in->getAttributeAsFloat("SampleWidth");

   Balls.clear();
   Colors.clear();
   for (u32 i = in->getAttributeAsInt("MetaballCount"); i > 0; i--) {
	   Balls.push_back(in->getAttributeAsVector3d("MetaballPosition"));
	   Colors.push_back(in->getAttributeAsColor("MetaballColor"));
   }

   updateAbsolutePosition();
   triangulateVolume();
}

void MetaballSceneNode::triangulate(vector3df position, f64 scale) {
	s32 flagIndex = 0;
	f64 cubeValues[8];
	for(u32 v = 0; v < 8; v++) {
		cubeValues[v] = calculateValue(vector3df(position.X + vertexOffsets[v][0] * scale, position.Y + vertexOffsets[v][1] * scale, position.Z + vertexOffsets[v][2] * scale));
		if (cubeValues[v] <= Threshold) 
			flagIndex |= 1 << v;
	}

	s32 edgeFlag = edgeFlags[flagIndex];
	if (edgeFlags == 0) 
		return;

	f64 offset;
	vector3df edgeVertices[12];
	vector3df edgeNormals[12];
	for(u32 e = 0; e < 12; e++)
		if (edgeFlag & (1 << e)) {
			offset = (Threshold - cubeValues[edgeConnections[e][0]]) / (cubeValues[edgeConnections[e][1]] - cubeValues[edgeConnections[e][0]]);

			edgeVertices[e].X = position.X + (vertexOffsets[edgeConnections[e][0]][0] + offset * edgeDirections[e][0]) * scale;
			edgeVertices[e].Y = position.Y + (vertexOffsets[edgeConnections[e][0]][1] + offset * edgeDirections[e][1]) * scale;
			edgeVertices[e].Z = position.Z + (vertexOffsets[edgeConnections[e][0]][2] + offset * edgeDirections[e][2]) * scale;

			edgeNormals[e].X = calculateValue(vector3df(edgeVertices[e].X - 0.01, edgeVertices[e].Y, edgeVertices[e].Z)) - calculateValue(vector3df(edgeVertices[e].X + 0.01, edgeVertices[e].Y, edgeVertices[e].Z));
			edgeNormals[e].Y = calculateValue(vector3df(edgeVertices[e].X, edgeVertices[e].Y - 0.01, edgeVertices[e].Z)) - calculateValue(vector3df(edgeVertices[e].X, edgeVertices[e].Y + 0.01, edgeVertices[e].Z));
			edgeNormals[e].Z = calculateValue(vector3df(edgeVertices[e].X, edgeVertices[e].Y, edgeVertices[e].Z - 0.01)) - calculateValue(vector3df(edgeVertices[e].X, edgeVertices[e].Y, edgeVertices[e].Z + 0.01));
		}

	u32 vertexIndex;
	for(u32 t = 0; t < 5; t++) {
		if (triangleConnections[flagIndex][3 * t] < 0)
			break;

		for(u32 v = 0; v < 3; v++) {
			vertexIndex = triangleConnections[flagIndex][3 * t + v];
			Indices.push_back(Vertices.size());
			Vertices.push_back(S3DVertex(edgeVertices[vertexIndex], edgeNormals[vertexIndex], calculateColor(edgeVertices[vertexIndex]), vector2df(0, 0)));
			Box.addInternalPoint(Vertices.getLast().Pos);
		}
	}
}

f64 MetaballSceneNode::calculateValue(vector3df position) {
	f64 value = 0;
	for (u32 i = 0; i < Balls.size(); i++)
		if (Balls[i] != position)
			value += valueFunction(position, Balls[i]);
	return value;
}

SColor MetaballSceneNode::calculateColor(vector3df position) {
	deque<f64> value;
	f64 total = 0;
	f64 max = 0;
	for (u32 i = 0; i < Balls.size(); i++) {
		value.push_back(valueFunction(position, Balls[i]));
		total += value.back();
	}

	vector3di c(0, 0, 0);
	for (u32 i = 0; i < value.size(); i++) {
		c.X += value[i] / total * Colors[i].getRed();
		c.Y += value[i] / total * Colors[i].getGreen();
		c.Z += value[i] / total * Colors[i].getBlue();
	}
		
	return SColor(255, c.X, c.Y, c.Z);
}

f64 MetaballSceneNode::valueFunction(vector3df position, vector3df center) {
	if (position == center)
		return Threshold;
	return 1 / ((position.X - center.X) * (position.X - center.X) + (position.Y - center.Y) * (position.Y - center.Y) + (position.Z - center.Z) * (position.Z - center.Z));
}
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

Post by killthesand »

Main.cpp

Code: Select all

#include <irrlicht.h>
using namespace irr;

using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#pragma comment(lib, "Irrlicht.lib")

#include "MetaballSceneNode.h"

IrrlichtDevice *device = 0;

int main() {
	IrrlichtDevice *device = createDevice(EDT_OPENGL, dimension2d<s32>(720, 480));
	if (device == 0)
		return 1;

	IVideoDriver *driver = device->getVideoDriver();
	ISceneManager *smgr = device->getSceneManager();

	ISceneNodeFactory *metaFactory = new MetaballSceneNodeFactory(smgr);
	smgr->registerSceneNodeFactory(metaFactory);

	ICameraSceneNode *cam = smgr->addCameraSceneNodeFPS();
	cam->setPosition(vector3df(0, 0, -400));

	MetaballSceneNode *meta = (MetaballSceneNode *)smgr->addSceneNode("MetaballSceneNode", 0);
	meta->setSampleWidth(.125);
	meta->setBound(2.25);
	meta->setThreshold(1);

	meta->addMetaball(vector3df(1, -1, 1), SColor(255, 0, 0, 255));
	meta->addMetaball(vector3df(-1, -1, -1), SColor(255, 0, 255, 0));
	meta->addMetaball(vector3df(0, 1, 0), SColor(255, 255, 0, 0));
	meta->triangulateVolume();

	meta->setScale(vector3df(100, 100, 100));
	meta->setRotation(vector3df(0, 45, 0));

	device->getCursorControl()->setVisible(false);
	int lastFPS = -1;
	while(device->run()) {
		driver->beginScene(true, true, SColor(0,200,200,200));
		smgr->drawAll();
		driver->endScene();
	}

	device->drop();
	return 0;
}
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Wicked! :D Give us some screenshots, now!
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

Post by killthesand »

Image
Image
Image
Image
Image
Image
trivtn
Posts: 132
Joined: Tue Jan 17, 2006 12:30 pm
Location: Viet Nam
Contact:

Post by trivtn »

Nice! I'll try. Thank!
There's something is fantastic, there's nothing is absolute.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Looks really nice, and a very clean solution. Maybe you could submit it to the irrExt project?
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

Hey that is pretty cool. Maybe you could possibly talk with Blindside about making a tech demo with his refraction shader for some cool rain effects or something. Although it couldn't be used in a realtime game, it would be a sweet graphics demonstration.
TheQuestion = 2B || !2B
Lekane
Posts: 31
Joined: Thu Jun 01, 2006 7:07 pm

Post by Lekane »

hmmm, i was impressed someone actually coded it, but now with screenshots, i'm breathless! nice job!
Dorth
Posts: 931
Joined: Sat May 26, 2007 11:03 pm

Post by Dorth »

Wow, you got my thumbs up. How good does it look shaded?
killthesand
Posts: 42
Joined: Sat Sep 29, 2007 3:33 am
Contact:

Post by killthesand »

Thanks for the positive feedback! For the moment I am quite finished working on this, but I'm pleased with what was accomplished. I have a lot more to learn about processing triangle mesh data before I can go any further.
Dorth wrote:How good does it look shaded?
ah, that's where the bubble bursts. I don't have materials implemented, just vertex colors. In order to get it working 100%, a better coder than I will have to fix the following:

The algorithm spurts out individual triangles, not a solid mesh. In other words, no two triangles share any vertices. Where two triangles mathematically share an edge, there are 4 vertices instead of just 2.

There is no UV mapping. Every vertex is U = 0 V = 0.

In usual marching cubes fashion, the topology is ridiculous. (Try setting Material.Wireframe = true; in the constructor!) Even if mesh, UVs, and materials were good, any light model applied to the object would look bad. Especially specular highlights would be wavy and choppy instead of round and smooth. Fixing this would require a more advanced triangulation function. One possibility: http://svr-www.eng.cam.ac.uk/reports/sv ... _tr333.pdf

For 110%, store metaball positions and colors using some sort of pointer so they can be individually animated. Then invent an ingenuous way to recalculate the mesh at 60+ fps...
Post Reply