Пример #1
0
void LuxRenderer::createAreaLightMesh(mtlu_MayaObject *obj)
{
	MString meshName("");
	MFnDependencyNode depFn(obj->mobject);
	MObject otherSideObj = getOtherSideNode(MString("mtlu_areaLight_geo"), obj->mobject);
	if( otherSideObj != MObject::kNullObj)
	{


	}else{
		int indices[6] = {0,1,2,2,3,0};
		float floatPointArray[12] = {-1, -1, 0,
									 -1,  1, 0,
									  1,  1, 0,
									  1, -1, 0};

		float floatNormalArray[12] = {0,0,-1,
									  0,0,-1,
									  0,0,-1,
									  0,0,-1};

		ParamSet triParams = CreateParamSet();
		triParams->AddInt("indices", indices, 6);
		triParams->AddPoint("P", floatPointArray, 4);
		triParams->AddNormal("N", floatNormalArray, 4);
		
		lux->transformBegin();
		float fm[16];
		MMatrix tm = obj->transformMatrices[0];
		setZUp(tm, fm);
		this->lux->transform(fm);
		this->lux->shape("trianglemesh", boost::get_pointer(triParams));
		lux->transformEnd();
	}
}
Пример #2
0
void Heightfield::Refine(vector<Reference<Shape> > &refined) const {
    int ntris = 2*(nx-1)*(ny-1);
    refined.reserve(ntris);
    int *verts = new int[3*ntris];
    Point *P = new Point[nx*ny];
    float *uvs = new float[2*nx*ny];
    int nverts = nx*ny;

    int x, y;
    // Compute heightfield vertex positions
    int pos = 0;
    for (y = 0; y < ny; ++y) {
        for (x = 0; x < nx; ++x) {
            P[pos].x = uvs[2*pos]   = (float)x / (float)(nx-1);
            P[pos].y = uvs[2*pos+1] = (float)y / (float)(ny-1);
            P[pos].z = z[pos];
            ++pos;
        }
    }

    // Fill in heightfield vertex offset array
    int *vp = verts;
    for (y = 0; y < ny-1; ++y) {
        for (x = 0; x < nx-1; ++x) {
#define VERT(x,y) ((x)+(y)*nx)
            *vp++ = VERT(x, y);
            *vp++ = VERT(x+1, y);
            *vp++ = VERT(x+1, y+1);
    
            *vp++ = VERT(x, y);
            *vp++ = VERT(x+1, y+1);
            *vp++ = VERT(x, y+1);
        }
#undef VERT
    }
    ParamSet paramSet;
    paramSet.AddInt("indices", verts, 3*ntris);
    paramSet.AddFloat("uv", uvs, 2 * nverts);
    paramSet.AddPoint("P", P, nverts);
    refined.push_back(CreateTriangleMeshShape(ObjectToWorld, WorldToObject, ReverseOrientation, paramSet));
    delete[] P;
    delete[] uvs;
    delete[] verts;
}
Пример #3
0
void LuxRenderer::defineTriangleMesh(mtlu_MayaObject *obj, bool noObjectDef = false)
{
	MObject meshObject = obj->mobject;
	MStatus stat = MStatus::kSuccess;
	MFnMesh meshFn(meshObject, &stat);
	
	CHECK_MSTATUS(stat);
	MItMeshPolygon faceIt(meshObject, &stat);
	CHECK_MSTATUS(stat);

	MPointArray points;
	meshFn.getPoints(points);
    MFloatVectorArray normals;
    meshFn.getNormals( normals, MSpace::kWorld );
	MFloatArray uArray, vArray;
	meshFn.getUVs(uArray, vArray);

	logger.debug(MString("Translating mesh object ") + meshFn.name().asChar());
	MString meshFullName = obj->fullNiceName;


	MIntArray trianglesPerFace, triVertices;
	meshFn.getTriangles(trianglesPerFace, triVertices);
	int numTriangles = 0;
	for( size_t i = 0; i < trianglesPerFace.length(); i++)
		numTriangles += trianglesPerFace[i];

	// lux render does not have a per vertex per face normal definition, here we can use one normal and uv per vertex only
	// So I create the triangles with unique vertices, normals and uvs. Of course this way vertices etc. cannot be shared.
	int numPTFloats = numTriangles * 3 * 3;
	logger.debug(MString("Num Triangles: ") + numTriangles + " num tri floats " + numPTFloats);

	float *floatPointArray = new float[numPTFloats];
	float *floatNormalArray = new float[numPTFloats];
	float *floatUvArray = new float[numTriangles * 3 * 2];
	
	logger.debug(MString("Allocated ") + numPTFloats + " floats for point and normals");

	MIntArray triangelVtxIdListA;
	MFloatArray floatPointArrayA;

	MPointArray triPoints;
	MIntArray triVtxIds;
	MIntArray faceVtxIds;
	MIntArray faceNormalIds;
	
	int *triangelVtxIdList = new int[numTriangles * 3];

	for( uint sgId = 0; sgId < obj->shadingGroups.length(); sgId++)
	{
		MString slotName = MString("slot_") + sgId;
	}
	
	int triCount = 0;
	int vtxCount = 0;

	for(faceIt.reset(); !faceIt.isDone(); faceIt.next())
	{
		int faceId = faceIt.index();
		int numTris;
		faceIt.numTriangles(numTris);
		faceIt.getVertices(faceVtxIds);

		MIntArray faceUVIndices;

		faceNormalIds.clear();
		for( uint vtxId = 0; vtxId < faceVtxIds.length(); vtxId++)
		{
			faceNormalIds.append(faceIt.normalIndex(vtxId));
			int uvIndex;
			faceIt.getUVIndex(vtxId, uvIndex);
			faceUVIndices.append(uvIndex);
		}

		int perFaceShadingGroup = 0;
		if( obj->perFaceAssignments.length() > 0)
			perFaceShadingGroup = obj->perFaceAssignments[faceId];
		//logger.info(MString("Face ") + faceId + " will receive SG " +  perFaceShadingGroup);

		for( int triId = 0; triId < numTris; triId++)
		{
			int faceRelIds[3];
			faceIt.getTriangle(triId, triPoints, triVtxIds);

			for( uint triVtxId = 0; triVtxId < 3; triVtxId++)
			{
				for(uint faceVtxId = 0; faceVtxId < faceVtxIds.length(); faceVtxId++)
				{
					if( faceVtxIds[faceVtxId] == triVtxIds[triVtxId])
					{
						faceRelIds[triVtxId] = faceVtxId;
					}
				}
			}

			
			uint vtxId0 = faceVtxIds[faceRelIds[0]];
			uint vtxId1 = faceVtxIds[faceRelIds[1]];
			uint vtxId2 = faceVtxIds[faceRelIds[2]];
			uint normalId0 = faceNormalIds[faceRelIds[0]];
			uint normalId1 = faceNormalIds[faceRelIds[1]];
			uint normalId2 = faceNormalIds[faceRelIds[2]];
			uint uvId0 = faceUVIndices[faceRelIds[0]];
			uint uvId1 = faceUVIndices[faceRelIds[1]];
			uint uvId2 = faceUVIndices[faceRelIds[2]];
			
			floatPointArray[vtxCount * 3] = points[vtxId0].x;
			floatPointArray[vtxCount * 3 + 1] = points[vtxId0].y;
			floatPointArray[vtxCount * 3 + 2] = points[vtxId0].z;

			floatNormalArray[vtxCount * 3] = normals[normalId0].x;
			floatNormalArray[vtxCount * 3 + 1] = normals[normalId0].y;
			floatNormalArray[vtxCount * 3 + 2] = normals[normalId0].z;

			floatUvArray[vtxCount * 2] = uArray[uvId0];
			floatUvArray[vtxCount * 2 + 1] = vArray[uvId0];

			vtxCount++;

			floatPointArray[vtxCount * 3] = points[vtxId1].x;
			floatPointArray[vtxCount * 3 + 1] = points[vtxId1].y;
			floatPointArray[vtxCount * 3 + 2] = points[vtxId1].z;

			floatNormalArray[vtxCount * 3] = normals[normalId1].x;
			floatNormalArray[vtxCount * 3 + 1] = normals[normalId1].y;
			floatNormalArray[vtxCount * 3 + 2] = normals[normalId1].z;

			floatUvArray[vtxCount * 2] = uArray[uvId1];
			floatUvArray[vtxCount * 2 + 1] = vArray[uvId1];

			vtxCount++;

			floatPointArray[vtxCount * 3] = points[vtxId2].x;
			floatPointArray[vtxCount * 3 + 1] = points[vtxId2].y;
			floatPointArray[vtxCount * 3 + 2] = points[vtxId2].z;

			floatNormalArray[vtxCount * 3] = normals[normalId2].x;
			floatNormalArray[vtxCount * 3 + 1] = normals[normalId2].y;
			floatNormalArray[vtxCount * 3 + 2] = normals[normalId2].z;

			floatUvArray[vtxCount * 2] = uArray[uvId2];
			floatUvArray[vtxCount * 2 + 1] = vArray[uvId2];

			vtxCount++;
			
			//logger.debug(MString("Vertex count: ") + vtxCount + " maxId " + ((vtxCount - 1) * 3 + 2) + " ptArrayLen " + (numTriangles * 3 * 3));

			triangelVtxIdList[triCount * 3] = triCount * 3;
			triangelVtxIdList[triCount * 3 + 1] = triCount * 3 + 1;
			triangelVtxIdList[triCount * 3 + 2] = triCount * 3 + 2;

			triCount++;
		}		
	}

//generatetangents 	bool 	Generate tangent space using miktspace, useful if mesh has a normal map that was also baked using miktspace (such as blender or xnormal) 	false
//subdivscheme 	string 	Subdivision algorithm, options are "loop" and "microdisplacement" 	"loop"
//displacementmap 	string 	Name of the texture used for the displacement. Subdivscheme parameter must always be provided, as load-time displacement is handled by the loop-subdivision code. 	none - optional. (loop subdiv can be used without displacement, microdisplacement will not affect the mesh without a displacement map specified)
//dmscale 	float 	Scale of the displacement (for an LDR map, this is the maximum height of the displacement in meter) 	0.1
//dmoffset 	float 	Offset of the displacement. 	0
//dmnormalsmooth 	bool 	Smoothing of the normals of the subdivided faces. Only valid for loop subdivision. 	true
//dmnormalsplit 	bool 	Force the mesh to split along breaks in the normal. If a mesh has no normals (flat-shaded) it will rip open on all edges. Only valid for loop subdivision. 	false
//dmsharpboundary 	bool 	Try to preserve mesh boundaries during subdivision. Only valid for loop subdivision. 	false
//nsubdivlevels 	integer 	Number of subdivision levels. This is only recursive for loop subdivision, microdisplacement will need much larger values (such as 50). 	0

	bool generatetangents = false;
	getBool(MString("mtlu_mesh_generatetangents"), meshFn, generatetangents);
	int subdivscheme = 0;
	const char *subdAlgos[] = {"loop", "microdisplacement"};
	getInt(MString("mtlu_mesh_subAlgo"), meshFn, subdivscheme);
	const char *subdalgo =  subdAlgos[subdivscheme];
	float dmscale;
	getFloat(MString("mtlu_mesh_dmscale"), meshFn, dmscale);
	float dmoffset;
	getFloat(MString("mtlu_mesh_dmoffset"), meshFn, dmoffset);
	MString displacementmap;
	getString(MString("mtlu_mesh_displacementMap"), meshFn, displacementmap);
	const char *displacemap = displacementmap.asChar();
	bool dmnormalsmooth = true;
	getBool(MString("mtlu_mesh_dmnormalsmooth"), meshFn, dmnormalsmooth);
	bool dmnormalsplit = false;
	getBool(MString("mtlu_mesh_dmnormalsplit"), meshFn, dmnormalsplit);
	bool dmsharpboundary = false;
	getBool(MString("mtlu_mesh_dmsharpboundary"), meshFn, dmsharpboundary);
	int nsubdivlevels = 0;
	getInt(MString("mtlu_mesh_subdivlevel"), meshFn, nsubdivlevels);

	// a displacment map needs its own texture defintion
	MString displacementTextureName = "";
	if(displacementmap.length() > 0)
	{
		ParamSet dmParams = CreateParamSet();
		dmParams->AddString("filename", &displacemap);
		displacementTextureName = meshFn.name() + "_displacementMap";
		this->lux->texture(displacementTextureName.asChar(), "float", "imagemap", boost::get_pointer(dmParams));
	}

	ParamSet triParams = CreateParamSet();
	int numPointValues = numTriangles * 3;
	int numUvValues = numTriangles * 3 * 2;
	clock_t startTime = clock();
	logger.info(MString("Adding mesh values to params."));
	triParams->AddInt("indices", triangelVtxIdList, numTriangles * 3);
	triParams->AddPoint("P", floatPointArray, numPointValues);
	triParams->AddNormal("N", floatNormalArray, numPointValues);
	triParams->AddFloat("uv",  floatUvArray, numUvValues);
	if( nsubdivlevels > 0)
		triParams->AddInt("nsubdivlevels", &nsubdivlevels, 1);
	triParams->AddBool("generatetangents",  &generatetangents, 1);
	triParams->AddString("subdivscheme", &subdalgo , 1);
	if(displacementmap.length() > 0)
	{
		triParams->AddFloat("dmoffset",  &dmoffset, 1);
		triParams->AddFloat("dmscale",  &dmscale, 1);
		const char *dmft = displacementTextureName.asChar();
		triParams->AddString("displacementmap", &dmft);
	}
	triParams->AddBool("dmnormalsmooth",  &dmnormalsmooth, 1);
	triParams->AddBool("dmnormalsplit",  &dmnormalsplit, 1);
	triParams->AddBool("dmsharpboundary",  &dmsharpboundary, 1);


	clock_t pTime = clock();
	if(!noObjectDef)
		this->lux->objectBegin(meshFullName.asChar());
	this->lux->shape("trianglemesh", boost::get_pointer(triParams));
	if(!noObjectDef)
		this->lux->objectEnd();

	clock_t eTime = clock();
	logger.info(MString("Timing: Parameters: ") + ((pTime - startTime)/CLOCKS_PER_SEC) + " objTime " + ((eTime - pTime)/CLOCKS_PER_SEC) + " all " + ((eTime - startTime)/CLOCKS_PER_SEC));

	return;

}
Пример #4
0
void LoopSubdiv::Refine(vector<Reference<Shape> > &refined) const {
    vector<SDFace *> f = faces;
    vector<SDVertex *> v = vertices;
    MemoryArena arena;
    for (int i = 0; i < nLevels; ++i) {
        // Update _f_ and _v_ for next level of subdivision
        vector<SDFace *> newFaces;
        vector<SDVertex *> newVertices;

        // Allocate next level of children in mesh tree
        for (uint32_t j = 0; j < v.size(); ++j) {
            v[j]->child = arena.Alloc<SDVertex>();
            v[j]->child->regular = v[j]->regular;
            v[j]->child->boundary = v[j]->boundary;
            newVertices.push_back(v[j]->child);
        }
        for (uint32_t j = 0; j < f.size(); ++j)
            for (int k = 0; k < 4; ++k) {
                f[j]->children[k] = arena.Alloc<SDFace>();
                newFaces.push_back(f[j]->children[k]);
            }

        // Update vertex positions and create new edge vertices

        // Update vertex positions for even vertices
        for (uint32_t j = 0; j < v.size(); ++j) {
            if (!v[j]->boundary) {
                // Apply one-ring rule for even vertex
                if (v[j]->regular)
                    v[j]->child->P = weightOneRing(v[j], 1.f/16.f);
                else
                    v[j]->child->P = weightOneRing(v[j], beta(v[j]->valence()));
            }
            else {
                // Apply boundary rule for even vertex
                v[j]->child->P = weightBoundary(v[j], 1.f/8.f);
            }
        }

        // Compute new odd edge vertices
        map<SDEdge, SDVertex *> edgeVerts;
        for (uint32_t j = 0; j < f.size(); ++j) {
            SDFace *face = f[j];
            for (int k = 0; k < 3; ++k) {
                // Compute odd vertex on _k_th edge
                SDEdge edge(face->v[k], face->v[NEXT(k)]);
                SDVertex *vert = edgeVerts[edge];
                if (!vert) {
                    // Create and initialize new odd vertex
                    vert = arena.Alloc<SDVertex>();
                    newVertices.push_back(vert);
                    vert->regular = true;
                    vert->boundary = (face->f[k] == NULL);
                    vert->startFace = face->children[3];

                    // Apply edge rules to compute new vertex position
                    if (vert->boundary) {
                        vert->P =  0.5f * edge.v[0]->P;
                        vert->P += 0.5f * edge.v[1]->P;
                    }
                    else {
                        vert->P =  3.f/8.f * edge.v[0]->P;
                        vert->P += 3.f/8.f * edge.v[1]->P;
                        vert->P += 1.f/8.f * face->otherVert(edge.v[0], edge.v[1])->P;
                        vert->P += 1.f/8.f *
                            face->f[k]->otherVert(edge.v[0], edge.v[1])->P;
                    }
                    edgeVerts[edge] = vert;
                }
            }
        }

        // Update new mesh topology

        // Update even vertex face pointers
        for (uint32_t j = 0; j < v.size(); ++j) {
            SDVertex *vert = v[j];
            int vertNum = vert->startFace->vnum(vert);
            vert->child->startFace =
                vert->startFace->children[vertNum];
        }

        // Update face neighbor pointers
        for (uint32_t j = 0; j < f.size(); ++j) {
            SDFace *face = f[j];
            for (int k = 0; k < 3; ++k) {
                // Update children _f_ pointers for siblings
                face->children[3]->f[k] = face->children[NEXT(k)];
                face->children[k]->f[NEXT(k)] = face->children[3];

                // Update children _f_ pointers for neighbor children
                SDFace *f2 = face->f[k];
                face->children[k]->f[k] =
                    f2 ? f2->children[f2->vnum(face->v[k])] : NULL;
                f2 = face->f[PREV(k)];
                face->children[k]->f[PREV(k)] =
                    f2 ? f2->children[f2->vnum(face->v[k])] : NULL;
            }
        }

        // Update face vertex pointers
        for (uint32_t j = 0; j < f.size(); ++j) {
            SDFace *face = f[j];
            for (int k = 0; k < 3; ++k) {
                // Update child vertex pointer to new even vertex
                face->children[k]->v[k] = face->v[k]->child;

                // Update child vertex pointer to new odd vertex
                SDVertex *vert = edgeVerts[SDEdge(face->v[k], face->v[NEXT(k)])];
                face->children[k]->v[NEXT(k)] = vert;
                face->children[NEXT(k)]->v[k] = vert;
                face->children[3]->v[k] = vert;
            }
        }

        // Prepare for next level of subdivision
        f = newFaces;
        v = newVertices;
    }
    // Push vertices to limit surface
    PbrtPoint *Plimit = new PbrtPoint[v.size()];
    for (uint32_t i = 0; i < v.size(); ++i) {
        if (v[i]->boundary)
            Plimit[i] =  weightBoundary(v[i], 1.f/5.f);
        else
            Plimit[i] =  weightOneRing(v[i], gamma(v[i]->valence()));
    }
    for (uint32_t i = 0; i < v.size(); ++i)
        v[i]->P = Plimit[i];

    // Compute vertex tangents on limit surface
    vector<Normal> Ns;
    Ns.reserve(v.size());
    vector<PbrtPoint> Pring(16, PbrtPoint());
    for (uint32_t i = 0; i < v.size(); ++i) {
        SDVertex *vert = v[i];
        Vector S(0,0,0), T(0,0,0);
        int valence = vert->valence();
        if (valence > (int)Pring.size())
            Pring.resize(valence);
        vert->oneRing(&Pring[0]);
        if (!vert->boundary) {
            // Compute tangents of interior face
            for (int k = 0; k < valence; ++k) {
                S += cosf(2.f*M_PI*k/valence) * Vector(Pring[k]);
                T += sinf(2.f*M_PI*k/valence) * Vector(Pring[k]);
            }
        } else {
            // Compute tangents of boundary face
            S = Pring[valence-1] - Pring[0];
            if (valence == 2)
                T = Vector(Pring[0] + Pring[1] - 2 * vert->P);
            else if (valence == 3)
                T = Pring[1] - vert->P;
            else if (valence == 4) // regular
                T = Vector(-1*Pring[0] + 2*Pring[1] + 2*Pring[2] +
                           -1*Pring[3] + -2*vert->P);
            else {
                float theta = M_PI / float(valence-1);
                T = Vector(sinf(theta) * (Pring[0] + Pring[valence-1]));
                for (int k = 1; k < valence-1; ++k) {
                    float wt = (2*cosf(theta) - 2) * sinf((k) * theta);
                    T += Vector(wt * Pring[k]);
                }
                T = -T;
            }
        }
        Ns.push_back(Normal(Cross(S, T)));
    }

    // Create _TriangleMesh_ from subdivision mesh
    uint32_t ntris = uint32_t(f.size());
    int *verts = new int[3*ntris];
    int *vp = verts;
    uint32_t totVerts = uint32_t(v.size());
    map<SDVertex *, int> usedVerts;
    for (uint32_t i = 0; i < totVerts; ++i)
        usedVerts[v[i]] = i;
    for (uint32_t i = 0; i < ntris; ++i) {
        for (int j = 0; j < 3; ++j) {
            *vp = usedVerts[f[i]->v[j]];
            ++vp;
        }
    }
    ParamSet paramSet;
    paramSet.AddInt("indices", verts, 3*ntris);
    paramSet.AddPoint("P", Plimit, totVerts);
    paramSet.AddNormal("N", &Ns[0], int(Ns.size()));
    refined.push_back(CreateTriangleMeshShape(ObjectToWorld,
            WorldToObject, ReverseOrientation, paramSet));
    delete[] verts;
    delete[] Plimit;
}
Пример #5
0
MedianCutEnvironmentLight::MedianCutEnvironmentLight(const Transform &light2world,
    const Spectrum &L, int ns_, const string &texmap)
  : Light(light2world, ns_), impl(new MedCutEnvImpl {nullptr, nullptr, ns_}) {
  int width = 0, height = 0;
  RGBSpectrum *texels = NULL;
  // Read texel data from _texmap_ into _texels_
  if (texmap != "") {
    texels = ReadImage(texmap, &width, &height);
    if (texels)
      for (int i = 0; i < width * height; ++i)
        texels[i] *= L.ToRGBSpectrum();
  }
  if (!texels) {
    width = height = 1;
    texels = new RGBSpectrum[1];
    texels[0] = L.ToRGBSpectrum();
  }
  impl->radianceMap = new MIPMap<RGBSpectrum>(width, height, texels);
  impl->width = width;
  impl->inv_w = 1.0f/(width-1);
  impl->height = height;
  impl->inv_h = 1.0f/(height-1);
  impl->createDistantLight = [this](const RGBSpectrum& s, float cy, float cx) {
    ParamSet p;

    float rgb[3];
    s.ToRGB(rgb);
    p.AddRGBSpectrum("L", rgb, 3);

    const float theta = impl->inv_h*cy * M_PI
              , phi   = impl->inv_w*cx * 2.f * M_PI;
    const float costheta = cosf(theta), sintheta = sinf(theta);
    const float sinphi = sinf(phi), cosphi = cosf(phi);
    const Point wi(-sintheta*cosphi, -sintheta*sinphi, -costheta);
    p.AddPoint(string("to"), &wi, 1);

#if DEBUG >= 1
fprintf(stderr, "rgb (%f,%f,%f)\n", rgb[0], rgb[1], rgb[2]);
#endif

    return CreateDistantLight(this->LightToWorld, p);
  };

  impl->solid_angle = ((2.f * M_PI) / (width - 1)) * (M_PI / (1.f * (height - 1)));

#if DEBUG >= 1
fprintf(stderr, "solid_angle = %f\n", impl->solid_angle);
#endif

  for (int y = 0; y < height; ++y) {
    float sinTheta = sinf(M_PI * float(y + 0.5f)/height);
    for (int x = 0; x < width; ++x)
      texels[y*width + x] *= impl->solid_angle * sinTheta;
  }

  // Initialize energy sum array; the array is shifted for (1,1)
  // i.e. (0,*) and (*,0) are inserted 0-boundaries
  fprintf(stderr, "[+] [%10.2f] Initializing sum array\n", clock()*1.0/CLOCKS_PER_SEC);

#if DEBUG >= 3
for (int y = 0; y < 5; ++y) {
  for (int x = 0; x < 5; ++x) {
    fprintf(stderr, "%.2f ", texels[y*width+x].y());
  }
  fprintf(stderr, "\n");
}
fprintf(stderr, "\n");
#endif

  vector<vector<float>> acc(height+1, vector<float>(width+1));
  for (int y = 0; y < height; ++y)
    for (int x = 0; x < width; ++x)
      acc[y+1][x+1] = acc[y+1][x] + texels[y*width + x].y();

#if DEBUG >= 3
for (int y = 0; y < 5; ++y) {
  for (int x = 0; x < 5; ++x) {
    fprintf(stderr, "%.2f ", acc[y][x]);
  }
  fprintf(stderr, "\n");
}
fprintf(stderr, "\n");
#endif

   for (int x = 1; x <= width; ++x)
    for (int y = 1; y <= height; ++y)
      acc[y][x] += acc[y-1][x];

#if DEBUG >= 3
for (int y = 0; y < 5; ++y) {
  for (int x = 0; x < 5; ++x) {
    fprintf(stderr, "%.2f ", acc[y][x]);
  }
  fprintf(stderr, "\n");
}
fprintf(stderr, "\n");
#endif

 
  // initialize median cut
  printf("[+] [%10.2f] Calculating median cut\n", clock()*1.0/CLOCKS_PER_SEC);
  subdivide(this->impl, 1, texels, acc, 0, 0, width-1, height-1);
  printf("[+] [%10.2f] Done with %d lights\n", clock()*1.0/CLOCKS_PER_SEC, static_cast<int>(impl->ls.size()));

  delete[] texels;

  // Initialize sampling PDFs for environment area light
  // Compute scalar-valued image _img_ from environment map
  float filter = 1.f / max(width, height);
  float *img = new float[width*height];
  for (int v = 0; v < height; ++v) {
    float vp = (float)v / (float)height;
    float sinTheta = sinf(M_PI * float(v+.5f)/float(height));
    for (int u = 0; u < width; ++u) {
      float up = (float)u / (float)width;
      img[u+v*width] = impl->radianceMap->Lookup(up, vp, filter).y();
      img[u+v*width] *= sinTheta;
    }
  }

  // Compute sampling impl->distributions for rows and columns of image
  impl->distribution = new Distribution2D(img, width, height);
  delete[] img;
}
Пример #6
0
void NURBS::Refine(vector<Reference<Shape> > &refined) const {
	// Compute NURBS dicing rates
	int diceu = 30, dicev = 30;
	float *ueval = new float[diceu];
	float *veval = new float[dicev];
	Point *evalPs = new Point[diceu*dicev];
	Normal *evalNs = new Normal[diceu*dicev];
	int i;
	for (i = 0; i < diceu; ++i)
		ueval[i] = Lerp((float)i / (float)(diceu-1), umin, umax);
	for (i = 0; i < dicev; ++i)
		veval[i] = Lerp((float)i / (float)(dicev-1), vmin, vmax);
	// Evaluate NURBS over grid of points
	memset(evalPs, 0, diceu*dicev*sizeof(Point));
	memset(evalNs, 0, diceu*dicev*sizeof(Point));
	float *uvs = new float[2*diceu*dicev];
	// Turn NURBS into triangles
	Homogeneous3 *Pw = (Homogeneous3 *)P;
	if (!isHomogeneous) {
		Pw = (Homogeneous3 *)alloca(nu*nv*sizeof(Homogeneous3));
		for (int i = 0; i < nu*nv; ++i) {
			Pw[i].x = P[3*i];
			Pw[i].y = P[3*i+1];
			Pw[i].z = P[3*i+2];
			Pw[i].w = 1.;
		}
	}
	for (int v = 0; v < dicev; ++v) {
		for (int u = 0; u < diceu; ++u) {
			uvs[2*(v*diceu+u)]   = ueval[u];
			uvs[2*(v*diceu+u)+1] = veval[v];
	
			Vector dPdu, dPdv;
			Point pt = NURBSEvaluateSurface(uorder, uknot, nu, ueval[u],
				vorder, vknot, nv, veval[v], Pw, &dPdu, &dPdv);
			evalPs[v*diceu + u].x = pt.x;
			evalPs[v*diceu + u].y = pt.y;
			evalPs[v*diceu + u].z = pt.z;
			evalNs[v*diceu + u] = Normal(Normalize(Cross(dPdu, dPdv)));
		}
	}
	// Generate points-polygons mesh
	int nTris = 2*(diceu-1)*(dicev-1);
	int *vertices = new int[3 * nTris];
	int *vertp = vertices;
	// Compute the vertex offset numbers for the triangles
	for (int v = 0; v < dicev-1; ++v) {
		for (int u = 0; u < diceu-1; ++u) {
	#define VN(u,v) ((v)*diceu+(u))
			*vertp++ = VN(u,   v);
			*vertp++ = VN(u+1, v);
			*vertp++ = VN(u+1, v+1);
	
			*vertp++ = VN(u,   v);
			*vertp++ = VN(u+1, v+1);
			*vertp++ = VN(u,   v+1);
	#undef VN
		}
	}
	int nVerts = diceu*dicev;
	ParamSet paramSet;
	paramSet.AddInt("indices", vertices, 3*nTris);
	paramSet.AddPoint("P", evalPs, nVerts);
	paramSet.AddFloat("uv", uvs, 2 * nVerts);
	paramSet.AddNormal("N", evalNs, nVerts);
	refined.push_back(MakeShape("trianglemesh", ObjectToWorld,
			reverseOrientation, paramSet));
	// Cleanup from NURBS refinement
	delete[] uvs;
	delete[] ueval;
	delete[] veval;
	delete[] evalPs;
	delete[] evalNs;
	delete[] vertices;
}