void co_Line(const LWCustomObjAccess *cobjAcc, LWDVector p0, LWDVector p1, int csys) { LWDVector h1,h0; VCPY(h0,p0); VCPY(h1,p1); cobjAcc->line(cobjAcc->dispData, h0,h1,csys); }
double Atmosphere::evalTexture( LWMicropol *mp, double pos[ 3 ], double stride, double col[ 4 ], LWTextureID txtr ) { VCPY( mp->oPos, pos ); VCPY( mp->wPos, pos ); mp->spotSize = 0.3333 * stride; return txtrf->evaluate( txtr, mp, col ); }
double HUD_Transform(LWViewportInfo *ViewGlobal, int view, Matrix xf) { double z, mat[9]; z = HUD_Depth(ViewGlobal, view); ViewGlobal->xfrm(view, mat); VCPY(xf[0], mat); VCPY(xf[1], &(mat[3]) ); VCPY(xf[2], &(mat[6]) ); VSCL(xf[0],z); VSCL(xf[1],z); VSCL(xf[2],z); return z; }
Activate( long version, GlobalFunc *global, LWMeshEditTool *local, void *serverData ) { sqData *tool; if ( version != LWMESHEDITTOOL_VERSION ) return AFUNC_BADVERSION; xpanf = global( LWXPANELFUNCS_GLOBAL, GFUSE_TRANSIENT ); if ( !xpanf ) return AFUNC_BADGLOBAL; tool = calloc( 1, sizeof( sqData )); if ( !tool ) return AFUNC_OK; tool->nsides = nsides; tool->nsegments = nsegments; tool->shape = shape; tool->axis = axis; tool->bf1 = bf1; tool->bf2 = bf2; tool->diam = rad[ 3 ]; tool->update = LWT_TEST_NOTHING; tool->active = 0; VCPY( tool->org, org ); VCPY_F( tool->center, org ); VCPY( tool->rad, rad ); local->instance = tool; local->tool->done = SuperQ_Done; local->tool->help = SuperQ_Help; local->tool->count = SuperQ_Count; local->tool->handle = SuperQ_Handle; local->tool->adjust = SuperQ_Adjust; local->tool->start = SuperQ_Start; local->tool->draw = SuperQ_Draw; local->tool->dirty = SuperQ_Dirty; local->tool->event = SuperQ_Event; local->tool->panel = SuperQ_Panel; local->build = SuperQ_Build; local->test = SuperQ_Test; local->end = SuperQ_End; return AFUNC_OK; }
// transform pixel point into world space in place void HUD_Point(LWViewportInfo *ViewGlobal, const LWCustomObjAccess *cob, Matrix m, LWDVector pt) { LWDVector p; VCPY(p,pt); MatrixApply(pt, m,p); HUDPosition(ViewGlobal, cob->view, p, cob->viewDir); VADD(pt, p); }
static int SuperQ_Handle( sqData *tool, LWToolEvent *event, int handle, LWDVector pos ) { if ( handle <= 3 ) VCPY( pos, tool->top[ handle ] ); else if ( handle <= 7 ) VCPY( pos, tool->bot[ handle - 4 ] ); else if ( handle == 8 ) VCPY( pos, tool->org ); else if ( handle == 9 ) VCPY( pos, tool->holex ); else if ( handle == 10 ) VCPY( pos, tool->holez ); /* The center crosshair and the hole size handle will overlap in some views. Give the center handle a higher priority. */ return handle == 8 ? 2 : 1; }
// Draw pixel-space box void HUD_Box(LWViewportInfo *ViewGlobal, const LWCustomObjAccess *cob, Matrix m, LWDVector corn, double w, double h, int flags) { LWDVector a,b,c,p, home; VCPY(b, corn); b[0] += w; VCPY(a, b); b[1] -= h; VCPY(c, corn); c[1] -= h; VCPY(p,a); MatrixApply(a, m,p); VCPY(p,b); MatrixApply(b, m,p); VCPY(p,c); MatrixApply(c, m,p); MatrixApply(p, m,corn); HUDPosition(ViewGlobal, cob->view, home, cob->viewDir); VADD(a, home); VADD(b, home); VADD(c, home); VADD(p, home); cob->line(cob->dispData, p, a, LWCSYS_WORLD); cob->line(cob->dispData, a, b, LWCSYS_WORLD); cob->line(cob->dispData, b, c, LWCSYS_WORLD); cob->line(cob->dispData, c, p, LWCSYS_WORLD); if(flags&HUDF_FILL) { cob->triangle(cob->dispData, p, a, b, LWCSYS_WORLD); cob->triangle(cob->dispData, c, p, b, LWCSYS_WORLD); } }
/** * Co-ordinate space transformation: From World to Local space of item. * * @param iteminfo LWItemInfo pointer * @param id Item * @param time Evaluation time * @param wpos Incoming World position * @param localPos Localized position */ void LWMAT_getLocalPos(LWItemInfo *iteminfo, LWItemID local, double time, LWDVector wpos, LWDVector localPos) { LWFVector temp, tempPos; LWFMatrix4 m, inv; if(iteminfo->parent(local)) { // Construct matrix(based on hierarchy of object) and invert LWMAT_identity4(m); LWMAT_getTransform(iteminfo, iteminfo->parent(local), time, m); LWMAT_inverse4(m, inv); // Transform the world position of the target into the local co-ordinate space. VCPY(temp, wpos); LWMAT_transformp(temp, inv, tempPos); VCPY(localPos, tempPos); } else { // No need to transform world co-ordinates into local if there is no hierarchy VCPY(localPos, wpos); } }
static int SuperQ_Start( sqData *tool, LWToolEvent *event ) { if ( !tool->active ) tool->active = 1; VCPY( tool->org, event->posSnap ); VCPY_F( tool->center, event->posSnap ); if ( event->portAxis >= 0 ) tool->axis = event->portAxis; setBoxCorners( tool ); return 0; }
/** * Co-ordinate space transformation: From World to Local space of item. * * @param iteminfo LWItemInfo pointer * @param id Item * @param time Evaluation time * @param wrot Incoming world-space rotation * @param localRot Result in Euler form */ void LWMAT_getLocalRot(LWItemInfo *iteminfo, LWItemID local, double time, LWDVector wrot, LWDVector localRot) { LWFMatrix4 m; VSET3(localRot, 0.0, 0.0, 0.0); if(iteminfo->parent(local)) { LWMAT_identity4(m); LWMAT_getRotate(wrot, m); LWMAT_getLocalRot2(iteminfo, local, time, wrot, m, localRot); } else { VCPY(localRot, wrot); } }
LWXPRefreshCode Atmosphere::DataSet (unsigned int vid, void *value) { double *d = ( double * ) value; int *i = ( int * ) value; switch ( vid ) { case ID_MARCH: march = *i; return LWXPRC_DFLT; case ID_HI: hi = *d; return LWXPRC_DFLT; case ID_LO: lo = *d; return LWXPRC_DFLT; case ID_FA: fa = *d; return LWXPRC_DFLT; case ID_LUM: lum = *d; return LWXPRC_DFLT; case ID_OPA: opa = *d; return LWXPRC_DFLT; case ID_DEN: den = *d; return LWXPRC_DFLT; case ID_BCK: bck = *i; return LWXPRC_DFLT; case ID_RES: res = *i; return LWXPRC_DFLT; case ID_TXTR: useTxtr = *i; return LWXPRC_DFLT; case ID_COL: VCPY( col, d ); return LWXPRC_DFLT; default: return LWXPRC_NONE; } }
void HUD_Line(LWViewportInfo *ViewGlobal, const LWCustomObjAccess *cob, Matrix m, LWDVector corn, double w, int flags) { LWDVector a,b,c,p, home; VCPY(b, corn); VCPY(a, b); b[0] += w; VCPY(p,a); MatrixApply(a, m,p); VCPY(p,b); MatrixApply(b, m,p); if(flags&HUDF_FILL) { VCPY(c, corn); c[0]+= 1; c[1]-= 1; c[2]+=1; VCPY(p, c); p[0] += w; VCPY(home,c); MatrixApply(c, m,home); VCPY(home,p); MatrixApply(p, m,home); } HUDPosition(ViewGlobal, cob->view, home, cob->viewDir); VADD(a, home); VADD(b, home); cob->line(cob->dispData, a, b, LWCSYS_WORLD); if(flags&HUDF_FILL) { float shad[4] = {0, 0, 0, 0.5f}; cob->setColor(cob->dispData, shad); // dangerous side-effect, leaves color changed VADD(c, home); VADD(p, home); cob->line(cob->dispData, c, p, LWCSYS_WORLD); } }
/** * Co-ordinate space transformation: From World to Local space of item. * * @param iteminfo LWItemInfo pointer * @param id Item * @param time Evaluation time * @param wrot Incoming world-space rotation * @param localRot Result in Euler form * @param m Result in Matrix form */ void LWMAT_getLocalRot2(LWItemInfo *iteminfo, LWItemID local, double time, LWDVector wrot, LWFMatrix4 m, LWDVector localRot) { LWFMatrix4 m2, inv, mResult; VSET3(localRot, 0.0, 0.0, 0.0); if(iteminfo->parent(local)) { // Target's ROTATION in CHILD-SPACE LWMAT_identity4(m2); LWMAT_identity4(inv); LWMAT_identity4(mResult); LWMAT_getRotations(iteminfo, iteminfo->parent(local), time, m2); LWMAT_inverse4(m2, inv); LWMAT_matmul4(m, inv, mResult); LWMAT_getEuler(mResult, localRot); } else { VCPY(localRot, wrot); } }
/** * Co-ordinate space transformation: From World to Local space of item. * * @param iteminfo LWItemInfo pointer * @param id Item * @param time Evaluation time * @param wscale Incoming world-space scale * @param localScale Scale in local-space */ void LWMAT_getLocalScale(LWItemInfo *iteminfo, LWItemID local, double time, LWDVector wscale, LWDVector localScale) { LWFMatrix4 m, m2, inv, mResult; VSET3(localScale, 0.0, 0.0, 0.0); if(iteminfo->parent(local)) { // World Scale in local space LWMAT_identity4(m2); LWMAT_identity4(inv); LWMAT_identity4(mResult); LWMAT_getScales(iteminfo, iteminfo->parent(local), time, m2); LWMAT_inverse4(m2, inv); LWMAT_matmul4(m, inv, mResult); LWMAT_getScale(m, wscale); } else { VCPY(localScale, wscale); } }
void co_FillRect(const LWCustomObjAccess *cobjAcc, double pos[3], double w, double h, int csys, int axis) { double dx,dy,stp[3],endp[3],crn[3],z; int axx,axy; z = pos[axis]; axx = xax[axis]; axy = yax[axis]; dx = 0.5*w; dy = 0.5*h; stp[axis] = endp[axis] = z; stp[axx] = pos[axx] - dx; stp[axy] = pos[axy] + dy; endp[axx] = pos[axx] + dx; endp[axy] = pos[axy] - dy; VCPY(crn,stp); crn[axx] = endp[axx]; (*cobjAcc->triangle)(cobjAcc->dispData, stp,crn,endp,csys); crn[axx] = stp[axx]; crn[axy] = endp[axy]; (*cobjAcc->triangle)(cobjAcc->dispData, stp,crn,endp,csys); }
void setBoxCorners( sqData *tool ) { int x, y, z, i; y = tool->axis; x = xax[ tool->axis ]; z = zax[ tool->axis ]; VCPY( tool->top[ 0 ], tool->center ); VCPY( tool->bot[ 0 ], tool->center ); tool->top[ 0 ][ y ] += ( float )( tool->rad[ y ] ); tool->bot[ 0 ][ y ] -= ( float )( tool->rad[ y ] ); for ( i = 1; i < 4; i++ ) { VCPY( tool->top[ i ], tool->top[ 0 ] ); VCPY( tool->bot[ i ], tool->bot[ 0 ] ); } tool->top[ 0 ][ x ] += ( float ) tool->rad[ x ]; tool->bot[ 0 ][ x ] += ( float ) tool->rad[ x ]; tool->top[ 0 ][ z ] += ( float ) tool->rad[ z ]; tool->bot[ 0 ][ z ] += ( float ) tool->rad[ z ]; tool->top[ 1 ][ x ] += ( float ) tool->rad[ x ]; tool->bot[ 1 ][ x ] += ( float ) tool->rad[ x ]; tool->top[ 1 ][ z ] -= ( float ) tool->rad[ z ]; tool->bot[ 1 ][ z ] -= ( float ) tool->rad[ z ]; tool->top[ 2 ][ x ] -= ( float ) tool->rad[ x ]; tool->bot[ 2 ][ x ] -= ( float ) tool->rad[ x ]; tool->top[ 2 ][ z ] -= ( float ) tool->rad[ z ]; tool->bot[ 2 ][ z ] -= ( float ) tool->rad[ z ]; tool->top[ 3 ][ x ] -= ( float ) tool->rad[ x ]; tool->bot[ 3 ][ x ] -= ( float ) tool->rad[ x ]; tool->top[ 3 ][ z ] += ( float ) tool->rad[ z ]; tool->bot[ 3 ][ z ] += ( float ) tool->rad[ z ]; VCPY( tool->holex, tool->center ); VCPY( tool->holez, tool->center ); if ( tool->shape ) { tool->holex[ x ] += ( float )( tool->diam * tool->rad[ x ] ); tool->holez[ z ] += ( float )( tool->diam * tool->rad[ z ] ); } }
Load( AtmosphereData *dat, const LWLoadState *lState ) { int version, txtr = 0; float fp[ 3 ]; LWLOAD_I4( lState, &version, 1 ); LWLOAD_FP( lState, fp, 1); dat->hi = fp[ 0 ]; LWLOAD_FP( lState, fp, 1); dat->lo = fp[ 0 ]; LWLOAD_FP( lState, fp, 1); dat->fa = fp[ 0 ]; LWLOAD_FP( lState, fp, 1); dat->lum = fp[ 0 ]; LWLOAD_FP( lState, fp, 1); dat->opa = fp[ 0 ]; LWLOAD_FP( lState, fp, 1); dat->den = fp[ 0 ]; LWLOAD_FP( lState, fp, 3); VCPY( dat->col, fp ); LWLOAD_I4( lState, &dat->res, 1 ); LWLOAD_I4( lState, &dat->useTxtr, 1 ); LWLOAD_I4( lState, &dat->march, 1 ); if ( version > 1 ) LWLOAD_I4( lState, &dat->bck, 1 ); if ( version > 2 ) LWLOAD_I4( lState, &txtr, 1 ); else return NULL; if ( !txtr ) return NULL; if ( LWLOAD_FIND( lState, headerBlks )) { if ( !dat->txtr ) dat->txtr = txtrf->create( TRT_COLOR, "FogTexture", NULL, NULL ); txtrf->load( dat->txtr, lState ); LWLOAD_END( lState ); } return NULL; }
static int ui_set( AtmosphereData *dat, unsigned long vid, void *value ) { double *d = ( double * ) value; int *i = ( int * ) value; if ( !dat ) return 0; switch ( vid ) { case ID_MARCH: dat->march = *i; return 1; case ID_HI: dat->hi = *d; return 1; case ID_LO: dat->lo = *d; return 1; case ID_FA: dat->fa = *d; return 1; case ID_LUM: dat->lum = *d; return 1; case ID_OPA: dat->opa = *d; return 1; case ID_DEN: dat->den = *d; return 1; case ID_BCK: dat->bck = *i; return 1; case ID_RES: dat->res = *i; return 1; case ID_TXTR: dat->useTxtr = *i; return 1; case ID_COL: VCPY( dat->col, d ); return 1; default: return 0; } }
void raymarchEval( const LWVolumeAccess *va, AtmosphereData *dat ) { double density = 100.0, falloff = 10.0; double integstart = 0.0, integend = 100.0; double minstepsize = 0.01, maxstepsize = 100.0; double k = 200.0; double fogclr[ 3 ]; int use_lighting = 1, atmos_type = dat->type; double dtau, last_dtau, total_tau, rstep, tau, x, y, h, col[ 4 ], trans; int nsteps = 0; /* record number of integration steps */ double li[ 3 ], last_li[ 3 ]; LWVolumeSample sample; /* differential color & opacity */ LWDVector PP; LWMicropol mp; k *= dat->res; falloff *= dat->fa; density /= dat->den; h = dat->hi - dat->lo; if ( h == 0 ) return; /* if using a texture, initialize the micropolygon */ if ( dat->useTxtr ) { memset( &mp, 0, sizeof( LWMicropol )); mp.gNorm[ 1 ] = mp.wNorm[ 1 ] = 1.0; mp.oAxis = mp.wAxis = 1; mp.oScl[ 0 ] = mp.oScl[ 1 ] = mp.oScl[ 2 ] = 1.0; } /* get the fog color */ if ( dat->bck ) backdropinfo->backdrop( dat->time, va->dir, fogclr ); else VCPY( fogclr, dat->col ); /* assume initially that the ray origin is in the fog */ sample.dist = va->nearClip; /* below the fog bottom, looking up */ if ( va->dir[ 1 ] > 0 && va->o[ 1 ] < dat->lo ) { y = ( dat->lo - va->o[ 1 ] ); x = y / va->dir[ 1 ]; sample.dist = sqrt( x * x + y * y ); } /* above the fog top, looking down */ if ( va->dir[ 1 ] < 0 && va->o[ 1 ] > dat->hi ) { y = ( dat->hi - va->o[ 1 ] ); x = y / va->dir[ 1 ]; sample.dist = sqrt( x * x + y * y ); } /* test if intersection within clipping range */ if ( sample.dist > va->farClip ) return; VADDS3( PP, va->o, va->dir, sample.dist ); y = ( upcomp( PP ) - dat->lo ) / h; /* test if outside fog */ if (( y > 1 && va->dir[ 1 ] > 0 ) || ( y < 0 && va->dir[ 1 ] < 0 )) return; dtau = density * GADD( va, PP, y, falloff, use_lighting, atmos_type, li ); rstep = 1.0 / ( k * dtau + 0.001 ); sample.stride = sample.dist * MAX( MIN( CLAMP( rstep, minstepsize, maxstepsize ), va->farClip - sample.dist ), 0.0005 ); ++nsteps; total_tau = 0; while (( sample.dist <= va->farClip ) && ( total_tau * dat->opa < 300 ) && ( nsteps < 200 )) { last_dtau = dtau; VCPY( last_li, li ); VADDS3( PP, va->o, va->dir, sample.dist ); y = ( upcomp( PP ) - dat->lo ) / h; /* test if outside fog */ if (( y > 1 && va->dir[ 1 ] > 0 ) || ( y < 0 && va->dir[ 1 ] < 0 )) return; dtau = density * GADD( va, PP, y, falloff, use_lighting, atmos_type, li ); if ( !dat->useTxtr ) { trans = 0; VSCL3( col, fogclr, dat->lum ); } else { trans = evalTexture( &mp, PP, sample.stride, col, dat->txtr ); VSCL( col, dat->lum ); } if ( trans != 1.0 ) { tau = 0.5 * sample.stride * ( dtau * ( 1.0 - trans ) + last_dtau ); total_tau += tau; /* color */ sample.color[ 0 ] = 0.5 * col[ 0 ] * sample.stride * ( li[ 0 ] * dtau + last_li[ 0 ] * last_dtau ); sample.color[ 1 ] = 0.5 * col[ 1 ] * sample.stride * ( li[ 1 ] * dtau + last_li[ 1 ] * last_dtau ); sample.color[ 2 ] = 0.5 * col[ 2 ] * sample.stride * ( li[ 2 ] * dtau + last_li[ 2 ] * last_dtau ); /* opacity */ VSET( sample.opacity, tau * dat->opa ); /* add volumetric sample to the ray */ va->addSample( va->ray, &sample ); } /* new stride = f(dist) */ rstep = 1.0 / ( k * dtau + 0.001 ); sample.stride = sample.dist * MAX( MIN( CLAMP( rstep, minstepsize, maxstepsize ), va->farClip - sample.dist ), 0.0005 ); sample.dist += sample.stride; nsteps += 1; } }
void analyticEval( const LWVolumeAccess *va, AtmosphereData *dat ) { LWVolumeSample sample; /* differential color & opacity */ double density = 100.f, falloff = 200.f; double tau, fog, x, y, yo, ye, lo, le, h , nearClip, fogclr[ 3 ], dir[ 3 ]; /* skip evaluation if this is a shadow ray */ if ( !( va->flags & LWVEF_COLOR )) return; h = dat->hi - dat->lo; if ( h == 0 ) return; falloff = 200 * dat->fa; density /= dat->den; nearClip = 0.0001; /* find ray/fog intersection */ y = va->o[ 1 ]; if ( va->dir[ 1 ] > 0 ) { /* looking up */ if ( y > dat->hi ) return; else if ( y > dat->lo && y < dat->hi ) { y = ( dat->hi - va->o[ 1 ] ); x = y / va->dir[ 1 ]; ye = dat->hi; le = sqrt( x * x + y * y ); lo = nearClip; yo = va->o[ 1 ] + lo * va->dir[ 1 ]; sample.dist = lo; } else if ( y < dat->lo ) { y = ( dat->lo - va->o[ 1 ] ); x = y / va->dir[ 1 ]; lo = sqrt( x * x + y * y ); yo = va->o[ 1 ] + lo * va->dir[ 1 ]; y = ( dat->hi - va->o[ 1 ] ); x = y / va->dir[ 1 ]; ye = dat->hi; le = sqrt( x * x + y * y ); sample.dist = lo; } } if ( va->dir[ 1 ] < 0 ) { /* looking down */ if ( y < dat->lo ) return; else if ( y > dat->lo && y < dat->hi ) { y = ( dat->lo - va->o[ 1 ] ); x = y / va->dir[ 1 ]; ye = dat->lo; le = sqrt( x * x + y * y ); lo = nearClip; yo = va->o[ 1 ] + lo * va->dir[ 1 ]; } else if ( y > dat->hi ) { y = ( dat->hi - va->o[ 1 ] ); x = y / va->dir[ 1 ]; lo = sqrt( x * x + y * y ); yo = va->o[ 1 ] + lo * va->dir[ 1 ]; y = ( dat->lo - va->o[ 1 ] ); x = y / va->dir[ 1 ]; ye = dat->lo; le = sqrt( x * x + y * y ); } } if ( lo > va->farClip ) return; /* evaluate tau = optical distance */ sample.dist = 0.9999 * va->farClip; if ( le > va->farClip ) { le = va->farClip; ye = va->o[ 1 ] + le * va->dir[ 1 ]; } yo = ( yo - dat->lo ) / h; ye = ( ye - dat->lo ) / h; if ( fabs( va->dir[ 1 ] ) > 0.001 ) { tau = exp( -( yo + va->dir[ 1 ] * ( le - lo ))) - exp( -yo ); tau *= -( density * ( le - lo )) / ( falloff * va->dir[ 1 ] ); } else { VCPY( dir, va->dir ); if ( dir[ 1 ] > 0 ) dir[ 1 ] = 0.001; else dir[ 1 ] = -0.001; tau = exp( -( yo + dir[ 1 ] * ( le - lo ))) - exp( -yo ); tau *= -( density * ( le - lo )) / ( falloff * dir[ 1 ] ); } /* convert tau to the overall normalised fog amount along that ray */ tau -= density * ( le - lo ) * exp( -falloff ); if ( tau > 0 ) fog = 1 - exp( -tau ); /* R -> [0,1].... 0 = no fog , 1 = max fog */ else fog = 1; fog *= dat->opa; CLAMP( fog, 0, 1 ); /* Now we compute the final color value in a way similar to LW's fog: final_color = (1 - fog) * backColor + fog * fogColor * luminosity backColor = va->rayColor is the color viewed from the ray (ie LW's render). The result is set a sample of size 0, and opacity = 1.0 which means that this sample is opaque (null sized samples are treated as surface samples). */ sample.stride = 0; VSET( sample.opacity, 1.0 ); if ( dat->bck ) backdropinfo->backdrop( dat->time, va->dir, fogclr ); else VCPY( fogclr, dat->col ); sample.color[ 0 ] = ( 1 - fog ) * va->rayColor[ 0 ] + fog * fogclr[ 0 ] * dat->lum; sample.color[ 1 ] = ( 1 - fog ) * va->rayColor[ 1 ] + fog * fogclr[ 1 ] * dat->lum; sample.color[ 2 ] = ( 1 - fog ) * va->rayColor[ 2 ] + fog * fogclr[ 2 ] * dat->lum; va->addSample( va->ray, &sample ); }
void Atmosphere::analyticEval(lwpp::VolumetricAccess va) { LWVolumeSample sample; /* differential color & opacity */ double density = 100.f, falloff = 200.f; double tau = 0, fog = 0, x = 0, y = 0, yo = 0, ye = 0, lo = 0, le = 0, h = 0 , nearClip = 0, fogclr[ 3 ]; lwpp::Vector3D dir; /* skip evaluation if this is a shadow ray */ if ( !( va.getFlags() & LWVEF_COLOR )) return; h = hi - lo; if ( h == 0 ) return; falloff = 200 * fa; density /= den; le = lo = nearClip = 0.0001; /* find ray/fog intersection */ y = va.getOrigin().y; if ( va.getDirection().y > 0 ) { /* looking up */ if ( y > hi ) return; else if ( y > lo && y < hi ) { y = ( hi - va.getOrigin().y ); x = y / va.getDirection().y; ye = hi; le = sqrt( x * x + y * y ); lo = nearClip; yo = va.getOrigin().y + lo * va.getDirection().y; sample.dist = lo; } else if ( y < lo ) { y = ( lo - va.getOrigin().y ); x = y / va.getDirection().y; lo = sqrt( x * x + y * y ); yo = va.getOrigin().y + lo * va.getDirection().y; y = ( hi - va.getOrigin().y ); x = y / va.getDirection().y; ye = hi; le = sqrt( x * x + y * y ); sample.dist = lo; } } else if ( va.getDirection().y < 0 ) { /* looking down */ if ( y < lo ) return; else if ( y > lo && y < hi ) { y = ( lo - va.getOrigin().y ); x = y / va.getDirection().y; ye = lo; le = sqrt( x * x + y * y ); lo = nearClip; yo = va.getOrigin().y + lo * va.getDirection().y; } else if ( y > hi ) { y = ( hi - va.getOrigin().y ); x = y / va.getDirection().y; lo = sqrt( x * x + y * y ); yo = va.getOrigin().y + lo * va.getDirection().y; y = ( lo - va.getOrigin().y ); x = y / va.getDirection().y; ye = lo; le = sqrt( x * x + y * y ); } } else return; if ( lo > va.getFarClip() ) return; /* evaluate tau = optical distance */ sample.dist = 0.9999 * va.getFarClip(); if ( le > va.getFarClip() ) { le = va.getFarClip(); ye = va.getOrigin().y + le * va.getDirection().y; } yo = ( yo - lo ) / h; ye = ( ye - lo ) / h; if ( fabs( va.getDirection().y ) > 0.001 ) { tau = exp( -( yo + va.getDirection().y * ( le - lo ))) - exp( -yo ); tau *= -( density * ( le - lo )) / ( falloff * va.getDirection().y ); } else { dir = va.getDirection(); if ( dir.y > 0 ) dir.y = 0.001; else dir.y = -0.001; tau = exp( -( yo + dir.y * ( le - lo ))) - exp( -yo ); tau *= -( density * ( le - lo )) / ( falloff * dir.y ); } /* convert tau to the overall normalised fog amount along that ray */ tau -= density * ( le - lo ) * exp( -falloff ); if ( tau > 0 ) fog = 1 - exp( -tau ); /* R -> [0,1].... 0 = no fog , 1 = max fog */ else fog = 1; fog *= opa; CLAMP( fog, 0, 1 ); /* Now we compute the final color value in a way similar to LW's fog: final_color = (1 - fog) * backColor + fog * fogColor * luminosity backColor = va.rayColor is the color viewed from the ray (ie LW's render). The result is set a sample of size 0, and opacity = 1.0 which means that this sample is opaque (null sized samples are treated as surface samples). */ sample.stride = 0; VSET( sample.opacity, 1.0 ); if ( bck ) { const double direction[3] = {va.getDirection().x,va.getDirection().y, va.getDirection().z }; backdropinfo->backdrop( time, direction, fogclr ); } else { VCPY( fogclr, col ); } sample.color[ 0 ] = ( 1 - fog ) * va.getRayColorR() + fog * fogclr[ 0 ] * lum; sample.color[ 1 ] = ( 1 - fog ) * va.getRayColorG() + fog * fogclr[ 1 ] * lum; sample.color[ 2 ] = ( 1 - fog ) * va.getRayColorB() + fog * fogclr[ 2 ] * lum; va.addSample( &sample ); }
static int SuperQ_Adjust( sqData *tool, LWToolEvent *event, int handle ) { int x, y, z, i, j; y = tool->axis; x = xax[ tool->axis ]; z = zax[ tool->axis ]; if ( event->portAxis >= 0 ) { if ( event->flags & LWTOOLF_CONSTRAIN ) { int tx, ty, stxax[] = { 1, 2, 0 }, styax[] = { 2, 0, 1 }; tx = stxax[ event->portAxis ]; ty = styax[ event->portAxis ]; if ( event->flags & LWTOOLF_CONS_X ) event->posSnap[ tx ] -= event->deltaSnap[ tx ]; else if ( event->flags & LWTOOLF_CONS_Y ) event->posSnap[ ty ] -= event->deltaSnap[ ty ]; } } /* dragging a corner, update the radius */ if ( handle <= 7 ) { VSUB3( tool->rad, event->posSnap, tool->org ); tool->rad[ 0 ] = ABS( tool->rad[ 0 ] ); tool->rad[ 1 ] = ABS( tool->rad[ 1 ] ); tool->rad[ 2 ] = ABS( tool->rad[ 2 ] ); setBoxCorners( tool ); } /* dragging the center, update the position */ else if ( handle == 8 ) { LWDVector dif; VSUB3( dif, event->posSnap, tool->org ); for ( j = 0; j < 4; j++ ) { for ( i = 0; i < 3; i++ ) { tool->top[ j ][ i ] += ( float ) dif[ i ]; tool->bot[ j ][ i ] += ( float ) dif[ i ]; } } for ( i = 0; i < 3; i++ ) { tool->holex[ i ] += ( float ) dif[ i ]; tool->holez[ i ] += ( float ) dif[ i ]; } VCPY( tool->org, event->posSnap ); VCPY_F( tool->center, tool->org ); } /* dragging the X hole size handle */ else if ( handle == 9 ) { event->posSnap[ y ] = tool->org[ y ]; event->posSnap[ z ] = tool->org[ z ]; if ( tool->rad[ x ] > 1e-7f ) tool->diam = ( event->posSnap[ x ] - tool->org[ x ] ) / tool->rad[ x ]; if ( tool->diam < 1.0f ) tool->diam = 1.0f; VCPY_F( tool->holex, event->posSnap ); VCPY( tool->holez, tool->center ); tool->holez[ z ] += ( float )( tool->diam * tool->rad[ z ] ); } /* dragging the Z hole size handle */ else if ( handle == 10 ) { event->posSnap[ y ] = tool->org[ y ]; event->posSnap[ x ] = tool->org[ x ]; if ( tool->rad[ z ] > 1e-7f ) tool->diam = ( event->posSnap[ z ] - tool->org[ z ] ) / tool->rad[ z ]; if ( tool->diam < 1.0f ) tool->diam = 1.0f; VCPY_F( tool->holez, event->posSnap ); VCPY(tool->holex, tool->center); tool->holex[ x ] += ( float )( tool->diam * tool->rad[ x ] ); } tool->dirty = 1; tool->update = LWT_TEST_UPDATE; return handle; }
static void SuperQ_Draw( sqData *tool, LWWireDrawAccess *draw ) { LWFVector top[ 4 ], bot[ 4 ], del; int x, y, z, i; if ( !tool->active ) return; y = tool->axis; x = xax[ tool->axis ]; z = zax[ tool->axis ]; /* bounding box */ draw->moveTo( draw->data, tool->top[ 0 ], LWWIRE_DASH ); draw->lineTo( draw->data, tool->top[ 1 ], LWWIRE_ABSOLUTE ); draw->lineTo( draw->data, tool->top[ 2 ], LWWIRE_ABSOLUTE ); draw->lineTo( draw->data, tool->top[ 3 ], LWWIRE_ABSOLUTE ); draw->lineTo( draw->data, tool->top[ 0 ], LWWIRE_ABSOLUTE ); draw->moveTo( draw->data, tool->bot[ 0 ], LWWIRE_DASH ); draw->lineTo( draw->data, tool->bot[ 1 ], LWWIRE_ABSOLUTE ); draw->lineTo( draw->data, tool->bot[ 2 ], LWWIRE_ABSOLUTE ); draw->lineTo( draw->data, tool->bot[ 3 ], LWWIRE_ABSOLUTE ); draw->lineTo( draw->data, tool->bot[ 0 ], LWWIRE_ABSOLUTE ); draw->lineTo( draw->data, tool->top[ 0 ], LWWIRE_ABSOLUTE ); draw->moveTo( draw->data, tool->top[ 3 ], LWWIRE_DASH ); draw->lineTo( draw->data, tool->bot[ 3 ], LWWIRE_ABSOLUTE ); draw->moveTo( draw->data, tool->bot[ 2 ], LWWIRE_DASH ); draw->lineTo( draw->data, tool->top[ 2 ], LWWIRE_ABSOLUTE ); draw->moveTo( draw->data, tool->top[ 1 ], LWWIRE_DASH ); draw->lineTo( draw->data, tool->bot[ 1 ], LWWIRE_ABSOLUTE ); /* center crosshair */ for ( i = 0; i < 3; i++ ) { VCPY( top[ i ], tool->center ); VCPY( bot[ i ], tool->center); } VSUB3( del, tool->top[ 0 ], tool->bot[ 2 ] ); VSCL( del, 0.25f ); top[ 0 ][ z ] += del[ z ]; bot[ 0 ][ z ] -= del[ z ]; top[ 1 ][ x ] += del[ x ]; bot[ 1 ][ x ] -= del[ x ]; top[ 2 ][ y ] += del[ y ]; bot[ 2 ][ y ] -= del[ y ]; draw->moveTo( draw->data, top[ 0 ], LWWIRE_SOLID ); draw->lineTo( draw->data, bot[ 0 ], LWWIRE_ABSOLUTE ); draw->moveTo( draw->data, top[ 1 ], LWWIRE_SOLID ); draw->lineTo( draw->data, bot[ 1 ], LWWIRE_ABSOLUTE ); draw->moveTo( draw->data, top[ 2 ], LWWIRE_SOLID ); draw->lineTo( draw->data, bot[ 2 ], LWWIRE_ABSOLUTE ); /* handles for toroid hole */ if ( tool->shape ) { VCPY( del, tool->center ); draw->moveTo( draw->data, del, LWWIRE_DASH ); draw->lineTo( draw->data, tool->holex, LWWIRE_ABSOLUTE ); draw->circle( draw->data, 0.025, LWWIRE_SCREEN ); draw->moveTo( draw->data, del, LWWIRE_DASH ); draw->lineTo( draw->data, tool->holez, LWWIRE_ABSOLUTE ); draw->circle( draw->data, 0.025, LWWIRE_SCREEN ); } tool->dirty = 0; }
void HUD_Knob(LWViewportInfo *ViewGlobal, const LWCustomObjAccess *cob, Matrix m, LWDVector cent, double siz, int flags) { LWDVector a, b, c, home; VCPY(a, cent); VCPY(b, cent); VCPY(c, cent); siz *= 0.5; if(flags&HUDF_SIDE) { a[0] += siz; b[0] -= siz; c[0] -= siz; b[1] -= siz; c[1] += siz; } else if(flags&HUDF_DOWN) { a[0] += siz; b[0] -= siz; a[1] += siz; b[1] += siz; c[1] -= siz; } else { a[0] += siz; b[0] -= siz; a[1] -= siz; b[1] -= siz; c[1] += siz; } VCPY(home,a); MatrixApply(a, m,home); VCPY(home,b); MatrixApply(b, m,home); VCPY(home,c); MatrixApply(c, m,home); HUDPosition(ViewGlobal, cob->view, home, cob->viewDir); VADD(a, home); VADD(b, home); VADD(c, home); if(flags&HUDF_LOCK) { LWDVector d, p; VCPY(d, cent); VCPY(c, cent); d[0] += siz; c[0] -= siz; c[1] += siz; d[1] += siz; VCPY(p,c); MatrixApply(c, m,p); VCPY(p,d); MatrixApply(d, m,p); VADD(d, home); VADD(c, home); cob->line(cob->dispData, a, b, LWCSYS_WORLD); cob->line(cob->dispData, c, b, LWCSYS_WORLD); cob->line(cob->dispData, c, d, LWCSYS_WORLD); cob->line(cob->dispData, a, d, LWCSYS_WORLD); } else if(flags&HUDF_FILL) { float shad[4] = {0, 0, 0, 0.5f}, glint[4] = {1, 1, 1, 0.5f}; cob->triangle(cob->dispData, a, b, c, LWCSYS_WORLD); cob->setColor(cob->dispData, glint); cob->line(cob->dispData, c, b, LWCSYS_WORLD); cob->setColor(cob->dispData, shad); // dangerous side-effect, leaves color changed cob->line(cob->dispData, a, b, LWCSYS_WORLD); cob->line(cob->dispData, a, c, LWCSYS_WORLD); } else { cob->line(cob->dispData, a, b, LWCSYS_WORLD); cob->line(cob->dispData, c, b, LWCSYS_WORLD); cob->line(cob->dispData, a, c, LWCSYS_WORLD); } }
static int SuperQ_Set( sqData *tool, unsigned long vid, void *value ) { switch ( vid ) { case XID_AXIS: axis = tool->axis = *(( int * ) value ); break; case XID_UVS: tool->uvs = *(( int * ) value ); break; case XID_SID: nsides = tool->nsides = *(( int * ) value ); if ( nsides < 2 ) nsides = tool->nsides = 2; break; case XID_SEG: nsegments = tool->nsegments = *(( int * ) value ); if ( nsegments < 2 ) nsegments = tool->nsegments = 2; break; case XID_TYPE: shape = tool->shape = *(( int * ) value ); break; case XID_BF1: bf1 = *(( double * ) value ); tool->bf1 = bf1 < 0.01 ? 0.01 : bf1; bf1 = tool->bf1; break; case XID_BF2: bf2 = *(( double * ) value ); tool->bf2 = bf2 < 0.01 ? 0.01 : bf2; bf2 = tool->bf2; break; case XID_CEN: VCPY( tool->org, ( double * ) value ); VCPY( org, ( double * ) value ); VCPY_F( tool->center, ( double * ) value ); break; case XID_RAD: VCPY( tool->rad, ( double * ) value ); VCPY( rad, ( double * ) value ); break; case XID_DIAM: tool->diam = *(( double * ) value ); rad[ 3 ] = tool->diam; break; case XID_ACTI: break; default: return 0; } tool->update = LWT_TEST_UPDATE; tool->dirty = 1; setBoxCorners( tool ); return 1; }
void Atmosphere::raymarchEval(lwpp::VolumetricAccess va) { double density = 100.0, falloff = 10.0; double integstart = 0.0, integend = 100.0; double minstepsize = 0.01, maxstepsize = 100.0; double k = 200.0; double fogclr[ 3 ]; int use_lighting = 1, atmos_type = type; double dtau, last_dtau, total_tau, rstep, tau, x, y, h, col[ 4 ], trans; int nsteps = 0; /* record number of integration steps */ double li[ 3 ], last_li[ 3 ]; LWVolumeSample sample; /* differential color & opacity */ // ORIGINALLY LWDVector PP; lwpp::Point3D PP; LWMicropol mp; k *= res; falloff *= fa; density /= den; h = hi - lo; if ( h == 0 ) return; /* if using a texture, initialize the micropolygon */ if ( useTxtr ) { memset( &mp, 0, sizeof( LWMicropol )); mp.gNorm[ 1 ] = mp.wNorm[ 1 ] = 1.0; mp.oAxis = mp.wAxis = 1; mp.oScl[ 0 ] = mp.oScl[ 1 ] = mp.oScl[ 2 ] = 1.0; } /* get the fog color */ if ( bck ) { const double origin[3] = {va.getOrigin().x,va.getOrigin().y, va.getOrigin().z }; backdropinfo->backdrop( time, origin, fogclr ); } else { VCPY( fogclr, this->col ); } /* assume initially that the ray origin is in the fog */ sample.dist = va.getNearClip(); /* below the fog bottom, looking up */ if ( va.getDirection().y > 0 && va.getOrigin().y < lo ) { y = ( lo - va.getOrigin().y ); x = y / va.getDirection().y; sample.dist = sqrt( x * x + y * y ); } /* above the fog top, looking down */ if ( va.getDirection().y < 0 && va.getOrigin().y > hi ) { y = ( hi - va.getOrigin().y ); x = y / va.getDirection().y; sample.dist = sqrt( x * x + y * y ); } /* test if intersection within clipping range */ if ( sample.dist > va.getFarClip() ) return; // ORIGINALLY // VADDS3( PP, va.getOrigin(), va.getDirection(), sample.dist ); PP = ((lwpp::Point3D(va.getOrigin()) + lwpp::Vector3D(va.getDirection())) * sample.dist); y = ( PP.y - lo ) / h; /* test if outside fog */ if (( y > 1 && va.getDirection().y > 0 ) || ( y < 0 && va.getDirection().y < 0 )) return; dtau = density * GADD( va, PP.asLWDVector(), y, falloff, use_lighting, atmos_type, li ); rstep = 1.0 / ( k * dtau + 0.001 ); sample.stride = sample.dist * MAX( MIN( CLAMP( rstep, minstepsize, maxstepsize ), va.getFarClip() - sample.dist ), 0.0005 ); ++nsteps; total_tau = 0; while (( sample.dist <= va.getFarClip() ) && ( total_tau * opa < 300 ) && ( nsteps < 200 )) { last_dtau = dtau; VCPY( last_li, li ); // ORIGINALLY // VADDS3( PP, va.getOrigin(), va.getDirection(), sample.dist ); y = ( upcomp( PP.asLWDVector() ) - lo ) / h; /* test if outside fog */ if (( y > 1 && va.getDirection().y > 0 ) || ( y < 0 && va.getDirection().y < 0 )) return; dtau = density * GADD( va, PP.asLWDVector(), y, falloff, use_lighting, atmos_type, li ); if ( !useTxtr ) { trans = 0; VSCL3( col, fogclr, lum ); } else { trans = evalTexture( &mp, PP.asLWDVector(), sample.stride, col, txtr ); VSCL( col, lum ); } if ( trans != 1.0 ) { tau = 0.5 * sample.stride * ( dtau * ( 1.0 - trans ) + last_dtau ); total_tau += tau; /* color */ sample.color[ 0 ] = 0.5 * col[ 0 ] * sample.stride * ( li[ 0 ] * dtau + last_li[ 0 ] * last_dtau ); sample.color[ 1 ] = 0.5 * col[ 1 ] * sample.stride * ( li[ 1 ] * dtau + last_li[ 1 ] * last_dtau ); sample.color[ 2 ] = 0.5 * col[ 2 ] * sample.stride * ( li[ 2 ] * dtau + last_li[ 2 ] * last_dtau ); /* opacity */ VSET( sample.opacity, tau * opa ); /* add volumetric sample to the ray */ va.addSample( &sample ); } /* new stride = f(dist) */ rstep = 1.0 / ( k * dtau + 0.001 ); sample.stride = sample.dist * MAX( MIN( CLAMP( rstep, minstepsize, maxstepsize ), va.getFarClip() - sample.dist ), 0.0005 ); sample.dist += sample.stride; nsteps += 1; } }