mesh import_mesh(char const * file_name) { Assimp::Importer importer; aiScene const * ai_scene = importer.ReadFile( file_name, aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_GenNormals | aiProcess_SortByPType ); if (!ai_scene) throw std::runtime_error(std::string("Unable to import mesh: ") + importer.GetErrorString()); aiMesh const & am = *ai_scene->mMeshes[0]; // TODO: What about multiple meshes? vertices vertices; { buffer<hvector4<float>> positions(am.mNumVertices); buffer<vector3<float>> normals(am.mNumVertices); for(unsigned int i = 0; i < am.mNumVertices; ++i) { positions[i] = { am.mVertices[i][0], am.mVertices[i][1], am.mVertices[i][2] }; normals [i] = { am. mNormals[i][0], am. mNormals[i][1], am. mNormals[i][2] }; } vertices.attribute("position", std::move(positions)); vertices.attribute("normal" , std::move(normals )); } for (size_t n = 0; n < am.GetNumColorChannels(); ++n) { buffer<hvector4<float>> colors(am.mNumVertices); for(unsigned int i = 0; i < am.mNumVertices; ++i) { auto const & c = am.mColors[n][i]; colors[i] = {c.r, c.g, c.b, c.a}; } std::ostringstream name("color", std::ios_base::ate); if (n) name << (n + 1); vertices.attribute(name.str(), std::move(colors)); } for (size_t n = 0; n < am.GetNumUVChannels(); ++n) { buffer<vector3<float>> uvs(am.mNumVertices); for(unsigned int i = 0; i < am.mNumVertices; ++i) { uvs[i] = { am.mTextureCoords[n][i][0], am.mTextureCoords[n][i][1], am.mTextureCoords[n][i][1] }; } std::ostringstream name("texture_coordinate", std::ios_base::ate); if (n) name << (n + 1); vertices.attribute(name.str(), std::move(uvs)); } buffer<GLushort> indices(am.mNumFaces * 3); for (size_t i = 0; i < am.mNumFaces; ++i) { indices[i*3 ] = am.mFaces[i].mIndices[0]; indices[i*3+1] = am.mFaces[i].mIndices[1]; indices[i*3+2] = am.mFaces[i].mIndices[2]; } return mesh(std::move(vertices), std::move(indices)); }
//-***************************************************************************** // much like lib/Alembic/Abc/OTypedProperty.cpp, this is just a compile test, // due to the implementation being in the .h file, due to templates. void __testOGeomParamCompile( Abc::OCompoundProperty &iParent ) { OV2fGeomParam uvs( iParent, "uv", false, kVertexScope, 1 ); std::vector<V2f> vec; vec.push_back( V2f( 1.0f, 2.0f ) ); V2fArraySample val( vec ); OV2fGeomParam::Sample samp( val, kUnknownScope ); uvs.set( samp ); }
// ======================================================================= // Read all faces from TRIANGLES, TRIANGLE_FANS, POLYLIST, POLYGON // Important: This function MUST be called before read_lines() // Otherwise we will loose all edges from faces (see read_lines() above) // // TODO: import uv set names // ======================================================================== void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) { unsigned int i; allocate_poly_data(collada_mesh, me); UVDataWrapper uvs(collada_mesh->getUVCoords()); VCOLDataWrapper vcol(collada_mesh->getColors()); MPoly *mpoly = me->mpoly; MLoop *mloop = me->mloop; int loop_index = 0; MaterialIdPrimitiveArrayMap mat_prim_map; COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives(); COLLADAFW::MeshVertexData& nor = collada_mesh->getNormals(); for (i = 0; i < prim_arr.getCount(); i++) { COLLADAFW::MeshPrimitive *mp = prim_arr[i]; // faces size_t prim_totpoly = mp->getFaceCount(); unsigned int *position_indices = mp->getPositionIndices().getData(); unsigned int *normal_indices = mp->getNormalIndices().getData(); bool mp_has_normals = primitive_has_useable_normals(mp); bool mp_has_faces = primitive_has_faces(mp); int collada_meshtype = mp->getPrimitiveType(); // since we cannot set mpoly->mat_nr here, we store a portion of me->mpoly in Primitive Primitive prim = {mpoly, 0}; // If MeshPrimitive is TRIANGLE_FANS we split it into triangles // The first trifan vertex will be the first vertex in every triangle // XXX The proper function of TRIANGLE_FANS is not tested!!! // XXX In particular the handling of the normal_indices looks very wrong to me if (collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLE_FANS) { unsigned grouped_vertex_count = mp->getGroupedVertexElementsCount(); for (unsigned int group_index = 0; group_index < grouped_vertex_count; group_index++) { unsigned int first_vertex = position_indices[0]; // Store first trifan vertex unsigned int first_normal = normal_indices[0]; // Store first trifan vertex normal unsigned int vertex_count = mp->getGroupedVerticesVertexCount(group_index); for (unsigned int vertex_index = 0; vertex_index < vertex_count - 2; vertex_index++) { // For each triangle store indeces of its 3 vertices unsigned int triangle_vertex_indices[3] = {first_vertex, position_indices[1], position_indices[2]}; set_poly_indices(mpoly, mloop, loop_index, triangle_vertex_indices, 3); if (mp_has_normals) { // vertex normals, same inplementation as for the triangles // the same for vertces normals unsigned int vertex_normal_indices[3] = {first_normal, normal_indices[1], normal_indices[2]}; if (!is_flat_face(vertex_normal_indices, nor, 3)) mpoly->flag |= ME_SMOOTH; normal_indices++; } mpoly++; mloop += 3; loop_index += 3; prim.totpoly++; } // Moving cursor to the next triangle fan. if (mp_has_normals) normal_indices += 2; position_indices += 2; } } if (collada_meshtype == COLLADAFW::MeshPrimitive::POLYLIST || collada_meshtype == COLLADAFW::MeshPrimitive::POLYGONS || collada_meshtype == COLLADAFW::MeshPrimitive::TRIANGLES) { COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp; unsigned int start_index = 0; COLLADAFW::IndexListArray& index_list_array_uvcoord = mp->getUVCoordIndicesArray(); COLLADAFW::IndexListArray& index_list_array_vcolor = mp->getColorIndicesArray(); for (unsigned int j = 0; j < prim_totpoly; j++) { // Vertices in polygon: int vcount = get_vertex_count(mpvc, j); set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount); for (unsigned int uvset_index = 0; uvset_index < index_list_array_uvcoord.getCount(); uvset_index++) { // get mtface by face index and uv set index COLLADAFW::IndexList& index_list = *index_list_array_uvcoord[uvset_index]; MLoopUV *mloopuv = (MLoopUV *)CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, index_list.getName().c_str()); if (mloopuv == NULL) { fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to TEXCOORD [#%s].\n", me->id.name, index_list.getName().c_str() ); } else { set_face_uv(mloopuv+loop_index, uvs, start_index, *index_list_array_uvcoord[uvset_index], vcount); } } if (mp_has_normals) { if (!is_flat_face(normal_indices, nor, vcount)) mpoly->flag |= ME_SMOOTH; } if (mp->hasColorIndices()) { int vcolor_count = index_list_array_vcolor.getCount(); for (unsigned int vcolor_index = 0; vcolor_index < vcolor_count; vcolor_index++) { COLLADAFW::IndexList& color_index_list = *mp->getColorIndices(vcolor_index); COLLADAFW::String colname = extract_vcolname(color_index_list.getName()); MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_named(&me->ldata, CD_MLOOPCOL, colname.c_str()); if (mloopcol == NULL) { fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to VCOLOR [#%s].\n", me->id.name, color_index_list.getName().c_str()); } else { set_vcol(mloopcol + loop_index, vcol, start_index, color_index_list, vcount); } } } mpoly++; mloop += vcount; loop_index += vcount; start_index += vcount; prim.totpoly++; if (mp_has_normals) normal_indices += vcount; position_indices += vcount; } } else if (collada_meshtype == COLLADAFW::MeshPrimitive::LINES) { continue; // read the lines later after all the rest is done } if (mp_has_faces) mat_prim_map[mp->getMaterialId()].push_back(prim); } geom_uid_mat_mapping_map[collada_mesh->getUniqueId()] = mat_prim_map; }
AssetLoader::submeshptr_type AssimpAssetLoader::buildSubMesh(const aiNode *node, int mMeshes_index, aiMatrix4x4 &worldSpace) { unsigned int mesh_index = node->mMeshes[mMeshes_index]; aiMesh *ai_mesh = mScene->mMeshes[mesh_index]; // create the submesh submeshptr_type submesh = createSubMeshImpl(node->mName.C_Str()); // copy the verts to memory managed by us std::vector<Vertex> verts(ai_mesh->mNumVertices); AssimpHelpers::copyAiVector3DToGLM(verts.data(), ai_mesh->mNumVertices, ai_mesh->mVertices); // copy the face indices to memory managed by us Face faces[ai_mesh->mNumFaces]; AssimpHelpers::copyAiFaceToGLM(faces, ai_mesh->mNumFaces, ai_mesh->mFaces); // create the material Material *mat = getMaterial(ai_mesh->mMaterialIndex); setSubMeshMaterialImpl(submesh, mat); setSubMeshGeometryImpl(submesh, verts.data(), ai_mesh->mNumVertices, faces, ai_mesh->mNumFaces); if(ai_mesh->GetNumUVChannels() > 0 && ai_mesh->mNumUVComponents[0] == 2) { // we only support 2 component texture lookups on texture 0 // copy the verts to memory managed by us std::vector<TexCoord> uvs(ai_mesh->mNumVertices); AssimpHelpers::copyAiTexCoordToGLM(uvs.data(), ai_mesh->mNumVertices, ai_mesh->mTextureCoords[0]); setSubMeshUVsImpl(submesh, uvs.data(), ai_mesh->mNumVertices); } // if we have normals, grab them too if(ai_mesh->HasNormals()) { std::vector<Vertex> normals(ai_mesh->mNumVertices); AssimpHelpers::copyAiVector3DToGLM(normals.data(), ai_mesh->mNumVertices, ai_mesh->mNormals); setSubMeshNormalsImpl(submesh, normals.data(), ai_mesh->mNumVertices); } /* // process any skeleton if(ai_mesh->HasBones()) { std::cout << "got a skeleton" << std::endl; for (int i = 0; i < ai_mesh->mNumBones; ++i) { aiBone *bone = ai_mesh->mBones[i]; std::cout << "\tBone: " << bone->mName.C_Str() << " mNumWeights: " << bone->mNumWeights << std::endl; aiNode *boneNode = mScene->mRootNode->FindNode(bone->mName); if(boneNode) { std::cout << "\tboneNode" << boneNode->mName.C_Str() << std::endl; } else { std::cout << "Error could not find Node in heirarchy for bone " << bone->mName.C_Str() << std::endl; } } }*/ return submesh; }
std::vector<std::shared_ptr<Shape>> CreateNURBS(const Transform *o2w, const Transform *w2o, bool reverseOrientation, const ParamSet ¶ms) { int nu = params.FindOneInt("nu", -1); if (nu == -1) { Error("Must provide number of control points \"nu\" with NURBS shape."); return std::vector<std::shared_ptr<Shape>>(); } int uorder = params.FindOneInt("uorder", -1); if (uorder == -1) { Error("Must provide u order \"uorder\" with NURBS shape."); return std::vector<std::shared_ptr<Shape>>(); } int nuknots, nvknots; const Float *uknots = params.FindFloat("uknots", &nuknots); if (uknots == nullptr) { Error("Must provide u knot vector \"uknots\" with NURBS shape."); return std::vector<std::shared_ptr<Shape>>(); } if (nuknots != nu + uorder) { Error( "Number of knots in u knot vector %d doesn't match sum of " "number of u control points %d and u order %d.", nuknots, nu, uorder); return std::vector<std::shared_ptr<Shape>>(); } Float u0 = params.FindOneFloat("u0", uknots[uorder - 1]); Float u1 = params.FindOneFloat("u1", uknots[nu]); int nv = params.FindOneInt("nv", -1); if (nv == -1) { Error("Must provide number of control points \"nv\" with NURBS shape."); return std::vector<std::shared_ptr<Shape>>(); } int vorder = params.FindOneInt("vorder", -1); if (vorder == -1) { Error("Must provide v order \"vorder\" with NURBS shape."); return std::vector<std::shared_ptr<Shape>>(); } const Float *vknots = params.FindFloat("vknots", &nvknots); if (vknots == nullptr) { Error("Must provide v knot vector \"vknots\" with NURBS shape."); return std::vector<std::shared_ptr<Shape>>(); } if (nvknots != nv + vorder) { Error( "Number of knots in v knot vector %d doesn't match sum of " "number of v control points %d and v order %d.", nvknots, nv, vorder); return std::vector<std::shared_ptr<Shape>>(); } Float v0 = params.FindOneFloat("v0", vknots[vorder - 1]); Float v1 = params.FindOneFloat("v1", vknots[nv]); bool isHomogeneous = false; int npts; const Float *P = (const Float *)params.FindPoint3f("P", &npts); if (!P) { P = params.FindFloat("Pw", &npts); if (!P) { Error( "Must provide control points via \"P\" or \"Pw\" parameter to " "NURBS shape."); return std::vector<std::shared_ptr<Shape>>(); } if ((npts % 4) != 0) { Error( "Number of \"Pw\" control points provided to NURBS shape must " "be " "multiple of four"); return std::vector<std::shared_ptr<Shape>>(); } npts /= 4; isHomogeneous = true; } if (npts != nu * nv) { Error("NURBS shape was expecting %dx%d=%d control points, was given %d", nu, nv, nu * nv, npts); return std::vector<std::shared_ptr<Shape>>(); } // Compute NURBS dicing rates int diceu = 30, dicev = 30; std::unique_ptr<Float[]> ueval(new Float[diceu]); std::unique_ptr<Float[]> veval(new Float[dicev]); std::unique_ptr<Point3f[]> evalPs(new Point3f[diceu * dicev]); std::unique_ptr<Normal3f[]> evalNs(new Normal3f[diceu * dicev]); int i; for (i = 0; i < diceu; ++i) ueval[i] = Lerp((float)i / (float)(diceu - 1), u0, u1); for (i = 0; i < dicev; ++i) veval[i] = Lerp((float)i / (float)(dicev - 1), v0, v1); // Evaluate NURBS over grid of points memset(evalPs.get(), 0, diceu * dicev * sizeof(Point3f)); memset(evalNs.get(), 0, diceu * dicev * sizeof(Point3f)); std::unique_ptr<Point2f[]> uvs(new Point2f[diceu * dicev]); // Turn NURBS into triangles std::unique_ptr<Homogeneous3[]> Pw(new Homogeneous3[nu * nv]); if (isHomogeneous) { for (int i = 0; i < nu * nv; ++i) { Pw[i].x = P[4 * i]; Pw[i].y = P[4 * i + 1]; Pw[i].z = P[4 * i + 2]; Pw[i].w = P[4 * i + 3]; } } else { 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[(v * diceu + u)].x = ueval[u]; uvs[(v * diceu + u)].y = veval[v]; Vector3f dpdu, dpdv; Point3f pt = NURBSEvaluateSurface(uorder, uknots, nu, ueval[u], vorder, vknots, nv, veval[v], Pw.get(), &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] = Normal3f(Normalize(Cross(dpdu, dpdv))); } } // Generate points-polygons mesh int nTris = 2 * (diceu - 1) * (dicev - 1); std::unique_ptr<int[]> vertices(new int[3 * nTris]); int *vertp = vertices.get(); // 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; return CreateTriangleMesh(o2w, w2o, reverseOrientation, nTris, vertices.get(), nVerts, evalPs.get(), nullptr, evalNs.get(), uvs.get(), nullptr); }
void PerlinNoise::execute_attributes(const CompositeDataBuffer &input, DataBuffer &output, DataBuffer::size_type index) const { PerlinNoiseData& data = *output.get_scratch_ref<std::shared_ptr<PerlinNoiseData>>(0); int dimensions = data.dimensions; const float* attribute_point = get_input_point_attribute(index, input, dimensions); std::vector<int> dimension_starts(dimensions); std::vector<std::vector<int>> points; std::vector<int> gradient_indexes; int num_gradients = data.vectors.size() / dimensions; // Get floor(x), floor(y), floor(z) etc for(int i = 0; i < dimensions; i++) { dimension_starts[i] = std::floor(attribute_point[i]); } // Get all points in the hypercube surrounding the input point get_point_permutations(dimension_starts, dimensions, std::vector<int>(), points); // Get all rng gradients for each point. Hash x/y/z to get index into gradients array for(unsigned int i = 0; i < points.size(); i++) { std::vector<int>& point = points[i]; unsigned int sum = 0; for(int j = 0; j < dimensions; j++) { static const unsigned int primes[] { 1699, 2237, 2671, 3571, 1949, 2221, 3469, 3083 }; sum += point[j] * point[j] * primes[j]; //Hopefully this has enough entropy and random enough results } gradient_indexes.push_back(sum % num_gradients); } // Because of how the get_point_permutations algorithm works, adjacent verticies are in pairs recursively // There will always be an even number of points (2^n) std::vector<float> out(points.size()); // vector from the first hypercube vertex to the input point (main diagonal) i.e. uv std::vector<float> uvs(dimensions); for(int i = 0; i < dimensions; i++) { uvs[i] = attribute_point[i] - points[0][i]; } // Number of vertexes for an n-dimensional hypercube is 2^n int num_points = std::pow(2, dimensions); // Find dot product for every vertex. // Multiply the vector from the hypercube vertex to the input point, and the gradient at the hypercube vertex for(int i = 0; i < num_points; i++) { std::vector<int>& point = points[i]; int gradient_index = gradient_indexes[i] * dimensions; // In theory, the dot products will be -1 to 1 float dot = 0; for(int j = 0; j < dimensions; j++) { // gradient value (for this dimension) at hypercube vertex signed char gradient_u = data.vectors[gradient_index + j]; // input point (in this dimension) float attr_p = attribute_point[j]; // vector (for this dimension) from hypercube vertex to input point float u = attr_p - point[j]; dot += u * gradient_u; } out[i] = dot; } // Collapse the dimensions down int current_dimension = dimensions; for(; num_points > 1; num_points /= 2) { // Take the dot products two at a time and interpolate between then int half_num = num_points / 2; for(int i = 0; i < half_num; i++) { int index = i * 2; float x_1 = out[index]; float x_2 = out[index + 1]; float u = uvs[current_dimension - 1]; float interpolated = 6 * std::pow(u, 5) - (15 * std::pow(u, 4)) + (10 * std::pow(u, 3)); out[i] = (x_1 * (1.0f - interpolated)) + (x_2 * interpolated); } current_dimension--; } output.set_attribute<float, 1>(*output_socket_, index, &out[0]); }
SGridder::SGridder(SGridderConfig cfg) { // ** Input scale = Param<double>("scale"); grid_size = Param<int>("grid_size"); vis = ImageParam(type_of<double>(), 2, "vis"); // GCF: Array of OxOxSxS complex numbers. We "fuse" two dimensions // as Halide only supports up to 4 dimensions. gcf_fused = ImageParam(type_of<double>(), 4, "gcf"); // ** Output // Grid starts out undefined so we can update the output buffer F(uvg); uvg(cmplx, x, y) = undef<double>(); // Get grid limits. This limits the uv pixel coordinates we accept // for the top-left corner of the GCF. Expr min_u = uvg.output_buffer().min(1); Expr max_u = uvg.output_buffer().min(1) + uvg.output_buffer().extent(1) - cfg.gcfSize - 1; Expr min_v = uvg.output_buffer().min(2); Expr max_v = uvg.output_buffer().min(2) + uvg.output_buffer().extent(2) - cfg.gcfSize - 1; // ** Helpers // Coordinate preprocessing Func Q(uvs); F(uv), F(overc); uvs(uvdim, t) = vis(uvdim, t) * scale; overc(uvdim, t) = clamp(cast<int>(round(OVER * (uvs(uvdim, t) - floor(uvs(uvdim, t))))), 0, OVER-1); uv(uvdim, t) = cast<int>(floor(uvs(uvdim, t)) + grid_size / 2 - cfg.gcfSize / 2); // Visibilities to ignore due to being out of bounds F(inBound); inBound(t) = uv(_U, t) >= min_u && uv(_U, t) <= max_u && uv(_V, t) >= min_v && uv(_V, t) <= max_v; // GCF lookup for a given visibility Func Q(gcf); Var suppx("suppx"), suppy("suppy"), overx("overx"), overy("overy"); gcf(suppx, suppy, t) = Complex(gcf_fused(_REAL, suppx, suppy, overc(_U, t) + OVER * overc(_V, t)), gcf_fused(_IMAG, suppx, suppy, overc(_U, t) + OVER * overc(_V, t))); // ** Definition // Reduction domain. Note that we iterate over time steps before // switching the GCF row in order to increase locality (Romein). typedef std::pair<Expr, Expr> rType; rType cRange = {0, _CPLX_FIELDS} , gRange = {0, cfg.gcfSize} , vRange = {0, cfg.steps} , blRange = {0, vis.height() / cfg.steps} ; std::vector<rType> rVec(5); rVec[cfg.cpos] = cRange; rVec[cfg.xpos] = gRange; rVec[cfg.ypos] = gRange; rVec[cfg.vpos] = vRange; rVec[cfg.blpos] = blRange; RDom red(rVec); rcmplx = red[cfg.cpos] , rgcfx = red[cfg.xpos] , rgcfy = red[cfg.ypos] , rstep = red[cfg.vpos] , rbl = red[cfg.blpos] ; Expr rvis = vis.top() + cfg.steps * rbl + rstep; // Get visibility as complex number Complex visC(vis(_R, rvis), vis(_I, rvis)); // Update grid uvg(rcmplx, rgcfx + clamp(uv(_U, rvis), min_u, max_u), rgcfy + clamp(uv(_V, rvis), min_v, max_v)) += select(inBound(rvis), (visC * Complex(gcf(rgcfx, rgcfy, rvis))).unpack(rcmplx), undef<double>()); if (cfg.dim & (1 << _VIS0)) vis.set_min(0,0).set_stride(0,1).set_extent(0,_VIS_FIELDS); if (cfg.dim & (1 << _VIS1)) vis.set_stride(1,_VIS_FIELDS); if (cfg.dim & (1 << _GCF0)) gcf_fused.set_min(0,0).set_stride(0,1).set_extent(0,_CPLX_FIELDS); if (cfg.dim & (1 << _GCF1)) gcf_fused.set_min(1,0).set_stride(1,_CPLX_FIELDS).set_extent(1,cfg.gcfSize); if (cfg.dim & (1 << _GCF2)) gcf_fused.set_min(2,0).set_stride(2,_CPLX_FIELDS*cfg.gcfSize).set_extent(2,cfg.gcfSize); if (cfg.dim & (1 << _GCF3)) gcf_fused.set_min(3,0).set_stride(3,_CPLX_FIELDS*cfg.gcfSize*cfg.gcfSize).set_extent(3,OVER*OVER); if (cfg.dim & (1 << _UVG0)) uvg.output_buffer().set_stride(0,1).set_extent(0,_CPLX_FIELDS); if (cfg.dim & (1 << _UVG1)) uvg.output_buffer().set_stride(1,_CPLX_FIELDS); // Compute UV & oversampling coordinates per visibility overc.compute_at(uvg, rstep).vectorize(uvdim); uv.compute_at(uvg, rstep).vectorize(uvdim); inBound.compute_at(uvg, rstep); RVar rgcfxc("rgcfxc"); switch(cfg.upd) { case _UPD_NONE: break; case _UPD_VECT: uvg.update() .allow_race_conditions() .vectorize(rcmplx); break; case _UPD_FUSE: uvg.update() .allow_race_conditions() .fuse(rgcfx, rcmplx, rgcfxc) .vectorize(rgcfxc, cfg.vector); break; case _UPD_FUSE_UNROLL: uvg.update() .allow_race_conditions() .fuse(rgcfx, rcmplx, rgcfxc) .vectorize(rgcfxc, cfg.vector) .unroll(rgcfxc, cfg.gcfSize * 2 / cfg.vector); break; case _UPD_UNROLL: uvg.update() .unroll(rcmplx); break; } }
void vixo_hairStyleMaya::exportNoise(MString uvInfo,MString noiseInfo,MDataBlock& data) { //getUVinfo ifstream fin(uvInfo.asChar(),ios_base::in|ios_base::binary); int triNum; fin.read((char*)&triNum,sizeof(int)); vector<int> hairNumPerTri(triNum); fin.read((char*)&hairNumPerTri[0],sizeof(int)*triNum); vector<int> ctrlVert(triNum*3); fin.read((char*)&ctrlVert[0],sizeof(int)*triNum*3); vector<int> hairStartIdxPerTri(triNum,0); int hairNum=0; for(int i=1;i<triNum;i++) { hairStartIdxPerTri[i]=hairStartIdxPerTri[i-1]+hairNumPerTri[i-1]; } hairNum=hairStartIdxPerTri[triNum-1]+hairNumPerTri[triNum-1]; vector<float> uvs(hairNum*2); fin.read((char*)&uvs[0],sizeof(float)*hairNum*2); fin.close(); //get noise data float lengthNoiseAmpValue=data.inputValue(lengthNoiseAmp).asFloat(); float lengthNoiseFreqValue=data.inputValue(lengthNoiseFreq).asFloat(); float inclinationNoiseAmpValue=data.inputValue(inclinationNoiseAmp).asFloat(); float inclinationNoiseFreqValue=data.inputValue(inclinationNoiseFreq).asFloat(); float polarNoiseAmpValue=data.inputValue(polarNoiseAmp).asFloat(); float polarNoiseFreqValue=data.inputValue(polarNoiseFreq).asFloat(); float tipCurlNoiseAmpValue=data.inputValue(tipCurlNoiseAmp).asFloat(); float tipCurlNoiseFreqValue=data.inputValue(tipCurlNoiseFreq).asFloat(); float baseCurlNoiseAmpValue=data.inputValue(baseCurlNoiseAmp).asFloat(); float baseCurlNoiseFreqValue=data.inputValue(baseCurlNoiseFreq).asFloat(); //~get noise data const float PI=3.1415926; vector<follicleNoise> hairNoise(hairNum); for(int i=0;i<hairNum;i++) { float lenn=noise::atPointUV(uvs[2*i]*lengthNoiseFreqValue,uvs[2*i+1]*lengthNoiseFreqValue); hairNoise[i].length=(lenn*2-1)*lengthNoiseAmpValue+1; hairNoise[i].inclination=(noise::atPointUV(uvs[2*i]*inclinationNoiseFreqValue,uvs[2*i+1]*inclinationNoiseFreqValue)*2-1)*lengthNoiseAmpValue*PI/2; hairNoise[i].polar=(noise::atPointUV(uvs[2*i]*polarNoiseFreqValue,uvs[2*i+1]*polarNoiseFreqValue)*2-1)*polarNoiseAmpValue*PI; hairNoise[i].tipCurl=(noise::atPointUV(uvs[2*i]*tipCurlNoiseFreqValue,uvs[2*i+1]*tipCurlNoiseFreqValue)*2-1)*tipCurlNoiseAmpValue*PI/6; hairNoise[i].baseCurl=(noise::atPointUV(uvs[2*i]*baseCurlNoiseFreqValue,uvs[2*i+1]*baseCurlNoiseFreqValue)*2-1)*baseCurlNoiseAmpValue*PI/6; } vector<streampos> startPos(triNum); startPos[0]=sizeof(int)+sizeof(streampos)*triNum; for(int i=1;i<triNum;i++) { startPos[i]=startPos[i-1].operator+(sizeof(int)+sizeof(follicleNoise)*hairNumPerTri[i-1]); } //print noise info fstream fout(noiseInfo.asChar(),ios_base::out|ios_base::trunc|ios_base::binary); fout.write((char*)&triNum,sizeof(int)); fout.write((char*)&startPos[0],sizeof(streampos)*triNum); for(int i=0;i<triNum;i++) { fout.write((char*)&hairNumPerTri[i],sizeof(int)); fout.write((char*)&hairNoise[hairStartIdxPerTri[i]],sizeof(follicleNoise)*hairNumPerTri[i]); } fout.flush(); fout.close(); //~print noise info //debug /* noiseInfo=noiseInfo+"debug"; fout.open(noiseInfo.asChar(),ios_base::out|ios_base::trunc); fout<<triNum<<endl; for(int i=0;i<triNum;i++) { fout<<i<<":"<<startPos[i]<<'\t'<<hairNumPerTri[i]<<endl; for(int j=0;j<hairNumPerTri[i];j++) { fout<<'\t'<<j<<":"<<hairNoise[hairStartIdxPerTri[i]+j].length <<'\t'<<hairNoise[hairStartIdxPerTri[i]+j].inclination <<'\t'<<hairNoise[hairStartIdxPerTri[i]+j].polar <<'\t'<<hairNoise[hairStartIdxPerTri[i]+j].tipCurl <<'\t'<<hairNoise[hairStartIdxPerTri[i]+j].baseCurl<<endl; } } fout.flush(); fout.close(); */ //~debug }
void vixo_hairStyleMaya::exportColor(MString uvInfo,MString colorInfo,MDataBlock& data) { //getUVinfo ifstream fin(uvInfo.asChar(),ios_base::in|ios_base::binary); int triNum; fin.read((char*)&triNum,sizeof(int)); vector<int> hairNumPerTri(triNum); fin.read((char*)&hairNumPerTri[0],sizeof(int)*triNum); vector<int> ctrlVert(triNum*3); fin.read((char*)&ctrlVert[0],sizeof(int)*triNum*3); vector<int> hairStartIdxPerTri(triNum,0); int hairNum=0; for(int i=1;i<triNum;i++) { hairStartIdxPerTri[i]=hairStartIdxPerTri[i-1]+hairNumPerTri[i-1]; } hairNum=hairStartIdxPerTri[triNum-1]+hairNumPerTri[triNum-1]; vector<float> uvs(hairNum*2); fin.read((char*)&uvs[0],sizeof(float)*hairNum*2); fin.close(); //getTextureInfo vector<follicleColor> follicleInfo(hairNum); getTextureInfo("densityMap",uvs,follicleInfo,data); getTextureInfo("tipColor",uvs,follicleInfo,data); getTextureInfo("baseColor",uvs,follicleInfo,data); getTextureInfo("tipOpacity",uvs,follicleInfo,data); getTextureInfo("baseOpacity",uvs,follicleInfo,data); vector<streampos> startPos(triNum); startPos[0]=sizeof(int)+sizeof(streampos)*triNum; for(int i=1;i<triNum;i++) { startPos[i]=startPos[i-1].operator+(sizeof(int)+sizeof(follicleColor)*hairNumPerTri[i-1]); } //Êä³ö fstream fout(colorInfo.asChar(),ios_base::out|ios_base::trunc|ios_base::binary); fout.write((char*)&triNum,sizeof(int)); fout.write((char*)&startPos[0],sizeof(streampos)*triNum); for(int i=0;i<triNum;i++) { fout.write((char*)&hairNumPerTri[i],sizeof(int)); fout.write((char*)&follicleInfo[hairStartIdxPerTri[i]],sizeof(follicleColor)*hairNumPerTri[i]); } fout.flush(); fout.close(); //Êä³ö /* colorInfo=colorInfo+"debug"; fout.open(colorInfo.asChar(),ios_base::out|ios_base::trunc); fout<<triNum<<endl; for(int i=0;i<triNum;i++) { fout<<i<<":"<<startPos[i]<<'\t'<<hairNumPerTri[i]<<endl; for(int j=0;j<hairNumPerTri[i];j++) { fout<<'\t'<<j<<":"<<follicleInfo[hairStartIdxPerTri[i]+j].density<<'\t'<<follicleInfo[hairStartIdxPerTri[i]+j].tipColorB<<endl; } } fout.flush(); fout.close(); */ }
void vixo_hairStyleMaya::exportFollicle(int hairNumValue,MString uvFileName,MString hairRootInfo,MDataBlock& data) { MObject meshObj=data.inputValue(inMesh).asMesh(); MItMeshPolygon iterFace(meshObj); double area=0.0; int triTotNum=0; for(iterFace.reset();!iterFace.isDone();iterFace.next()) { double areaTmp; iterFace.getArea(areaTmp); area+=areaTmp; int triTotNumTmp; iterFace.numTriangles(triTotNumTmp); triTotNum+=triTotNumTmp; if(iterFace.isDone()) break; } MFnMesh fnMesh(meshObj); vector<vector<float>> uv(triTotNum); vector<int> triInfoIndex(triTotNum,0); //numFollicle vector<streampos> triInfoPosIndex(triTotNum); vector<int> vertexCtrl(triTotNum*3); vector<vector<float>> vertexWeight(triTotNum); double diff=sqrt(area/hairNumValue); int hairIter=0; int triIter=0; for(iterFace.reset();!iterFace.isDone();iterFace.next()) { MIntArray faceVertexIndex; iterFace.getVertices(faceVertexIndex); MVectorArray faceNormals; iterFace.getNormals(faceNormals,MSpace::kWorld); MFloatVectorArray faceTangents; fnMesh.getFaceVertexTangents(iterFace.index(),faceTangents,MSpace::kWorld); map<int,int> vertexIndex2faceIndex; for(int i=0;i<faceVertexIndex.length();i++) { vertexIndex2faceIndex.insert(pair<int,int>(faceVertexIndex[i],i)); } int triNum; iterFace.numTriangles(triNum); MString uvset("map1"); for(int tri=0;tri<triNum;tri++) { MPointArray vertex; MIntArray vertexIndex; iterFace.getTriangle(tri,vertex,vertexIndex); int numLine1=MVector(vertex[1]-vertex[0]).length()/diff; int numLine2=MVector(vertex[2]-vertex[0]).length()/diff; MFloatArray uvs(6); float2 tempUV; iterFace.getUV(vertexIndex2faceIndex.find(vertexIndex[0])->second,tempUV,&uvset); uvs[0]=tempUV[0]; uvs[1]=tempUV[1]; iterFace.getUV(vertexIndex2faceIndex.find(vertexIndex[1])->second,tempUV,&uvset); uvs[2]=tempUV[0]; uvs[3]=tempUV[1]; iterFace.getUV(vertexIndex2faceIndex.find(vertexIndex[2])->second,tempUV,&uvset); uvs[4]=tempUV[0]; uvs[5]=tempUV[1]; vertexCtrl[3*triIter]=vertexIndex[1]; vertexCtrl[3*triIter+1]=vertexIndex[2]; vertexCtrl[3*triIter+2]=vertexIndex[0]; for(int i=0;i<numLine1;i++) { for(int j=0;j<(1-(float)i/numLine1)*numLine2;j++) { vertexWeight[triIter].push_back((float)i/numLine1); vertexWeight[triIter].push_back((float)j/numLine2); vertexWeight[triIter].push_back(1-(float)i/numLine1-(float)j/numLine2); int localHairIter=triInfoIndex[triIter]; uv[triIter].push_back(uvs[0]*vertexWeight[triIter][3*localHairIter+2]+uvs[2]*vertexWeight[triIter][3*localHairIter]+uvs[4]*vertexWeight[triIter][3*localHairIter+1]); uv[triIter].push_back(uvs[1]*vertexWeight[triIter][3*localHairIter+2]+uvs[3]*vertexWeight[triIter][3*localHairIter]+uvs[5]*vertexWeight[triIter][3*localHairIter+1]); hairIter++; triInfoIndex[triIter]++; } } triIter++; } if(iterFace.isDone()) break; } //print uv fstream fout(uvFileName.asChar(),ios_base::out|ios_base::binary); fout.write((char*)&triTotNum,sizeof(int)); fout.write((char*)&triInfoIndex[0],sizeof(int)*triTotNum); fout.write((char*)&vertexCtrl[0],sizeof(int)*3*triTotNum); //for cache export for(int i=0;i<triTotNum;i++) //for color info { fout.write((char*)&uv[i][0],sizeof(float)*2*triInfoIndex[i]); } fout.flush(); fout.close(); //~print uv /* //debug uv MString uvDebug=uvFileName+"debug"; fout.open(uvDebug.asChar(),ios_base::out); fout<<triTotNum<<endl; for(int i=0;i<triTotNum;i++) fout<<"tri"<<i<<":"<<'\t'<<triInfoIndex[i]<<'\t'<<vertexCtrl[3*i]<<'\t'<<vertexCtrl[3*i+1]<<'\t'<<vertexCtrl[3*i+2]<<endl; for(int i=0;i<triTotNum;i++) for(int j=0;j<triInfoIndex[i];j++) fout<<"tri"<<i<<":"<<'\t'<<j<<'\t'<<uv[i][2*j]<<'\t'<<uv[i][2*j+1]<<endl; fout.flush(); fout.close(); //~debug uv */ //prepare streampos triInfoPosIndex[0]=sizeof(int)+sizeof(streampos)*triTotNum; for(int i=1;i<triTotNum;i++) { triInfoPosIndex[i]=triInfoPosIndex[i-1].operator+(sizeof(int)+sizeof(float)*3*triInfoIndex[i-1]); } //~prepare streampos //print infos fout.open(hairRootInfo.asChar(),ios_base::out|ios_base::binary); fout.write((char*)&triTotNum,sizeof(int)); fout.write((char*)&triInfoPosIndex[0],sizeof(streampos)*triTotNum); for(int i=0;i<triTotNum;i++) //for color info { fout.write((char*)&triInfoIndex[i],sizeof(int)); fout.write((char*)&vertexWeight[i][0],sizeof(float)*3*triInfoIndex[i]); } fout.flush(); fout.close(); //~print infos /* //debug info MString hairRootInfoDebug=hairRootInfo+"debug"; fout.open(hairRootInfoDebug.asChar(),ios_base::out); fout<<triTotNum<<endl; for(int i=0;i<triTotNum;i++) fout<<"tri"<<i<<":"<<'\t'<<triInfoIndex[i]<<'\t'<<triInfoPosIndex[i]<<endl; for(int i=0;i<triTotNum;i++) for(int j=0;j<triInfoIndex[i];j++) fout<<"tri"<<i<<":"<<'\t'<<j<<'\t'<<vertexWeight[i][3*j]<<'\t'<<vertexWeight[i][3*j+1]<<'\t'<<vertexWeight[i][3*j+2]<<endl; fout.flush(); fout.close(); //~debug info */ }