/////////////////////////////////////////////////////////////////////// // Class : CPointHierarchy // Method : average // Description : /// \brief Create an internal node by averaging the point data // Return Value : - // Comments : int CPointHierarchy::average(int numItems,int *indices) { CMapNode node; // PASS 1: Average the position/normal initv(node.P,0); initv(node.N,0); for (int i=numItems;i>0;i--) { const CPointCloudPoint *item = CMap<CPointCloudPoint>::items + (*indices++); addvv(node.P,item->P); addvv(node.N,item->N); } indices -= numItems; // Normalize the thing assert(numItems > 0); mulvf(node.P,1/(float) numItems); normalizev(node.N); // PASS 2: Compute the maximum deviation initv(node.radiosity,0); node.dP = 0; node.dN = 1; for (int i=numItems;i>0;i--) { vector D; const CPointCloudPoint *item = CMap<CPointCloudPoint>::items + (*indices++); const float *src = data.array + item->entryNumber; float area; subvv(D,node.P,item->P); if (areaIndex == -1) area = max(((float) C_PI*item->dP*item->dP*dotvv(node.N,item->N)),0); else area = max((src[areaIndex]*dotvv(node.N,item->N)),0); node.dP += area; if (radiosityIndex != -1) { vector tmp; mulvf(tmp,src + radiosityIndex,area); addvv(node.radiosity,tmp); } node.dN = min(node.dN,dotvv(node.N,item->N)); } indices -= numItems; // Normalize the radiosity and the area mulvf(node.radiosity,1 / node.dP); // Normalize the radiosity node.dP = sqrtf(node.dP / (float) C_PI); // Convert to effective radius // Create the node nodes.push(node); return nodes.numItems - 1; }
/////////////////////////////////////////////////////////////////////// // Class : CDelayedInstance // Method : CDelayedInstance // Description : /// \brief Ctor // Return Value : - // Comments : CDelayedInstance::CDelayedInstance(CAttributes *a,CXform *x,CObject *in) : CObject(a,x) { atomicIncrement(&stats.numDelayeds); instance = in; processed = FALSE; initv(bmin,C_INFINITY); initv(bmax,-C_INFINITY); CObject *cObject; for (cObject=instance;cObject!=NULL;cObject=cObject->sibling) { addBox(bmin,bmax,cObject->bmin); addBox(bmin,bmax,cObject->bmax); } xform->transformBound(this->bmin,this->bmax); makeBound(this->bmin,this->bmax); }
/////////////////////////////////////////////////////////////////////// // Class : CXform // Method : transformBound // Description : This function is used to transform a bounding box // Return Value : - // Comments : void transformBound(float *lbmin,float *lbmax,const float *to,const float *bmin,const float *bmax) { vector corners[8]; int i; vector vtmp; // Compute & transfer the corners to the dest space initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[0],to,vtmp); initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[1],to,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[2],to,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[3],to,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[4],to,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[5],to,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[6],to,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[7],to,vtmp); movvv(lbmin,corners[0]); movvv(lbmax,corners[0]); for (i=1;i<8;i++) { addBox(lbmin,lbmax,corners[i]); } }
/////////////////////////////////////////////////////////////////////// // Class : CBSplinePatchGrid // Method : CBSplinePatchGrid // Description : /// \brief Ctor // Return Value : - // Comments : CBSplinePatchGrid::CBSplinePatchGrid(CAttributes *a,CXform *x,CVertexData *var,CParameter *p,int nu,int nv,float uOrg,float vOrg,float uMult,float vMult,float *ve) : CSurface(a,x) { atomicIncrement(&stats.numGprims); variables = var; variables->attach(); parameters = p; uVertices = nu; vVertices = nv; this->uOrg = uOrg; this->vOrg = vOrg; this->uMult = uMult; this->vMult = vMult; const int numVertices = (nu*nv); int i,j,k; matrix ut; matrix bsplinebasis; matrix geometryU,geometryV; matrix tmp; const int upatches = uVertices - 3; const int vpatches = vVertices - 3; initv(bmin,C_INFINITY,C_INFINITY,C_INFINITY); initv(bmax,-C_INFINITY,-C_INFINITY,-C_INFINITY); // Note that u basis and v basis are swapped to take the transpose into account done during the precomputation // Note also that we could use the B-spline basis to bound the curve, but Bezier bound is tighter for (i=0;i<4;i++) for (j=0;j<4;j++) bsplinebasis[element(i,j)] = RiBSplineBasis[j][i]; transposem(ut,bsplinebasis); mulmm(geometryV,invBezier,ut); mulmm(geometryU,bsplinebasis,invBezier); // alloc off upatches*vpatches*16*vertexSize worth of data const int vertexSize = var->vertexSize; const int vs = (variables->moving ? vertexSize*2 : vertexSize); vertex = new float[vs*16*upatches*vpatches]; for (i=0;i<vpatches;i++) { for (j=0;j<upatches;j++) { int r,c; float *patchData = vertex + (i*upatches + j)*16*vertexSize; // Fill in the geometry matrices for (r=0;r<4;r++) { int y = (r + i) % vVertices; for (c=0;c<4;c++) { int x = (c + j) % uVertices; const float *d = ve + (y*uVertices+x)*vs; for (k=0;k<vertexSize;k++) { patchData[16*k + element(r,c)] = *d++; } } } // add to bounds makeCubicBound(bmin,bmax,patchData+0*16,patchData+1*16,patchData+2*16); // precompute B*G*B' and stash it for (k=0;k<vertexSize;k++) { mulmm(tmp,ut,patchData); mulmm(patchData,tmp,bsplinebasis); patchData += 16; } // do the same for moving points if (variables->moving) { patchData = vertex + (upatches*vpatches + i*upatches + j)*16*vertexSize; for (r=0;r<4;r++) { int y = (r + i) % vVertices; for (c=0;c<4;c++) { int x = (c + j) % uVertices; const float *d = ve + vertexSize + (y*uVertices+x)*vs; for (k=0;k<vertexSize;k++) { patchData[16*k + element(r,c)] = *d++; } } } // add to bounds makeCubicBound(bmin,bmax,patchData+0*16,patchData+1*16,patchData+2*16); // precompute B*G*B' and stash it for (k=0;k<vertexSize;k++) { mulmm(tmp,ut,patchData); mulmm(patchData,tmp,bsplinebasis); patchData += 16; } } } } makeBound(bmin,bmax); }
/////////////////////////////////////////////////////////////////////// // Class : CBSplinePatchGrid // Method : sample // Description : See object.h // Return Value : - // Comments : void CBSplinePatchGrid::sample(int start,int numVertices,float **varying,float ***locals,unsigned int &up) const { const float *u = varying[VARIABLE_U]+start; const float *v = varying[VARIABLE_V]+start; const int vertexSize = variables->vertexSize; float *vertexData; int vertexDataStep; int vertexSampleStride; const int upatches = uVertices - 3; const int vpatches = vVertices - 3; if (variables->moving == FALSE) { vertexData = vertex; // No need for interpolation vertexDataStep = 0; vertexSampleStride = vertexSize*16; } else { if (up & PARAMETER_BEGIN_SAMPLE) { vertexData = vertex; // No need for interpolation vertexDataStep = 0; vertexSampleStride = vertexSize*16; } else if (up & PARAMETER_END_SAMPLE) { vertexData = vertex + vertexSize*16*upatches*vpatches; // No need for interpolation vertexDataStep = 0; vertexSampleStride = vertexSize*16; } else { // Interpolate the vertex data in advance // Note: this is potentially hugely expensive float *interpolate; const float *time = varying[VARIABLE_TIME] + start; vertexData = (float *) alloca(numVertices*vertexSize*16*sizeof(float)); vertexDataStep = vertexSize*16; vertexSampleStride = 0; interpolate = vertexData; for (int i=0;i<numVertices;++i) { const int x = (int) floor(min(u[i]*upatches,(uVertices-4))); const int y = (int) floor(min(v[i]*vpatches,(vVertices-4))); const float *vertex0 = vertex + (y*upatches + x)*vertexSize*16; const float *vertex1 = vertex0 + vertexSize*16*upatches*vpatches; const float ctime = *time++; for (int j=0;j<vertexDataStep;++j) { *interpolate++ = (float) (vertex0[j]*(1.0-ctime) + vertex1[j]*ctime); } } } } { // Do the vertices float *intr = (float *) alloca(numVertices*vertexSize*sizeof(float)); float *dPdu = varying[VARIABLE_DPDU] + start*3; float *dPdv = varying[VARIABLE_DPDV] + start*3; float *N = varying[VARIABLE_NG] + start*3; float *intrStart = intr; const float um = (float) upatches; const float vm = (float) vpatches; // Interpolate the vertices for (int i=0;i<numVertices;++i) { double tmp1[4],tmp2[4]; const int x = (int) floor(min(u[i]*upatches,(uVertices-4))); const int y = (int) floor(min(v[i]*vpatches,(vVertices-4))); const double cu = (u[i]*upatches - x); const double cv = (v[i]*vpatches - y); const float *data = vertexData + (y*upatches + x)*vertexSampleStride; const double usquared = cu*cu; const double ucubed = cu*usquared; const double vsquared = cv*cv; const double vcubed = cv*vsquared; int j; for (j=0;j<3;++j,data+=16) { for (int t=0;t<4;++t) { tmp2[t] = 3*vsquared*data[element(0,t)] + 2*cv*data[element(1,t)] + data[element(2,t)]; tmp1[t] = vcubed* data[element(0,t)] + vsquared*data[element(1,t)] + cv*data[element(2,t)] + data[element(3,t)]; } dPdv[j] = (float) (tmp2[0]*ucubed + tmp2[1]*usquared + tmp2[2]*cu + tmp2[3])*vm; dPdu[j] = (float) (tmp1[0]*3*usquared + tmp1[1]*2*cu + tmp1[2])*um; *intr++ = (float) (tmp1[0]*ucubed + tmp1[1]*usquared + tmp1[2]*cu + tmp1[3]); } for (;j<vertexSize;++j) { for (int t=0;t<4;++t) { tmp1[t] = vcubed* data[element(0,t)] + vsquared*data[element(1,t)] + cv*data[element(2,t)] + data[element(3,t)]; } *intr++ = (float) (tmp1[0]*ucubed + tmp1[1]*usquared + tmp1[2]*cu + tmp1[3]); data += 16; } crossvv(N,dPdu,dPdv); vertexData += vertexDataStep; dPdu += 3; dPdv += 3; N += 3; } // Note: make the common case fast: We're computing NG,DPDU and DPDV even if it's not required. // Most of the time though, surface normal is required // Dispatch the vertex data variables->dispatch(intrStart,start,numVertices,varying,locals); } // Compute dPdtime if (up & PARAMETER_DPDTIME) { float *dest = varying[VARIABLE_DPDTIME] + start*3; // Do we have motion? if (variables->moving) { assert(u == varying[VARIABLE_U] + start); assert(v == varying[VARIABLE_V] + start); const int disp = vertexSize*16*upatches*vpatches; // Interpolate the thing for (int i=0;i<numVertices;++i) { double tmpStart[4],tmpEnd[4]; const int x = (int) floor(min(u[i]*upatches,(uVertices-4))); const int y = (int) floor(min(v[i]*vpatches,(vVertices-4))); const double cu = (u[i]*upatches - x); const double cv = (v[i]*vpatches - y); const float *data = vertex + (y*upatches + x)*vertexSize*16; const double usquared = cu*cu; const double ucubed = cu*usquared; const double vsquared = cv*cv; const double vcubed = cv*vsquared; // For x,y,z for (int j=0;j<3;++j,data+=16) { // The inner product for (int t=0;t<4;++t) { tmpStart[t] = vcubed* data[element(0,t)] + vsquared*data[element(1,t)] + cv*data[element(2,t)] + data[element(3,t)]; tmpEnd[t] = vcubed* data[disp + element(0,t)] + vsquared*data[disp + element(1,t)] + cv*data[disp + element(2,t)] + data[disp + element(3,t)]; } // Update the data *dest++ = (float) ((tmpEnd[0]*ucubed + tmpEnd[1]*usquared + tmpEnd[2]*cu + tmpEnd[3]) - (tmpStart[0]*ucubed + tmpStart[1]*usquared + tmpStart[2]*cu + tmpStart[3])); } // Scale the dPdtime mulvf(dest-3,CRenderer::invShutterTime); } } else { // We have no motion, so dPdtime is {0,0,0} for (int i=0;i<numVertices;++i,dest+=3) initv(dest,0,0,0); } } // Make sure we don't have any zero normals normalFix(); // Turn off the processed parameters up &= ~(PARAMETER_P | PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_NG | PARAMETER_DPDTIME | variables->parameters); }
/////////////////////////////////////////////////////////////////////// // Class : CShadingContext // Method : convertColorFrom // Description : Do color conversion // Return Value : - // Comments : void convertColorFrom(float *out,const float *in,ECoordinateSystem s) { switch(s) { case COLOR_RGB: movvv(out,in); break; case COLOR_HSL: { #define HueToRGB(r,m1,m2,h ) \ if (h<0) h+=1; \ if (h>1) h-=1; \ if (6.0*h < 1 ) r = (m1+(m2-m1)*h*6); \ else if (2.0*h < 1 ) r = m2; \ else if (3.0*h < 2.0) r = (m1+(m2-m1)*((2.0f/3.0f)-h)*6); \ else r = m1; float m1,m2,h; if (in[1]==0) initv(out,in[2],in[2],in[2]); else { if (in[2] <=0.5) m2 = in[2]*(1+in[1]); else m2 = in[2]+in[1]-in[2]*in[1]; m1 = 2*in[2]-m2; h = in[0] + (1.0f/3.0f); HueToRGB(out[0],m1,m2,h); h = in[0]; HueToRGB(out[1],m1,m2,h); h = in[0] - (1.0f/3.0f); HueToRGB(out[2],m1,m2,h); } #undef HueToRGB } break; case COLOR_HSV: { if (in[1] < -1 || in[1] > 1) { if (in[0] == 0) { out[0] = in[2]; out[1] = in[2]; out[2] = in[2]; } else { out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; } } else { float f,p,q,t,h; int i; h = (float) fmod(in[0],1); if (h < 0) h += 1; h *= 6; i = (int) floor(h); f = h - i; p = in[2]*(1-in[1]); q = in[2]*(1-(in[1]*f)); t = in[2]*(1-(in[1]*(1-f))); switch(i) { case 0: out[COMP_R] = in[2]; out[COMP_G] = t; out[COMP_B] = p; break; case 1: out[COMP_R] = q; out[COMP_G] = in[2]; out[COMP_B] = p; break; case 2: out[COMP_R] = p; out[COMP_G] = in[2]; out[COMP_B] = t; break; case 3: out[COMP_R] = p; out[COMP_G] = q; out[COMP_B] = in[2]; break; case 4: out[COMP_R] = t; out[COMP_G] = p; out[COMP_B] = in[2]; break; case 5: out[COMP_R] = in[2]; out[COMP_G] = p; out[COMP_B] = q; break; } } } break; case COLOR_XYZ: out[COMP_R] = (float) (3.24079*in[0] - 1.537150*in[1] - 0.498535*in[2]); out[COMP_G] = (float) (-0.969256*in[0] + 1.875992*in[1] + 0.041556*in[2]); out[COMP_B] = (float) (0.055648*in[0] - 0.204043*in[1] + 1.057311*in[2]); break; case COLOR_CIE: out[COMP_R] = (float) (3.24079*in[0] - 1.537150*in[1] - 0.498535*in[2]); out[COMP_G] = (float) (-0.969256*in[0] + 1.875992*in[1] + 0.041556*in[2]); out[COMP_B] = (float) (0.055648*in[0] - 0.204043*in[1] + 1.057311*in[2]); break; case COLOR_YIQ: out[COMP_R] = (float) (in[0] + 0.956*in[1] + 0.620*in[2]); out[COMP_G] = (float) (in[0] - 0.272*in[1] - 0.647*in[2]); out[COMP_B] = (float) (in[0] - 1.108*in[1] + 1.705*in[2]); break; case COLOR_XYY: vector tin; if (in[2] == 0) { tin[0] = 0; tin[1] = 0; tin[2] = 0; } else { tin[0] = max(in[0]*in[2]/in[1],0); tin[1] = in[2]; tin[2] = max((1-in[0]-in[1])*in[2]/in[1],0); } out[COMP_R] = (float) (3.24079*tin[0] - 1.537150*tin[1] - 0.498535*tin[2]); out[COMP_G] = (float) (-0.969256*tin[0] + 1.875992*tin[1] + 0.041556*tin[2]); out[COMP_B] = (float) (0.055648*tin[0] - 0.204043*tin[1] + 1.057311*tin[2]); break; default: break; } }
/////////////////////////////////////////////////////////////////////// // Class : CShadingContext // Method : convertColorTo // Description : Do color conversion // Return Value : - // Comments : void convertColorTo(float *out,const float *in,ECoordinateSystem s) { switch(s) { case COLOR_RGB: movvv(out,in); break; case COLOR_HSL: { float mi = min(in[0],min(in[1],in[2])); float ma = max(in[0],max(in[1],in[2])); out[2] = (mi + ma) / 2; if (ma == mi) { out[0] = 100;// install value out of -1 to 1 range out[1] = 0; } else { float d = ma - mi; if (out[2] < 0.5) { out[1] = d / (ma + mi); } else { out[1] = d / (2 - (ma + mi)); } if (in[COMP_R] == ma) { out[0] = (in[COMP_G] - in[COMP_B])/d; } else if (in[COMP_G] == ma) { out[0] = 2 + (in[COMP_B] - in[COMP_R])/d; } else { out[0] = 4 + (in[COMP_R] - in[COMP_G])/d; } out[0] /= (float) 6; if (out[0] < 0) out[0] += 1; } } break; case COLOR_HSV: { float ma = max(in[0],max(in[1],in[2])); float mi = min(in[0],min(in[1],in[2])); out[2] = ma; out[1] = (ma - mi) / ma; if (ma == 0) { out[0] = 100;// install value out of -1 to 1 range } else { float d = ma - mi; if (in[COMP_R] == ma) { out[0] = (in[COMP_G] - in[COMP_B]) / d; } else if (in[COMP_G] == ma) { out[0] = 2 + (in[COMP_B] - in[COMP_R]) / d; } else { out[0] = 4 + (in[COMP_R] - in[COMP_G]) / d; } out[0] /= (float) 6; if (out[0] < 0) out[0] += 1; } } break; case COLOR_XYZ: out[0] = (float) (0.412453 * in[COMP_R] + 0.357580 * in[COMP_G] + 0.180423 * in[COMP_B]); out[1] = (float) (0.212671 * in[COMP_R] + 0.715160 * in[COMP_G] + 0.072169 * in[COMP_B]); out[2] = (float) (0.019334 * in[COMP_R] + 0.119193 * in[COMP_G] + 0.950227 * in[COMP_B]); break; case COLOR_CIE: out[0] = (float) (0.412453 * in[COMP_R] + 0.357580 * in[COMP_G] + 0.180423 * in[COMP_B]); out[1] = (float) (0.212671 * in[COMP_R] + 0.715160 * in[COMP_G] + 0.072169 * in[COMP_B]); out[2] = (float) (0.019334 * in[COMP_R] + 0.119193 * in[COMP_G] + 0.950227 * in[COMP_B]); break; case COLOR_YIQ: out[0] = (float) (0.299 * in[COMP_R] + 0.587 * in[COMP_G] + 0.114 * in[COMP_B]); out[1] = (float) (0.596 * in[COMP_R] - 0.275 * in[COMP_G] - 0.321 * in[COMP_B]); out[2] = (float) (0.212 * in[COMP_R] - 0.523 * in[COMP_G] + 0.311 * in[COMP_B]); break; case COLOR_XYY: vector tin; float sum; tin[0] = (float) (0.412453 * in[COMP_R] + 0.357580 * in[COMP_G] + 0.180423 * in[COMP_B]); tin[1] = (float) (0.212671 * in[COMP_R] + 0.715160 * in[COMP_G] + 0.072169 * in[COMP_B]); tin[2] = (float) (0.019334 * in[COMP_R] + 0.119193 * in[COMP_G] + 0.950227 * in[COMP_B]); sum = tin[0] + tin[1] + tin[2]; if (sum == 0) { initv(out,0,0,0); } else { out[0] = tin[0] / sum; out[1] = tin[1] / sum; out[2] = tin[2]; } break; default: break; } }
/////////////////////////////////////////////////////////////////////// // Class : CIrradianceCache // Method : sample // Description : Sample the occlusion // Return Value : // Comments : void CIrradianceCache::sample(float *C,const float *P,const float *dPdu,const float *dPdv,const float *N,CShadingContext *context) { CCacheSample *cSample; int i,j; float coverage; vector irradiance; vector envdir; float rMean; CRay ray; vector X,Y; CCacheNode *cNode; int depth; // Allocate memory const CShadingScratch *scratch = &(context->currentShadingState->scratch); const int nt = (int) (sqrtf(scratch->traceParams.samples / (float) C_PI) + 0.5); const int np = (int) (C_PI*nt + 0.5); const int numSamples = nt*np; CHemisphereSample *hemisphere = (CHemisphereSample *) alloca(numSamples*sizeof(CHemisphereSample)); // initialize texture lookups if needed if (scratch->occlusionParams.environment) { CTextureLookup::staticInit(&(context->currentShadingState->scratch)); } // Create an orthanormal coordinate system if (dotvv(dPdu,dPdu) > 0) { normalizevf(X,dPdu); crossvv(Y,N,X); } else if (dotvv(dPdv,dPdv) > 0) { normalizevf(X,dPdv); crossvv(Y,N,X); } else { // At this point, we're pretty screwed, so why not use the P normalizevf(X,P); crossvv(Y,N,X); } // Sample the hemisphere coverage = 0; initv(irradiance,0); initv(envdir,0); rMean = C_INFINITY; // Calculate the ray differentials (use average spread in theta and phi) const float da = tanf((float) C_PI/(2*(nt+np))); const float db = (lengthv(dPdu) + lengthv(dPdv))*0.5f; if (scratch->occlusionParams.occlusion == TRUE) { // We're shading for occlusion context->numOcclusionRays += numSamples; context->numOcclusionSamples++; for (i=0;i<nt;i++) { for (j=0;j<np;j++,hemisphere++) { float rv[2]; context->random2d.get(rv); float tmp = sqrtf((i+context->urand()) / (float) nt); const float phi = (float) (2*C_PI*(j+context->urand()) / (float) np); const float cosPhi = (cosf(phi)*tmp); const float sinPhi = (sinf(phi)*tmp); tmp = sqrtf(1 - tmp*tmp); ray.dir[0] = X[0]*cosPhi + Y[0]*sinPhi + N[0]*tmp; ray.dir[1] = X[1]*cosPhi + Y[1]*sinPhi + N[1]*tmp; ray.dir[2] = X[2]*cosPhi + Y[2]*sinPhi + N[2]*tmp; const float originJitterX = (rv[0] - 0.5f)*scratch->traceParams.sampleBase; const float originJitterY = (rv[1] - 0.5f)*scratch->traceParams.sampleBase; ray.from[COMP_X] = P[COMP_X] + originJitterX*dPdu[0] + originJitterY*dPdv[0]; ray.from[COMP_Y] = P[COMP_Y] + originJitterX*dPdu[1] + originJitterY*dPdv[1]; ray.from[COMP_Z] = P[COMP_Z] + originJitterX*dPdu[2] + originJitterY*dPdv[2]; ray.flags = ATTRIBUTES_FLAGS_DIFFUSE_VISIBLE; ray.tmin = scratch->traceParams.bias; ray.t = scratch->traceParams.maxDist; ray.time = 0; ray.da = da; ray.db = db; // Transform the ray into the right coordinate system mulmp(ray.from,from,ray.from); mulmv(ray.dir,from,ray.dir); context->trace(&ray); // Do we have an intersection ? if (ray.object != NULL) { const float *color = ray.object->attributes->surfaceColor; // Yes coverage++; addvv(irradiance,color); hemisphere->coverage = 1; initv(hemisphere->envdir,0); movvv(hemisphere->irradiance,color); } else { // No hemisphere->coverage = 0; addvv(envdir,ray.dir); movvv(hemisphere->envdir,ray.dir); // GSH : Texture lookup for misses if(scratch->occlusionParams.environment != NULL){ CEnvironment *tex = scratch->occlusionParams.environment; vector D0,D1,D2,D3; vector color; // GSHTODO: Add in the dCosPhi and dSinPhi movvv(D0,ray.dir); movvv(D1,ray.dir); movvv(D2,ray.dir); movvv(D3,ray.dir); float savedSamples = scratch->traceParams.samples; context->currentShadingState->scratch.traceParams.samples = 1; tex->lookup(color,D0,D1,D2,D3,context); context->currentShadingState->scratch.traceParams.samples = savedSamples; addvv(irradiance,color); movvv(hemisphere->irradiance,color); } else{ initv(hemisphere->irradiance,0); } } hemisphere->depth = ray.t; hemisphere->invDepth = 1 / ray.t; if (tmp > horizonCutoff) rMean = min(rMean,ray.t); movvv(hemisphere->dir,ray.dir); assert(hemisphere->invDepth > 0); } } } else { // We're shading for indirectdiffuse context->numIndirectDiffuseRays += numSamples; context->numIndirectDiffuseSamples++; for (i=0;i<nt;i++) { for (j=0;j<np;j++,hemisphere++) { float rv[2]; context->random2d.get(rv); float tmp = sqrtf((i+context->urand()) / (float) nt); const float phi = (float) (2*C_PI*(j+context->urand()) / (float) np); const float cosPhi = (cosf(phi)*tmp); const float sinPhi = (sinf(phi)*tmp); tmp = sqrtf(1 - tmp*tmp); ray.dir[0] = X[0]*cosPhi + Y[0]*sinPhi + N[0]*tmp; ray.dir[1] = X[1]*cosPhi + Y[1]*sinPhi + N[1]*tmp; ray.dir[2] = X[2]*cosPhi + Y[2]*sinPhi + N[2]*tmp; const float originJitterX = (rv[0] - 0.5f)*scratch->traceParams.sampleBase; const float originJitterY = (rv[1] - 0.5f)*scratch->traceParams.sampleBase; ray.from[COMP_X] = P[COMP_X] + originJitterX*dPdu[0] + originJitterY*dPdv[0]; ray.from[COMP_Y] = P[COMP_Y] + originJitterX*dPdu[1] + originJitterY*dPdv[1]; ray.from[COMP_Z] = P[COMP_Z] + originJitterX*dPdu[2] + originJitterY*dPdv[2]; ray.flags = ATTRIBUTES_FLAGS_DIFFUSE_VISIBLE; ray.tmin = scratch->traceParams.bias; ray.t = scratch->traceParams.maxDist; ray.time = 0; ray.da = da; ray.db = db; // Transform the ray into the right coordinate system mulmp(ray.from,from,ray.from); mulmv(ray.dir,from,ray.dir); context->trace(&ray); // Do we have an intersection ? if (ray.object != NULL) { vector P,N,C; CAttributes *attributes = ray.object->attributes; CPhotonMap *globalMap; if ((globalMap = attributes->globalMap) != NULL) { normalizev(N,ray.N); mulvf(P,ray.dir,ray.t); addvv(P,ray.from); if(dotvv(ray.dir,N) > 0) mulvf(N,-1); globalMap->lookup(C,P,N,attributes->photonEstimator); // HACK: Avoid too bright spots tmp = max(max(C[0],C[1]),C[2]); if (tmp > scratch->occlusionParams.maxBrightness) mulvf(C,scratch->occlusionParams.maxBrightness/tmp); mulvv(C,attributes->surfaceColor); addvv(irradiance,C); movvv(hemisphere->irradiance,C); context->numIndirectDiffusePhotonmapLookups++; } else { initv(hemisphere->irradiance,0); } // Yes coverage++; hemisphere->coverage = 1; initv(hemisphere->envdir,0); } else { // No hemisphere->coverage = 0; addvv(envdir,ray.dir); movvv(hemisphere->envdir,ray.dir); // GSH : Texture lookup for misses if(scratch->occlusionParams.environment != NULL){ CEnvironment *tex = scratch->occlusionParams.environment; vector D0,D1,D2,D3; vector color; // GSHTODO: Add in the dCosPhi and dSinPhi movvv(D0,ray.dir); movvv(D1,ray.dir); movvv(D2,ray.dir); movvv(D3,ray.dir); float savedSamples = scratch->traceParams.samples; context->currentShadingState->scratch.traceParams.samples = 1; tex->lookup(color,D0,D1,D2,D3,context); context->currentShadingState->scratch.traceParams.samples = savedSamples; addvv(irradiance,color); movvv(hemisphere->irradiance,color); } else{ movvv(hemisphere->irradiance,scratch->occlusionParams.environmentColor); addvv(irradiance,scratch->occlusionParams.environmentColor); } } hemisphere->depth = ray.t; hemisphere->invDepth = 1 / ray.t; if (tmp > horizonCutoff) rMean = min(rMean,ray.t); movvv(hemisphere->dir,ray.dir); assert(hemisphere->invDepth > 0); } } } hemisphere -= np*nt; // Normalize const float tmp = 1 / (float) numSamples; coverage *= tmp; mulvf(irradiance,tmp); normalizevf(envdir); // Record the value C[0] = irradiance[0]; C[1] = irradiance[1]; C[2] = irradiance[2]; C[3] = coverage; C[4] = envdir[0]; C[5] = envdir[1]; C[6] = envdir[2]; // Should we save it ? if ((scratch->occlusionParams.maxError != 0) && (coverage < 1-C_EPSILON)) { // We're modifying, lock the thing osLock(mutex); // Create the sample cSample = (CCacheSample *) memory->alloc(sizeof(CCacheSample)); // Compute the gradients of the illumination posGradient(cSample->gP,np,nt,hemisphere,X,Y); rotGradient(cSample->gR,np,nt,hemisphere,X,Y); // Compute the radius of validity rMean *= 0.5f; // Clamp the radius of validity rMean = min(rMean,db*scratch->occlusionParams.maxPixelDist); // Record the data (in the target coordinate system) movvv(cSample->P,P); movvv(cSample->N,N); cSample->dP = rMean; cSample->coverage = coverage; movvv(cSample->envdir,envdir); movvv(cSample->irradiance,irradiance); // Do the neighbour clamping trick clamp(cSample); rMean = cSample->dP; // copy dP back so we get the right place in the octree // The error multiplier const float K = 0.4f / scratch->occlusionParams.maxError; rMean /= K; // Insert the new sample into the cache cNode = root; depth = 0; while(cNode->side > (2*rMean)) { depth++; for (j=0,i=0;i<3;i++) { if (P[i] > cNode->center[i]) { j |= 1 << i; } } if (cNode->children[j] == NULL) { CCacheNode *nNode = (CCacheNode *) memory->alloc(sizeof(CCacheNode)); for (i=0;i<3;i++) { if (P[i] > cNode->center[i]) { nNode->center[i] = cNode->center[i] + cNode->side*0.25f; } else { nNode->center[i] = cNode->center[i] - cNode->side*0.25f; } } cNode->children[j] = nNode; nNode->side = cNode->side*0.5f; nNode->samples = NULL; for (i=0;i<8;i++) nNode->children[i] = NULL; } cNode = cNode->children[j]; } cSample->next = cNode->samples; cNode->samples = cSample; maxDepth = max(depth,maxDepth); osUnlock(mutex); } }
/////////////////////////////////////////////////////////////////////// // Class : CIrradianceCache // Method : lookup // Description : Lookup da cache // Return Value : // Comments : void CIrradianceCache::lookup(float *C,const float *cP,const float *cdPdu,const float *cdPdv,const float *cN,CShadingContext *context) { const CShadingScratch *scratch = &(context->currentShadingState->scratch); // Is this a point based lookup? if ((scratch->occlusionParams.pointbased) && (scratch->occlusionParams.pointHierarchy != NULL)) { int i; for (i=0;i<7;i++) C[i] = 0; scratch->occlusionParams.pointHierarchy->lookup(C,cP,cdPdu,cdPdv,cN,context); } else { CCacheSample *cSample; CCacheNode *cNode; float totalWeight = 0; CCacheNode **stackBase = (CCacheNode **) alloca(maxDepth*sizeof(CCacheNode *)*8); CCacheNode **stack; int i; float coverage; vector irradiance,envdir; vector P,N; // A small value for discard-smoothing of irradiance const float smallSampleWeight = (flags & CACHE_SAMPLE) ? 0.1f : 0.0f; // Transform the lookup point to the correct coordinate system mulmp(P,to,cP); mulmn(N,from,cN); // Init the result coverage = 0; initv(irradiance,0); initv(envdir,0); // The weighting algorithm is that described in [Tabellion and Lamorlette 2004] // We need to convert the max error as in Wald to Tabellion // The default value of maxError is 0.4f const float K = 0.4f / scratch->occlusionParams.maxError; // Note, we do not need to lock the data for reading // if word-writes are atomic // Prepare for the non recursive tree traversal stack = stackBase; *stack++ = root; while(stack > stackBase) { cNode = *(--stack); // Sum the values in this level for (cSample=cNode->samples;cSample!=NULL;cSample=cSample->next) { vector D; // D = vector from sample to query point subvv(D,P,cSample->P); // Ignore sample in the front float a = dotvv(D,cSample->N); if ((a*a / (dotvv(D,D) + C_EPSILON)) > 0.1) continue; // Positional error float e1 = sqrtf(dotvv(D,D)) / cSample->dP; // Directional error float e2 = 1 - dotvv(N,cSample->N); if (e2 < 0) e2 = 0; e2 = sqrtf(e2*weightNormalDenominator); // Compute the weight float w = 1 - K*max(e1,e2); if (w > context->urand()*smallSampleWeight) { vector ntmp; crossvv(ntmp,cSample->N,N); // Sum the sample totalWeight += w; coverage += w*(cSample->coverage + dotvv(cSample->gP+0*3,D) + dotvv(cSample->gR+0*3,ntmp)); irradiance[0] += w*(cSample->irradiance[0] + dotvv(cSample->gP+1*3,D) + dotvv(cSample->gR+1*3,ntmp)); irradiance[1] += w*(cSample->irradiance[1] + dotvv(cSample->gP+2*3,D) + dotvv(cSample->gR+2*3,ntmp)); irradiance[2] += w*(cSample->irradiance[2] + dotvv(cSample->gP+3*3,D) + dotvv(cSample->gR+3*3,ntmp)); envdir[0] += w*(cSample->envdir[0] + dotvv(cSample->gP+4*3,D) + dotvv(cSample->gR+4*3,ntmp)); envdir[1] += w*(cSample->envdir[1] + dotvv(cSample->gP+5*3,D) + dotvv(cSample->gR+5*3,ntmp)); envdir[2] += w*(cSample->envdir[2] + dotvv(cSample->gP+6*3,D) + dotvv(cSample->gR+6*3,ntmp)); } } // Check the children for (i=0;i<8;i++) { CCacheNode *tNode; if ((tNode = cNode->children[i]) != NULL) { const float tSide = tNode->side; if ( ((tNode->center[0] + tSide) > P[0]) && ((tNode->center[1] + tSide) > P[1]) && ((tNode->center[2] + tSide) > P[2]) && ((tNode->center[0] - tSide) < P[0]) && ((tNode->center[1] - tSide) < P[1]) && ((tNode->center[2] - tSide) < P[2])) { *stack++ = tNode; } } } } // Do we have anything ? if (totalWeight > C_EPSILON) { double normalizer = 1 / totalWeight; normalizevf(envdir); C[0] = (float) (irradiance[0]*normalizer); C[1] = (float) (irradiance[1]*normalizer); C[2] = (float) (irradiance[2]*normalizer); C[3] = (float) (coverage*normalizer); mulmv(C+4,from,envdir); // envdir is stored in the target coordinate system } else { // Are we sampling the cache ? if (flags & CACHE_SAMPLE) { vector dPdu,dPdv; // Convert the tangent space mulmv(dPdu,to,cdPdu); mulmv(dPdv,to,cdPdv); // Create a new sample sample(C,P,dPdu,dPdv,N,context); mulmv(C+4,from,C+4); // envdir is stored in the target coordinate system } else { // No joy C[0] = 0; C[1] = 0; C[2] = 0; C[3] = 1; C[4] = 0; C[5] = 0; C[6] = 0; } } // Make sure we don't have NaNs assert(dotvv(C,C) >= 0); } }
/////////////////////////////////////////////////////////////////////// // Class : CAttributes // Method : CAttributes // Description : The constructor, the default values for // attributes are given here // Return Value : - // Comments : CAttributes::CAttributes() { next = NULL; atomicIncrement(&stats.numAttributes); surface = NULL; displacement = NULL; atmosphere = NULL; interior = NULL; exterior = NULL; usedParameters = 0; initv(surfaceColor,1,1,1); initv(surfaceOpacity,1,1,1); s[0] = 0.0; s[1] = 1.0; s[2] = 0.0; s[3] = 1.0; t[0] = 0.0; t[1] = 0.0; t[2] = 1.0; t[3] = 1.0; initv(bmin,C_INFINITY,C_INFINITY,C_INFINITY); initv(bmax,-C_INFINITY,-C_INFINITY,-C_INFINITY); bexpand = 0.00001f; // Epsilon { int i,j; for (i=0;i<4;i++) for (j=0;j<4;j++) { uBasis[element(i,j)] = RiBezierBasis[i][j]; vBasis[element(i,j)] = RiBezierBasis[i][j]; } } uStep = 3; vStep = 3; flags = 0; flags |= ATTRIBUTES_FLAGS_PRIMARY_VISIBLE; flags |= ATTRIBUTES_FLAGS_DOUBLE_SIDED; maxDisplacement = 0; maxDisplacementSpace = NULL; lightSources = NULL; shadingRate = 1.0f; motionFactor = 0.0f; name = NULL; numUProbes = 4; numVProbes = 4; minSplits = 0; // This should no longer be needed with convergent dicing rasterExpand = 0.5f; // This could be significantly lowered for many primitives bias = 0.01f; transmissionHitMode = 'p'; diffuseHitMode = 'p'; cameraHitMode = 's'; specularHitMode = 's'; emit = -1; relativeEmit = 1; shadingModel = SM_MATTE; globalMapName = NULL; causticMapName = NULL; globalMap = NULL; causticMap = NULL; irradianceHandle = strdup(""); irradianceHandleMode = strdup("w"); irradianceMaxError = 0.6f; irradianceMaxPixelDistance = 20.0f; photonEstimator = 100; photonIor[0] = 1.5; photonIor[1] = 1.5; maxDiffuseDepth = 1; maxSpecularDepth = 2; shootStep = 1000; // Shoot 1000 rays at a time lodRange[0] = -C_INFINITY; lodRange[1] = -C_INFINITY; lodRange[2] = C_INFINITY; lodRange[3] = C_INFINITY; lodSize = 0; lodImportance = 1; checkParameters(); }
/////////////////////////////////////////////////////////////////////// // Class : CPointHierarchy // Method : cluster // Description : /// \brief Cluster the items // Return Value : - // Comments : int CPointHierarchy::cluster(int numItems,int *indices) { // Sanity check assert(numItems > 0); if (numItems == 1) { // Create a leaf return -indices[0]; } else if (numItems == 2) { // Easy case int nodeIndex = average(numItems,indices); CMapNode *node = nodes.array + nodeIndex; node->child0 = -indices[0]; node->child1 = -indices[1]; return nodeIndex; } else { // Allocate temp memory int *membership,*subItems; // Use alloca if the allocation size is low enough if (numItems >= ALLOCA_MAX_ITEMS) membership = new int[numItems*2]; else membership = (int *) alloca(numItems*2*sizeof(int)); subItems = membership + numItems; vector bmin,bmax; initv(bmin,C_INFINITY); initv(bmax,-C_INFINITY); // The membership is dummy ... Also compute the bounding box of the point set for (int i=0;i<numItems;i++) { membership[i] = -1; addBox(bmin,bmax,CMap<CPointCloudPoint>::items[indices[i]].P); } vector C0,C1; // The cluster centers vector N0,N1; // The cluster normals // Create random cluster centers initv(C0, _urand()*(bmax[0]-bmin[0]) + bmin[0], _urand()*(bmax[1]-bmin[1]) + bmin[1], _urand()*(bmax[2]-bmin[2]) + bmin[2]); initv(C1, _urand()*(bmax[0]-bmin[0]) + bmin[0], _urand()*(bmax[1]-bmin[1]) + bmin[1], _urand()*(bmax[2]-bmin[2]) + bmin[2]); // Create random cluster normals initv(N0, _urand()*2-1, _urand()*2-1, _urand()*2-1); initv(N1, _urand()*2-1, _urand()*2-1, _urand()*2-1); normalizevf(N0); normalizevf(N1); // Perform the clustering iterations int num0,num1; for (int iterations=0;iterations<5;iterations++) { // Try 5 times ... Not until convergence int changed = FALSE; vector nC0,nC1; vector nN0,nN1; // Clear the data initv(nC0,0); initv(nC1,0); initv(nN0,0); initv(nN1,0); num0 = 0; num1 = 0; // iterate over items for (int i=0;i<numItems;i++) { vector D; const CPointCloudPoint *cItem = CMap<CPointCloudPoint>::items + indices[i]; // Compute the distance to the first cluster subvv(D,cItem->P,C0); const float d0 = dotvv(D,D) / max(dotvv(N0,cItem->N),C_EPSILON); // Compute the distance to the second cluster subvv(D,cItem->P,C1); const float d1 = dotvv(D,D) / max(dotvv(N1,cItem->N),C_EPSILON); // Change the membership if necessary if (d0 < d1) { if (membership[i] != 0) { changed = TRUE; membership[i] = 0; } addvv(nC0,cItem->P); addvv(nN0,cItem->N); num0++; } else { if (membership[i] != 1) { changed = TRUE; membership[i] = 1; } addvv(nC1,cItem->P); addvv(nN1,cItem->N); num1++; } } // Check for degenerate cases if ((num0 == 0) || (num1 == 0)) { initv(C0, _urand()*(bmax[0]-bmin[0]) + bmin[0], _urand()*(bmax[1]-bmin[1]) + bmin[1], _urand()*(bmax[2]-bmin[2]) + bmin[2]); initv(C1, _urand()*(bmax[0]-bmin[0]) + bmin[0], _urand()*(bmax[1]-bmin[1]) + bmin[1], _urand()*(bmax[2]-bmin[2]) + bmin[2]); initv(N0, _urand()*2-1, _urand()*2-1, _urand()*2-1); initv(N1, _urand()*2-1, _urand()*2-1, _urand()*2-1); normalizevf(N0); normalizevf(N1); } else { if (changed == FALSE) break; mulvf(C0,nC0,1 / (float) num0); mulvf(C1,nC1,1 / (float) num1); // Normalize the normal vectors normalizevf(N0,nN0); normalizevf(N1,nN1); } } // Do we have a bad clustering? while (num0 == 0 || num1 == 0) { // Clustering failed - probably coincident points, make an arbitrary split num0 = num1 = 0; for (int i=0;i<numItems;i++) { const int which = i & 1; if (which) num1++; else num0++; membership[i] = which; } // FIXME: A smarter thing to do would be to sort the items in one dimension and split it in half } assert((num0 + num1) == numItems); // Average the items and create an internal node const int nodeIndex = average(numItems,indices); // OK, split the items into two int i,j; // Collect the items in the first child for (i=0,j=0;i<numItems;i++) if (membership[i] == 0) subItems[j++] = indices[i]; assert(j == num0); const int child0 = cluster(num0,subItems); // Collect the items in the second child for (i=0,j=0;i<numItems;i++) if (membership[i] == 1) subItems[j++] = indices[i]; assert(j == num1); const int child1 = cluster(num1,subItems); // NOTE: There's an important subtlety here... // We can not access cNode before the child nodes are created because the creation of children // may change the nodes.array field CMapNode *cNode = nodes.array + nodeIndex; cNode->child0 = child0; cNode->child1 = child1; // Reclaim the memory if applicable if (numItems >= ALLOCA_MAX_ITEMS) delete [] membership; // Return the index of the node return nodeIndex; } }
/////////////////////////////////////////////////////////////////////// // Class : COptions // Method : COptions // Description : /// \brief All the default frame specific settings are defined here // Return Value : - // Comments : COptions::COptions() { atomicIncrement(&stats.numOptions); xres = 640; yres = 480; frame = -1; pixelAR = 1; frameAR = 4.0f/3.0f; cropLeft = 0; cropRight = 1; cropTop = 0; cropBottom = 1; screenLeft = -4.0f/3.0f; screenRight = 4.0f/3.0f; screenTop = 1; screenBottom = -1; clipMin = C_EPSILON; clipMax = C_INFINITY; pixelVariance = 0.05f; jitter = 0.99f; hider = strdup("stochastic"); #ifdef __APPLE__ // Support for finding resources in Mac OS X bundles and standard Mac OS X file system locations // Find the application bundle's plug-in and Resources directory char path[OS_MAX_PATH_LENGTH]; char pathtmp[OS_MAX_PATH_LENGTH]; CFBundleRef bundle = CFBundleGetMainBundle(); if (bundle) { CFURLRef url = CFBundleCopyBuiltInPlugInsURL(bundle); if (url) { Boolean validpath = CFURLGetFileSystemRepresentation(url,true,(UInt8*)path,OS_MAX_PATH_LENGTH); if (validpath) setenv("PIXIEAPPPLUGINS", (const char*)path, 1); CFRelease(url); } url = CFBundleCopyResourcesDirectoryURL(bundle); if (url) { Boolean validpath = CFURLGetFileSystemRepresentation(url,true,(UInt8*)path,OS_MAX_PATH_LENGTH); if (validpath) setenv("PIXIEAPPRESOURCES", (const char*)path, 1); CFRelease(url); } CFRelease(bundle); } // Find the application support directory (~/Library/Application Support/Pixie/PlugIns), and set the // PIXIEUSERDIR environment variable to that directory FSRef appsupport; if (FSFindFolder(kUserDomain, kApplicationSupportFolderType, kCreateFolder, &appsupport) == noErr) { FSRefMakePath(&appsupport, (UInt8*)path, OS_MAX_PATH_LENGTH); sprintf(pathtmp, "%s/" PACKAGE, path); mkdir(pathtmp, 0755); setenv("PIXIEUSERDIR", (const char*)pathtmp, 1); } // Find the application support directory (/Library/Application Support/Pixie/PlugIns), and set the // PIXIELOCALDIR environment variable to that directory if (FSFindFolder(kLocalDomain, kApplicationSupportFolderType, kCreateFolder, &appsupport) == noErr) { FSRefMakePath(&appsupport, (UInt8*)path, OS_MAX_PATH_LENGTH); snprintf(pathtmp, OS_MAX_PATH_LENGTH, "%s/" PACKAGE, path); mkdir(pathtmp, 0755); setenv("PIXIELOCALDIR", (const char*)pathtmp, 1); } // Default home, unless overridden with environment setenv("PIXIEHOME","/Library/Pixie",0); archivePath = optionsGetSearchPath(".:%RIBS%:%PIXIEHOME%/ribs" ,NULL); proceduralPath = optionsGetSearchPath(".:%PROCEDURALS%:%PIXIEUSERDIR%/procedurals:%PIXIELOCALDIR%/procedurals:%PIXIEAPPPLUGINS%:%PIXIEHOME%/procedurals",NULL); texturePath = optionsGetSearchPath(".:%TEXTURES%:%PIXIEUSERDIR%/textures:%PIXIELOCALDIR%/textures:%PIXIEAPPRESOURCES%/textures:%PIXIEHOME%/textures",NULL); shaderPath = optionsGetSearchPath(".:%SHADERS%:%PIXIEUSERDIR%/shaders:%PIXIELOCALDIR%/shaders:%PIXIEAPPRESOURCES%/shaders:%PIXIEHOME%/shaders",NULL); displayPath = optionsGetSearchPath("%DISPLAYS%:%PIXIEUSERDIR%/displays:%PIXIELOCALDIR%/displays:%PIXIEAPPPLUGINS%:%PIXIEHOME%/displays",NULL); modulePath = optionsGetSearchPath("%MODULES%:%PIXIEUSERDIR%/modules:%PIXIELOCALDIR%/modules:%PIXIEAPPPLUGINS%:%PIXIEHOME%/modules",NULL); #else archivePath = optionsGetSearchPath(".:%RIBS%:" PIXIE_RIBS,NULL); proceduralPath = optionsGetSearchPath(".:%PROCEDURALS%:" PIXIE_PROCEDURALS,NULL); texturePath = optionsGetSearchPath(".:%TEXTURES%:" PIXIE_TEXTURES,NULL); shaderPath = optionsGetSearchPath(".:%SHADERS%:" PIXIE_SHADERS,NULL); displayPath = optionsGetSearchPath(".:%DISPLAYS%:" PIXIE_DISPLAYS,NULL); modulePath = optionsGetSearchPath(".:%MODULES%:" PIXIE_MODULES,NULL); #endif pixelXsamples = 2; pixelYsamples = 2; gamma = 1; gain = 1; pixelFilterWidth = 2; pixelFilterHeight = 2; pixelFilter = RiCatmullRomFilter; colorQuantizer[0] = 0; // Zero colorQuantizer[1] = 255; // One colorQuantizer[2] = 0; // Min colorQuantizer[3] = 255; // Max colorQuantizer[4] = 0.5; depthQuantizer[0] = 0; // Zero depthQuantizer[1] = 0; // One depthQuantizer[2] = 0; // Min depthQuantizer[3] = 0; // Max depthQuantizer[4] = 0; initv(opacityThreshold,0.996f); initv(zvisibilityThreshold,0.996f); // We default to sampling motion, but this can be turned off. // Additionally, if there's no motionblur in the scene, it will be turned off flags = OPTIONS_FLAGS_SAMPLEMOTION; displays = NULL; clipPlanes = NULL; relativeDetail = 1; projection = OPTIONS_PROJECTION_ORTHOGRAPHIC; fov = 90; nColorComps = 3; fromRGB = NULL; toRGB = NULL; fstop = C_INFINITY; focallength = 1; focaldistance = 1; shutterOpen = 0; shutterClose = 0; shutterOffset = 0; endofframe = 0; filelog = NULL; numThreads = osAvailableCPUs(); if (numThreads < 1) numThreads = DEFAULT_NUM_THREADS; maxTextureSize = DEFAULT_MAX_TEXTURESIZE; maxBrickSize = DEFAULT_MAX_BRICKSIZE; maxGridSize = DEFAULT_MAX_GRIDSIZE; maxRayDepth = 5; maxPhotonDepth = 10; bucketWidth = DEFAULT_TILE_WIDTH; bucketHeight = DEFAULT_TILE_HEIGHT; netXBuckets = DEFAULT_NET_XBUCKETS; netYBuckets = DEFAULT_NET_YBUCKETS; threadStride = DEFAULT_THREAD_STRIDE; geoCacheMemory = DEFAULT_GEO_CACHE_SIZE; maxEyeSplits = 10; tsmThreshold = DEFAULT_TSM_THRESHOLD; causticIn = NULL; causticOut = NULL; globalIn = NULL; globalOut = NULL; numEmitPhotons = 10000; shootStep = 1000; depthFilter = DEPTH_MIN; }
double gmuon_(void) { /*compute the total g-2 from supersymmetry. Parameters are : Mmu : muon mass Mz : Z-boson's mass Mw : W-boson's mass s2thw : sin^2(thw) e : alpha modM1 & argM1 : modulus and argument of M1 modM2 & argM2 : modulus and argument of M2 modmu & argmu : modulus and argument of mu modAmu & argAmu : modulus and argument of Amu */ /*declaration des variables*/ double thw, cb,cw,sw, ymu, g1,masssneutr, g2,gmuo = 0,beta,Mz,Mw,Mmu,e,tbeta; matrix massmatrc,massmatrn,massmatrsmu; matrix Ncomp, Nconj,N,Ucomp,Uconj,U,Vcomp,Vconj,V,X,Xconj,Xcomp; vecteur massen,massec,massesmu; double coeff1 ,coeff2; matrix matrixtemp,matrixtemp2,matrixtemp3,matrixtemp4,matrixtemp5; my_complex nc1,nc2; int i,j; /*Memory Allocation*/ massmatrn=initm(4); massmatrc=initm(2); massmatrsmu=initm(2); Ncomp=initm(4); Nconj=initm(4); N=initm(4); Ucomp=initm(2); Vcomp=initm(2); X=initm(2); U=initm(2); V=initm(2); Uconj=initm(2); Vconj=initm(2); Xcomp=initm(2); Xconj=initm(2); massen=initv(4); massesmu=initv(2); massec=initv(2); matrixtemp=initm(2); matrixtemp2=initm(2); matrixtemp3=initm(4); matrixtemp4=initm(4); matrixtemp5=initm(4); /*Get the values for the masses and mixing matrices*/ e=sqrt(4*M_PI*0.00781653); sw=0.48076; Mz=91.1876; Mmu=0.1057; findVal("tB",&tbeta); beta = atan(tbeta); cb = cos(beta); thw=asin(sw); cw=cos(thw); Mw=Mz*cw; g1 = e/cw; g2 = e/sw; ymu = g2 * Mmu / (sqrt(2)*cb*Mw); findVal("MNE1",&massen.e[0].r); findVal("MNE2",&massen.e[1].r); findVal("MNE3",&massen.e[2].r); findVal("MNE4",&massen.e[3].r); findVal("MC1",&massec.e[0].r); findVal("MC2",&massec.e[1].r); findVal("MSnm",&masssneutr); findVal("Zn11",&Nconj.e[0][0].r); findVal("Zn12",&Nconj.e[1][0].r); findVal("Zn13",&Nconj.e[2][0].r); findVal("Zn14",&Nconj.e[3][0].r); findVal("Zn21",&Nconj.e[0][1].r); findVal("Zn22",&Nconj.e[1][1].r); findVal("Zn23",&Nconj.e[2][1].r); findVal("Zn24",&Nconj.e[3][1].r); findVal("Zn31",&Nconj.e[0][2].r); findVal("Zn32",&Nconj.e[1][2].r); findVal("Zn33",&Nconj.e[2][2].r); findVal("Zn34",&Nconj.e[3][2].r); findVal("Zn41",&Nconj.e[0][3].r); findVal("Zn42",&Nconj.e[1][3].r); findVal("Zn43",&Nconj.e[2][3].r); findVal("Zn44",&Nconj.e[3][3].r); findVal("Zu11",&Uconj.e[0][0].r); findVal("Zu12",&Uconj.e[1][0].r); findVal("Zu21",&Uconj.e[0][1].r); findVal("Zu22",&Uconj.e[1][1].r); findVal("Zv11",&Vcomp.e[0][0].r); findVal("Zv12",&Vcomp.e[0][1].r); findVal("Zv21",&Vcomp.e[1][0].r); findVal("Zv22",&Vcomp.e[1][1].r); { double MSmuLL,MSmuRR,MSmuLR,Am,mu,MSmuth; MSmuLL=findValW("MSmL"); MSmuLL*=MSmuLL; MSmuRR=findValW("MSmR"); MSmuRR*=MSmuRR; Am=findValW("Am"); mu=findValW("mu"); MSmuLR=(Am-mu*tbeta)*Mmu; massesmu.e[0].r=sqrt((MSmuLL+MSmuRR-sqrt((MSmuLL-MSmuRR)*(MSmuLL-MSmuRR)+4*MSmuLR*MSmuLR))/2); massesmu.e[1].r=sqrt((MSmuLL+MSmuRR+sqrt((MSmuLL-MSmuRR)*(MSmuLL-MSmuRR)+4*MSmuLR*MSmuLR))/2); MSmuth=atan2(-2*MSmuLR, -MSmuLL+MSmuRR)/2; X.e[0][0].r=cos(MSmuth); X.e[0][1].r=sin(MSmuth); X.e[1][0].r=-X.e[0][1].r; X.e[1][1].r=X.e[0][0].r; } for(i=0;i<4;i++) if (massen.e[i].r<0) {for(j=0;j<4;j++) {Nconj.e[j][i]=prod(icomp,Nconj.e[j][i]); } massen.e[i].r=-massen.e[i].r; } for(i=0;i<2;i++) {if (massec.e[i].r<0) {for(j=0;j<2;j++) { Uconj.e [j][i]=prod(icomp,Uconj.e[j][i]); Vcomp.e [i][j]=prod(icomp,Vcomp.e[i][j]); } massec.e[i].r=-massec.e[i].r; } if (massesmu.e[i].r<0) {for(j=0;j<2;j++) {X.e [i][j]=prod(icomp,X.e[i][j]); } massesmu.e[i].r=-massesmu.e[i].r; } } N=adj(Nconj); U=adj(Uconj); /*Compute the coefficients entering the formula for the neutral and chargino contribution to g-2_muon and calculates gmuon*/ /*neutralinos*/ for ( i=0;i<4;i=i+1) for ( j=0;j<2;j=j+1) {nc1=somme(prodscal(sqrt(2)*g1,prod(N.e[i][0],X.e[j][1])),prodscal(ymu,prod(N.e[i][2],X.e[j][0]))); nc2=diff(prodscal(1/sqrt(2),prod(somme(prodscal(g2,N.e[i][1]),prodscal(g1,N.e[i][0])),conjug(X.e[j][0]))),prodscal(ymu,prod(N.e[i][2],conjug(X.e[j][1])))); coeff1 =(somme(prod(nc1,conjug(nc1)),prod(nc2,conjug(nc2)))).r; coeff2 = prod(nc1,nc2).r; if (massesmu.e[j].r<1e-8) {return 0; printf("erreur : Mass smuons nul\n");} gmuo=gmuo+calcgmuon (0,Mmu, massen.e[i].r, massesmu.e[j].r,coeff1, coeff2); } /*charginos*/ for (j=0;j<2;j=j+1) { nc1=prodscal(ymu,U.e[j][1]); nc2=prodscal(-g2,conjug(Vcomp.e[j][0])); coeff1 =(somme(prod(nc1,conjug(nc1)),prod(nc2,conjug(nc2)))).r; coeff2 = prod(nc1,nc2).r; if (masssneutr<1e-8) {return 0; printf("erreur : Mass sneutrinos nul\n");} gmuo=gmuo+calcgmuon (1,Mmu, massec.e[j].r, masssneutr,coeff1, coeff2); } return gmuo; }
int main() { unsigned int i,j,a,*SV; unsigned char logpi; int k,S,r,s1,s2,s,NS,logm,ptr,threshold,epri; long M,la,lptr; qsieve=gmpinit(-36,0); if(initv()<0) return 0; hmod=2*mlf+1; mpz_set_si(TA, hmod); while(!mpz_probab_prime_p(TA, qsieve->NTRY)) mpz_sub_ui(TA, TA, 2); //TT=不大于TT的素数 hmod=qsieve_getsize(TA); hmod2=hmod-2; for(k=0;k<hmod;k++) hash[k]=(-1); M=50*(long)mm; NS=(int)(M/SSIZE); if(M%SSIZE!=0) NS++; M=SSIZE*(long)NS; // M为不小于50*mm的SSIZE的倍数中最小的 from 以上四行 logm=0; la=M; while((la/=2)>0) logm++; // 以2为底 rp[0]=logp[0]=0; for(k=1;k<=mm;k++) //求k*N在每个素数下的二次剩余解,与每个素数的ln(pi) { r=mpz_tdiv_q_ui(TA, D, epr[k]); rp[k]=qsieve_sqrmp(r,epr[k]); logp[k]=0; r=epr[k]; while((r/=2)>0) logp[k]++; } r=mpz_tdiv_q_ui(TA, D, 8); if(r==5) logp[1]++; if(r==1) logp[1]+=2; threshold=logm+mpz_sizeinbase(R, 2)-2*logp[mm]; jj=0; nlp=0; mpz_mul_si(DG, D, 2); mpz_root(DG, DG, 2); mpz_set_si(TA, M); qsieve_divide(DG,TA,DG); mpz_root(DG, DG, 2); if(mpz_tdiv_q_ui(TA, DG, 2)==0) mpz_add_ui(DG, DG, 1); if(mpz_tdiv_q_ui(TA, DG, 4)==1) mpz_add_ui(DG, DG, 2); // 令DG等于大于等于DG的数中模4余3的最小的数 printf(" 0%"); while(1) //不断尝试新的多项式,可以并行计算 { r=qsieve->NTRY; qsieve->NTRY=1; do { do { mpz_add_ui(DG, DG, 4); } while(!(mpz_probab_prime_p(DG, qsieve->NTRY) ? TRUE : FALSE)); mpz_sub_ui(TA, DG, 1); mpz_tdiv_q_ui(TA, TA, 2); mpz_powm_sec(TA, D, TA, DG); } while(qsieve_getsize(TA)!=1); //直到DD是二次剩余 qsieve->NTRY=r; mpz_add_ui(TA, DG, 1); mpz_tdiv_q_ui(TA, TA, 4); mpz_powm_sec(B, D, TA, DG); mpz_neg(TA, D); qsieve_muladddiv(B,B,TA,DG,TA,TA); mpz_neg(TA, TA); mpz_mul_si(A, B, 2); qsieve_extgcd(A,DG,A,A,A); qsieve_muladddiv(A,TA,TA,DG,DG,A); mpz_mul(TA, A, DG); mpz_add(B, B, TA); mpz_mul(A, DG, DG); qsieve_extgcd(DG,D,IG,IG,IG); r1[0]=r2[0]=0; for(k=1;k<=mm;k++) //s1和s2是两个解 { s=mpz_tdiv_q_ui(TA, B, epr[k]); r=mpz_tdiv_q_ui(TA, A, epr[k]); r=qsieve_getinvers(r,epr[k]); s1=(epr[k]-s+rp[k]); s2=(epr[k]-s+epr[k]-rp[k]); if(s1 > s2) { int t = s1; s1 = s2; s2 = t; } r1[k]=(int)((((long long)s1)*((long long)r)) % ((long long)epr[k])); r2[k]=(int)((((long long)s2)*((long long)r)) % ((long long)epr[k])); } for(ptr=(-NS);ptr<NS;ptr++) { la=(long)ptr*SSIZE; SV=(unsigned int *)sieve; for(i=0; i<SSIZE/sizeof(int); i++) *SV++=0; for(k=1; k<=mm; k++) { epri=epr[k]; logpi=logp[k]; r=(int)(la%epri); s1=(r1[k]-r)%epri; if(s1<0) s1+=epri; s2=(r2[k]-r)%epri; if(s2<0) s2+=epri; /* 这部分是筛法的主要部分,数组下标表示多项式P(x)的参数x s1与s2是两个P(x)=0(mod p)的解 */ for(j=s1;j<SSIZE;j+=epri) sieve[j]+=logpi; if(s1==s2) continue; for(j=s2;j<SSIZE;j+=epri) sieve[j]+=logpi; } for(a=0;a<SSIZE;a++) //找那些没有被筛掉的数 { if(sieve[a]<threshold) continue; lptr=la+a; mpz_set_si(TA, lptr); S=0; mpz_mul(TA, A, TA); mpz_add(TA, TA, B); qsieve_muladddiv(TA,IG,TA,D,D,P); if(qsieve_getsize(P)<0) mpz_add(P, P, D); qsieve_muladddiv(P,P,P,D,D,V); mpz_abs(TA, TA); if(qsieve_compare(TA,R)<0) S=1; if(S==1) mpz_sub(V, D, V); if(V!=TA) mpz_set(TA, V); e[0]=S; for(k=1;k<=mm;k++) e[k]=0; if(!factored(lptr,TA)) continue; if(gotcha()) { mpz_gcd(P, TA, N); qsieve_getsize(P); printf("\b\b\b\b100%\nFactors are\n"); qsieve_outnum(P,stdout); qsieve_divide(N,P,N); qsieve_outnum(N,stdout); return 0; } } } } return 0; }
/////////////////////////////////////////////////////////////////////// // Class : CStochastic // Method : rasterBegin // Description : /// \brief Begin drawing an image // Return Value : - // Comments : void CStochastic::rasterBegin(int w,int h,int l,int t,int nullBucket) { int i,j,pxi,pxj; float zoldStart; CFragment *cFragment; assert(numFragments == 0); zoldStart = CRenderer::clipMax; // Set the digits width = w; height = h; left = l; top = t; sampleWidth = width*CRenderer::pixelXsamples + 2*CRenderer::xSampleOffset; sampleHeight = height*CRenderer::pixelYsamples + 2*CRenderer::ySampleOffset; right = left + sampleWidth; bottom = top + sampleHeight; // Early-out if we have no data if (!(CRenderer::flags & OPTIONS_FLAGS_DEEP_SHADOW_RENDERING) && nullBucket) return; assert(sampleWidth <= totalWidth); assert(sampleHeight <= totalHeight); // Init the occlusion culler to zero initToZero(); for (i=0,pxi=CRenderer::pixelYsamples-CRenderer::ySampleOffset;i<sampleHeight;i++,pxi++) { CPixel *pixel = fb[i]; if (pxi >= CRenderer::pixelYsamples) pxi = 0; for (j=0,pxj=CRenderer::pixelXsamples-CRenderer::xSampleOffset;j<sampleWidth;j++,pxj++,pixel++) { float aperture[2]; // The stratified sample pixel->jx = (CRenderer::jitter*(urand()-0.5f) + 0.5001011f); pixel->jy = (CRenderer::jitter*(urand()-0.5f) + 0.5001017f); // Time of the sample for motion blur if (pxj >= CRenderer::pixelXsamples) pxj = 0; pixel->jt = ( pxi*CRenderer::pixelXsamples + pxj + CRenderer::jitter*(urand()-0.5f) + 0.5001011f)/(float)(CRenderer::pixelXsamples*CRenderer::pixelYsamples); // Importance blend / jitter pixel->jimp = 1.0f - ( pxj*CRenderer::pixelYsamples + pxi + CRenderer::jitter*(urand()-0.5f) + 0.5001011f)/(float)(CRenderer::pixelXsamples*CRenderer::pixelYsamples); if (CRenderer::flags & OPTIONS_FLAGS_FOCALBLUR) { // Aperture sample for depth of field while (TRUE) { apertureGenerator.get(aperture); aperture[0] = 2.0f*aperture[0] - 1.0f; aperture[1] = 2.0f*aperture[1] - 1.0f; if ((aperture[0]*aperture[0] + aperture[1]*aperture[1]) < 1.0f) break; } pixel->jdx = aperture[0]; pixel->jdy = aperture[1]; } else { pixel->jdx = 0; pixel->jdy = 0; } // Center location of the sample pixel->xcent = (j+pixel->jx) + left; pixel->ycent = (i+pixel->jy) + top; pixel->z = CRenderer::clipMax; pixel->zold = zoldStart; pixel->numSplats = 0; pixel->node = getNode(j,i); pixel->node->zmax = CRenderer::clipMax; cFragment = &pixel->last; cFragment->z = CRenderer::clipMax; initv(cFragment->color,0); initv(cFragment->opacity,0); cFragment->next = NULL; cFragment->prev = &pixel->first; // The last sample's extra samples are genuine AOV data if (CRenderer::numExtraSamples > 0) memcpy(cFragment->extraSamples,CRenderer::sampleDefaults,sizeof(float)*CRenderer::numExtraSamples); initv(cFragment->accumulatedOpacity,0); cFragment = &pixel->first; cFragment->z = -C_INFINITY; initv(cFragment->color,0); initv(cFragment->opacity,0); cFragment->next = &pixel->last; cFragment->prev = NULL; // Note: The first fragment's extra samples are not used, and the pointer is NULL assert(cFragment->extraSamples == NULL); initv(cFragment->accumulatedOpacity,0); pixel->update = &pixel->first; } } resetHierarchy(); }
/////////////////////////////////////////////////////////////////////// // Class : CObject // Method : estimateDicing // Description : /// \brief Estimate the dicing size on the screen // Return Value : // Comments : /// \note P must be in pixels void CObject::estimateDicing(float *P,int udiv,int vdiv,int &nudiv,int &nvdiv,float shadingRate,int nonrasterorient) { float uMin,vMin; // The minimum edge length float uMax,vMax; // The maximum edge length int i,j; const float *cP,*nP,*tP; float dx,dy; uMax = vMax = 0; uMin = vMin = C_INFINITY; if (!nonrasterorient) { // Project to pixels camera2pixels((udiv+1)*(vdiv+1),P); // U stats cP = P; for (j=(vdiv+1);j>0;--j) { float total = 0; for (i=udiv;i>0;--i,cP+=3) { dx = cP[3 + COMP_X] - cP[COMP_X]; dy = cP[3 + COMP_Y] - cP[COMP_Y]; total += sqrtf(dx*dx + dy*dy); } cP += 3; uMax = max(uMax,total); uMin = min(uMin,total); } // V stats cP = P; for (i=(udiv+1);i>0;--i,cP+=3) { nP = cP; tP = nP + (udiv+1)*3; float total = 0; for (j=vdiv;j>0;--j,nP=tP,tP+=(udiv+1)*3) { dx = tP[COMP_X] - nP[COMP_X]; dy = tP[COMP_Y] - nP[COMP_Y]; total += sqrtf(dx*dx + dy*dy); } vMax = max(vMax,total); vMin = min(vMin,total); } } else { // non raster oriented vector tmp; float maxDim = max(CRenderer::dPixeldx,CRenderer::dPixeldy); if(CRenderer::projection == OPTIONS_PROJECTION_PERSPECTIVE) { for (j=0;j<(vdiv+1)*(udiv+1);++j) { float x,y; x = (CRenderer::imagePlane*P[j*3+COMP_X]/P[j*3+COMP_Z]); y = (CRenderer::imagePlane*P[j*3+COMP_Y]/P[j*3+COMP_Z]); initv(tmp,x-P[j*3+COMP_X],y-P[j*3+COMP_Y],P[j*3+COMP_Z]-1); P[j*3+COMP_X] = x*maxDim; P[j*3+COMP_Y] = y*maxDim; P[j*3+COMP_Z] = lengthv(tmp)*maxDim; } } else { for (j=0;j<(vdiv+1)*(udiv+1);++j) { P[j*3+COMP_X] = P[j*3+COMP_X]*CRenderer::dPixeldx; P[j*3+COMP_Y] = P[j*3+COMP_Y]*CRenderer::dPixeldy; P[j*3+COMP_Z] *= maxDim; } } // U stats cP = P; for (j=(vdiv+1);j>0;--j) { float total = 0; for (i=udiv;i>0;--i,cP+=3) { subvv(tmp,cP+3,cP); total += lengthv(tmp); } cP += 3; uMax = max(uMax,total); uMin = min(uMin,total); } // V stats cP = P; for (i=(udiv+1);i>0;--i,cP+=3) { nP = cP; tP = nP + (udiv+1)*3; float total = 0; for (j=vdiv;j>0;--j,nP=tP,tP+=(udiv+1)*3) { subvv(tmp,tP,nP); total += lengthv(tmp); } vMax = max(vMax,total); vMin = min(vMin,total); } } float udivf,vdivf; // Compute the new grid size based on the maximum size udivf = uMax / shadingRate; vdivf = vMax / shadingRate; // Clamp the division amount udivf = max(1,udivf); vdivf = max(1,vdivf); udivf = min(10000,udivf); vdivf = min(10000,vdivf); // Estimate the dicing amount if (attributes->flags & ATTRIBUTES_FLAGS_BINARY_DICE) { const double log2 = log(2.0); nudiv = 1 << (unsigned int) (ceil(log(udivf) / log2)); nvdiv = 1 << (unsigned int) (ceil(log(vdivf) / log2)); } else { nudiv = (int) ceil(udivf); nvdiv = (int) ceil(vdivf); } }
/////////////////////////////////////////////////////////////////////// // Class : CObject // Method : cluster // Description : /// \brief Cluster the objects // Return Value : // Comments : void CObject::cluster(CShadingContext *context) { int numChildren; CObject *cObject; // Count the number of children for (numChildren=0,cObject=children;cObject!=NULL;cObject=cObject->sibling,numChildren++); // If we have too few children, continue if (numChildren <= 2) return; // These are the two children CObject *front,*frontChildren; CObject *back,*backChildren; // Begin a memory page memBegin(context->threadMemory); // Cluster the midpoints of the objects float *P = (float *) ralloc(numChildren*3*sizeof(float),context->threadMemory); int *indices = (int *) ralloc(numChildren*sizeof(int),context->threadMemory); // For 5 iterations for (int iteration=0;iteration<15;iteration++) { // Compute a slightly jittered center position for the object for (numChildren=0,cObject=children;cObject!=NULL;cObject=cObject->sibling,numChildren++) { initv(P + numChildren*3 , (cObject->bmax[0] - cObject->bmin[0])*(context->urand()*0.2f + 0.4f) + cObject->bmin[0] , (cObject->bmax[1] - cObject->bmin[1])*(context->urand()*0.2f + 0.4f) + cObject->bmin[1] , (cObject->bmax[2] - cObject->bmin[2])*(context->urand()*0.2f + 0.4f) + cObject->bmin[2]); indices[numChildren] = -1; } // The random cluster centers vector P1,P2; initv(P1, (bmax[0] - bmin[0])*context->urand() + bmin[0] , (bmax[1] - bmin[1])*context->urand() + bmin[1] , (bmax[2] - bmin[2])*context->urand() + bmin[2]); initv(P2, (bmax[0] - bmin[0])*context->urand() + bmin[0] , (bmax[1] - bmin[1])*context->urand() + bmin[1] , (bmax[2] - bmin[2])*context->urand() + bmin[2]); // The main clustering loop int done; for (done=FALSE;done==FALSE;) { int i; vector nP1,nP2; int num1,num2; done = TRUE; initv(nP1,0); initv(nP2,0); num1 = 0; num2 = 0; for (i=0;i<numChildren;i++) { vector D1,D2; subvv(D1,P + i*3,P1); subvv(D2,P + i*3,P2); if (dotvv(D1,D1) < dotvv(D2,D2)) { if (indices[i] != 0) { done = FALSE; indices[i] = 0; } addvv(nP1,P+i*3); num1++; } else { if (indices[i] != 1) { done = FALSE; indices[i] = 1; } addvv(nP2,P+i*3); num2++; } } if ((num1 == 0) || (num2 == 0)) break; mulvf(P1,nP1,1/(float) num1); mulvf(P2,nP2,1/(float) num2); } if (done == TRUE) break; } // Cluster the rest of the objects front = new CDummyObject(attributes,xform); back = new CDummyObject(attributes,xform); initv(front->bmin,C_INFINITY); initv(front->bmax,-C_INFINITY); initv(back->bmin,C_INFINITY); initv(back->bmax,-C_INFINITY); frontChildren = NULL; backChildren = NULL; // Create the clusters for (numChildren=0,cObject=children;cObject!=NULL;numChildren++) { CObject *nObject = cObject->sibling; if (indices[numChildren] == 0) { cObject->sibling = frontChildren; frontChildren = cObject; addBox(front->bmin,front->bmax,cObject->bmin); addBox(front->bmin,front->bmax,cObject->bmax); } else { cObject->sibling = backChildren; backChildren = cObject; addBox(back->bmin,back->bmax,cObject->bmin); addBox(back->bmin,back->bmax,cObject->bmax); } cObject = nObject; } memEnd(context->threadMemory); // Recurse front->children = frontChildren; back->children = backChildren; front->attach(); back->attach(); front->sibling = back; back->sibling = NULL; children = front; }
/////////////////////////////////////////////////////////////////////// // Class : CXform // Method : invTransformBound // Description : Transfer the bounding box from one system to another // Return Value : - // Comments : void CXform::invTransformBound(float *bmin,float *bmax) const { vector corners[8]; int i; const float *from; vector vtmp; vector lbmin,lbmax; from = this->to; // Compute & transfer the corners to the dest space initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[0],from,vtmp); initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[1],from,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[2],from,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[3],from,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[4],from,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[5],from,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[6],from,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[7],from,vtmp); movvv(lbmin,corners[0]); movvv(lbmax,corners[0]); for (i=1;i<8;i++) { addBox(lbmin,lbmax,corners[i]); } if (next != NULL) { from = next->from; // Compute & transfer the corners to the dest space initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[0],from,vtmp); initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[1],from,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[2],from,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[3],from,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[4],from,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[5],from,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[6],from,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[7],from,vtmp); for (i=0;i<8;i++) { addBox(lbmin,lbmax,corners[i]); } } movvv(bmin,lbmin); movvv(bmax,lbmax); }