solaris nebula effect

   23929   24   7
User Avatar
Member
15 posts
Joined: March 2010
Offline
Using Houdini, has anyone tried their hand at the Doc Baily nebula effect he used in Solaris, etc?

http://www.imagesavant.com/images-720/flare.720.jpg [imagesavant.com]
http://www.imagesavant.com/images-720/angel.jpg [imagesavant.com]
http://www.imagesavant.com/index3.html [imagesavant.com]


chris

http://toonlets.com [toonlets.com]
User Avatar
Member
225 posts
Joined: July 2005
Offline
Here's an interesting idea I've taken a shot at reimplementing in houdini, with some interesting results. I don't have houdini with me now but you can play around with this for some fun in the meantime

http://www.escapemotions.com/experiments/flame/index.html#top [escapemotions.com]
User Avatar
Member
15 posts
Joined: March 2010
Offline
Yeah, that's exactly what I need. Care to share how it's done?


http://toonlets.com [toonlets.com]
User Avatar
Member
15 posts
Joined: March 2010
Offline
My picture saves are coming up as solid orange.

http://toonlets.com [toonlets.com]
User Avatar
Member
15 posts
Joined: March 2010
Offline
Thanks for posting your interactive flame-thing. It was a help.

Here's my first attempt:

http://toonlets.com/work/tube.jpg [toonlets.com]


chris

http://toonlets.com [toonlets.com]
User Avatar
Member
48 posts
Joined: Sept. 2006
Offline
We have similar system for genereting such pointclouds with Maya, codenamed “Scallop”, but we have plans to reimplement it for Houdini as OpenSource project. Keep in touch.
User Avatar
Member
1145 posts
Joined: July 2005
Offline
You can also do some very simple things like the attached and get interesting results.

Attachments:
flame_tubes.hip (455.0 KB)

“gravity is not a force, it is a boundary layer”
“everything is coincident”
“Love; the state of suspended anticipation.”
User Avatar
Member
15 posts
Joined: March 2010
Offline
JoeMislang
We have similar system for genereting such pointclouds with Maya, codenamed “Scallop”, but we have plans to reimplement it for Houdini as OpenSource project. Keep in touch.

Do you have an rendered examples?

http://toonlets.com [toonlets.com]
User Avatar
Member
48 posts
Joined: Sept. 2006
Offline
Here you are!

Attachments:
scallopsample.zip (1.6 MB)

User Avatar
Member
15 posts
Joined: March 2010
Offline
Here's a variation on my attempt…

Attachments:
bubble.jpg (22.9 KB)


http://toonlets.com [toonlets.com]
User Avatar
Member
48 posts
Joined: Sept. 2006
Offline
How much particles?

our sample contains about ~50M
User Avatar
Member
15 posts
Joined: March 2010
Offline
Only 10k… I was iterating.

http://toonlets.com [toonlets.com]
User Avatar
Member
15 posts
Joined: March 2010
Offline
This is with only 4000 particles driving the sim, but rendering a nurbs surface.

Attachments:
bubble02.jpg (17.1 KB)


http://toonlets.com [toonlets.com]
User Avatar
Member
15 posts
Joined: March 2010
Offline
I double-checked… that particle nebula was on the order of 250,000 particles (not 10k). I was still iterating, but my memory was way off.

http://toonlets.com [toonlets.com]
User Avatar
Member
48 posts
Joined: Sept. 2006
Offline
Hm…. you may generate reduced pointcloud for previewing and spool much more points with gui-less mode, then ask a mantra to render them. 250K is not too much!
User Avatar
Member
48 posts
Joined: Sept. 2006
Offline
Here it is.

#ifdef LINUX
#define DLLEXPORT
#define SIZEOF_VOID_P 8
#else
#define DLLEXPORT __declspec(dllexport)
#endif
#define MAKING_DSO

// CRT
#include <limits.h>
#include <strstream>

#include <iostream>
using namespace std;

// H
#include <UT/UT_DSOVersion.h>

#include <GU/GU_Detail.h>
#include <OBJ/OBJ_Node.h>
#include <SOP/SOP_Node.h>

#include <PRM/PRM_Include.h>
#include <PRM/PRM_SpareData.h>
#include <PRM/PRM_ChoiceList.h>

#include <OP/OP_Operator.h>
#include <OP/OP_OperatorTable.h>

#include <UT/UT_Vector3.h>

class SOP_Scallop :
public SOP_Node
{
public:
SOP_Scallop(OP_Network *net, const char *name, OP_Operator *entry) : SOP_Node(net,name,entry) {};
virtual ~SOP_Scallop() {};

static OP_Node *creator(OP_Network *net, const char *name, OP_Operator *entry);
static PRM_Template templateList;

protected:
virtual OP_ERROR cookMySop (OP_Context &context);
};

static PRM_Name bindnames =
{
PRM_Name(“obj#”, “OBJ Path”),
PRM_Name(“model#”, “Model”),
PRM_Name(“weight#”, “Weight”),
PRM_Name(“color#”, “Color”),
PRM_Name(“daemons”, “Number of Daemons”),
PRM_Name(0)
};

static PRM_Name modelNames =
{
PRM_Name(“linear”, “Linear”),
PRM_Name(“spherical”, “Spherical”),
PRM_Name(“polar”, “Polar”),
PRM_Name(“swirl”, “Swirl”),
PRM_Name(“trig”, “Trigonometric”),
PRM_Name(0)
};

static PRM_ChoiceList modelMenu(PRM_CHOICELIST_SINGLE, modelNames);

static PRM_Template theBindTemplates =
{
PRM_Template(PRM_STRING, PRM_TYPE_DYNAMIC_PATH, 1, &bindnames, 0, 0, 0, 0, &PRM_SpareData:bjGeometryPath),
PRM_Template(PRM_ORD, PRM_Template:RM_EXPORT_MAX, 1,&bindnames, 0, &modelMenu),
PRM_Template(PRM_FLT, 1, &bindnames),
PRM_Template(PRM_RGB, 3, &bindnames),
PRM_Template()
};

static PRM_Default switcherInfo = {
PRM_Default( 2, “Setup”),
PRM_Default( 1, “Daemons”)
};

PRM_Name savePathName(“path”,“Path”);
PRM_Default savePathDef(0,“”);

PRM_Name countName(“count”,“Count”);
PRM_Default countDef(1000,“”);

PRM_Name visibleName(“showpts”,“Show Points”);
PRM_Name visibleSizeName(“ptssz”,“Point Size”);

PRM_Template SOP_Scallop::templateList=
{
PRM_Template(PRM_SWITCHER_EXCLUSIVE,2, &PRMswitcherName, switcherInfo),

// SPOOL SETUP
PRM_Template(PRM_FILE,1,&savePathName,&savePathDef),
PRM_Template(PRM_INT,1,&countName,&countDef),

// DAEMONS
PRM_Template(PRM_MULTITYPE_LIST,
theBindTemplates, 4, &bindnames,
PRMzeroDefaults, 0, &PRM_SpareData::multiStartOffsetOne),

// RECENT
PRM_Template(PRM_TOGGLE,1,&visibleName,PRMoneDefaults),
PRM_Template(PRM_INT,1,&visibleSizeName,PRMtwoDefaults),
PRM_Template()
};

OP_Node *SOP_Scallop::creator(OP_Network *net,const char *name,OP_Operator *entry)
{
return new SOP_Scallop(net, name, entry);
};

struct Methods
{
static void Linear(float*) {};
static void Spherical(float*_P)
{
float Len = sqrt(_P*_P+_P*_P+_P*_P);
if(Len!=0) { _P /= Len; _P /= Len; _P /= Len+_P; };
};
static void Polar(float*_P)
{
float Len = sqrt(_P*_P+_P*_P+_P*_P);
_P = atan2(_P,_P); _P = Len;
};
static void Swirl(float*_P)
{
float Len = sqrt(_P*_P+_P*_P+_P*_P);
_P = Len*cos(Len); _P = Len*sin(Len);
};
static void Trigonometric(float*_P)
{
_P = cos(abs(_P+_P))-abs(sin(_P+_P));
_P = cos(_P);
_P = sin(_P);
};
};

typedef void (*NonLinear)(float*);

struct Daemon
{
NonLinear method;
UT_Matrix4 xform;
float c;
float weight;
float range;
bool Transform(float w, UT_Vector3& P, float* C);
Daemon() : method(Methods::Linear) { range=0; range=0; };
};

bool Daemon::Transform(float w, UT_Vector3& P, float* C)
{
if(w<range) return false;
if(w>=range) return false;

P = P*xform;

method(P.vec);

C=C+0.333*(c-C);
C=C+0.333*(c-C);
C=C+0.333*(c-C);

return true;
};

OP_ERROR SOP_Scallop::cookMySop(OP_Context &context)
{
//OP_Node::flags().timeDep = 1;

float now = context.getTime();

gdp->clearAndDestroy();

bool showPts = (evalInt(“showpts”,0,now)!=0);

if(showPts)
{
float sz = evalInt(“ptssz”,0,now);
if(sz > 0)
{
float one = 1.0f;
gdp->addAttrib(“showpoints”,4,GB_ATTRIB_FLOAT,&one);
gdp->addAttrib(“revealsize”,4,GB_ATTRIB_FLOAT,&sz);
};
};

int cnt = evalInt(“daemons”, 0, now);

//QList<Daemon> daemons;

Daemon* daemons=new Daemon;

float weights = 0;

int totd=0;

for(int i=1;i<=cnt;i++)
{
Daemon& d = daemons;

UT_String path = “”;
evalStringInst(“obj#”, &i, path, 0, now);

if(path == “”) continue;

SOP_Node* node = getSOPNode(path);

OBJ_Node* obj = dynamic_cast<OBJ_Node*>(node->getParent());

if(obj == NULL) continue;

addExtraInput(obj, OP_INTEREST_DATA);

d.xform = obj->getWorldTransform(context);

d.weight = evalFloatInst(“weight#”,&i,0,now);

d.c = evalFloatInst(“color#”,&i,0,now);
d.c = evalFloatInst(“color#”,&i,1,now);
d.c = evalFloatInst(“color#”,&i,2,now);

int mth = evalIntInst(“model#”,&i,0,now);

switch(mth)
{
case 1:
d.method = Methods:pherical;
break;
case 2:
d.method = Methods:olar;
break;
case 3:
d.method = Methods:wirl;
break;
case 4:
d.method = Methods::Trigonometric;
break;
case 0:
default:
d.method = Methods::Linear;
};

weights+=d.weight;
totd++;
};

if(totd == 0)
{
delete daemons;
return error();
}

float base = 0.0;
for(int i=0;i<totd;i++)
{
Daemon& d = daemons;
d.range=base;
d.range = base+d.weight/weights;
base=d.range;
};

int total = evalInt(“count”,0,now);

int dt = gdp->addDiffuseAttribute(GEO_POINT_DICT);

UT_Vector3 current(0,0,0);
float C = { 0,0,0 };

srand(0);

for(int i=-50;i<total;i++)
{
bool ok = false;

float w = double(rand())/double(RAND_MAX);

for(int j=0;j<totd;j++)
{
ok = daemons.Transform(w,current,C);
if(ok) break;
};

if(i<0) continue;

if(ok)
{
GEO_Point* p = gdp->appendPoint();
p->setPos(current);

float* Cd=p->castAttribData<float>(dt);
memcpy(Cd,C,12);
};
};

delete daemons;

return error();
}

void newSopOperator(OP_OperatorTable *table)
{
table->addOperator(new OP_Operator(
“hdk_scallop”,“Scallop”,
SOP_Scallop::creator,SOP_Scallop::templateList,
0,1));
}


We reimplemented our tool at Houdini, excluding Pixar's pointcloud export, which is produced by another node. You may play with different Non-linear formulas, which may be plugged easily. I don't think, that using CVEX as non-linear kernel will allow to build pointclouds very fast, but you may add such features too. Good luck!
Sample scene attached.

Attachments:
scallop.hipnc (213.4 KB)

User Avatar
Member
75 posts
Joined:
Offline
This is pretty awesome Joe, thanks , one thing, compiling this I'm getting an error in the “Trigonometric” function, it appears that the absolute functions in that are erroring

“error: call of overloaded ‘abs(float)’ is ambiguous”
“error: call of overloaded ‘abs(double)’ is ambiguous”

commenting out that one option makes it all happy.

another question tho, is how do you control the scale of the functions?

I've tried making a new one with two nulls and can't get it to stay in a reasonable world size as in your example..

thanks for any hints..

-johnc
User Avatar
Member
48 posts
Joined: Sept. 2006
Offline
1. Simplest hints is to keep scaling at one of daemon less than 1.0. Some kind of non-linears make set limited, but scaling more than 1 blows pointcloud up in most of cases.
2. You may write fabs() infstead of abs()
3. I implemented VEX-based non-linear parts, these days I'll publish such version. It has a lot of additional features too.

Good luck and thank you!
User Avatar
Member
160 posts
Joined:
Offline
toonlets
This is with only 4000 particles driving the sim, but rendering a nurbs surface.

but…i can't understand what you said.
could you post a source file or explain it again?
User Avatar
Member
606 posts
Joined: May 2007
Offline
As a variation on the theme, i once tried rendering some flame fractal images and then stacked them to form a volume: http://forums.odforce.net/index.php?/topic/8471-eetus-lab/page__view__findpost__p__56247 [forums.odforce.net]

eetu.
  • Quick Links