diff options
author | Maxime Curioni <maxime.curioni@gmail.com> | 2009-10-05 04:40:33 +0400 |
---|---|---|
committer | Maxime Curioni <maxime.curioni@gmail.com> | 2009-10-05 04:40:33 +0400 |
commit | f5a14015e3585e3c8c82a27f2148e5ce8a54d72f (patch) | |
tree | 107b52a38ebbe617c987e0d3e5ac12831a3536ee /source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp | |
parent | e3e6e3ff0c5bec5fe65ae4e1e5f7f4b70221fcf1 (diff) |
moved all Blender-Freestyle interface-related files to source/freestyle/intern/blender_interface folder
Diffstat (limited to 'source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp')
-rw-r--r-- | source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp new file mode 100644 index 00000000000..f70cdaf8720 --- /dev/null +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -0,0 +1,416 @@ +#include "BlenderFileLoader.h" + +BlenderFileLoader::BlenderFileLoader(Render *re, SceneRenderLayer* srl) +{ + _re = re; + _srl = srl; + _Scene = NULL; + _numFacesRead = 0; + _minEdgeSize = DBL_MAX; +} + +BlenderFileLoader::~BlenderFileLoader() +{ + _Scene = NULL; +} + +NodeGroup* BlenderFileLoader::Load() +{ + ObjectInstanceRen *obi; + ObjectRen *obr; + + cout << "\n=== Importing triangular meshes into Blender ===" << endl; + + // creation of the scene root node + _Scene = new NodeGroup; + + int id = 0; + for(obi= (ObjectInstanceRen *) _re->instancetable.first; obi; obi=obi->next) { + if (!(obi->lay & _re->scene->lay & _srl->lay)) + continue; + + obr= obi->obr; + + if( obr->totvlak > 0) + insertShapeNode(obr, ++id); + else + cout << " Sorry, only vlak-based shapes are supported." << endl; + } + + //Returns the built scene. + return _Scene; +} + +void BlenderFileLoader::insertShapeNode(ObjectRen *obr, int id) +{ + VlakRen *vlr; + + float minBBox[3]; + float maxBBox[3]; + + NodeTransform *currentMesh = new NodeTransform; + NodeShape * shape; + + // Mesh *mesh = (Mesh *)ob->data; + //--------------------- + // mesh => obr + + // builds the shape: + shape = new NodeShape; + + // We invert the matrix in order to be able to retrieve the shape's coordinates in its local coordinates system (origin is the iNode pivot) + // Lib3dsMatrix M; + // lib3ds_matrix_copy(M, mesh->matrix); + // lib3ds_matrix_inv(M); + //--------------------- + // M allows to recover world coordinates from camera coordinates + // M => obr->ob->imat * obr->obmat (multiplication from left to right) + float M[4][4]; + Mat4MulMat4(M, obr->ob->imat, obr->ob->obmat); + + // We compute a normal per vertex and manages the smoothing of the shape: + // Lib3dsVector *normalL=(Lib3dsVector*)malloc(3*sizeof(Lib3dsVector)*mesh->faces); + // lib3ds_mesh_calculate_normals(mesh, normalL); + // mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL); + //--------------------- + // already calculated and availabe in vlak ? + + // We build the rep: + IndexedFaceSet *rep; + unsigned numFaces = 0; + for(int a=0; a < obr->totvlak; a++) { + if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak; + else vlr++; + + if(vlr->v4) + numFaces += 2; + else + numFaces++; + } + + unsigned vSize = 3*3*numFaces; + float *vertices = new float[vSize]; + unsigned nSize = vSize; + float *normals = new float[nSize]; + unsigned *numVertexPerFaces = new unsigned[numFaces]; + vector<FrsMaterial> meshFrsMaterials; + + IndexedFaceSet::TRIANGLES_STYLE *faceStyle = new IndexedFaceSet::TRIANGLES_STYLE[numFaces]; + unsigned i; + for (i = 0; i <numFaces; i++) { + faceStyle[i] = IndexedFaceSet::TRIANGLES; + numVertexPerFaces[i] = 3; + } + + unsigned viSize = 3*numFaces; + unsigned *VIndices = new unsigned[viSize]; + unsigned niSize = viSize; + unsigned *NIndices = new unsigned[niSize]; + unsigned *MIndices = new unsigned[viSize]; // Material Indices + + + float *pv = vertices; + float *pn = normals; + unsigned *pvi = VIndices; + unsigned *pni = NIndices; + unsigned *pmi = MIndices; + + unsigned currentIndex = 0; + unsigned currentMIndex = 0; + + FrsMaterial tmpMat; + + // we want to find the min and max coordinates as we build the rep. + // We initialize the min and max values whith the first vertex. + //lib3ds_vector_transform(pvtmp, M, mesh->pointL[mesh->faceL[0].points[0]].pos); + float pvtmp[3]; + pvtmp[0] = obr->vertnodes[0].vert->co[0]; + pvtmp[1] = obr->vertnodes[0].vert->co[1]; + pvtmp[2] = obr->vertnodes[0].vert->co[2]; + + Mat4MulVecfl( M, pvtmp); + + minBBox[0] = pvtmp[0]; + maxBBox[0] = pvtmp[0]; + minBBox[1] = pvtmp[1]; + maxBBox[1] = pvtmp[1]; + minBBox[2] = pvtmp[2]; + maxBBox[2] = pvtmp[2]; + + int p; + real vert[3][3]; + real norm; + for(p=0; p < obr->totvlak; ++p) // we parse the faces of the mesh + { + VertRen * fv[3]; + + // Lib3dsFace *f=&mesh->faceL[p]; + // Lib3dsMaterial *mat=0; + if((p & 255)==0) vlr = obr->vlaknodes[p>>8].vlak; + else vlr++; + Material *mat = vlr->mat; + + if (mat) + { + tmpMat.setDiffuse( mat->r, mat->g, mat->b, mat->alpha ); + tmpMat.setSpecular( mat->specr, mat->specg, mat->specb, mat->spectra); + float s = 1.0 * (mat->har + 1) / 4 ; // in Blender: [1;511] => in OpenGL: [0;128] + if(s > 128.f) + s = 128.f; + tmpMat.setShininess(s); + } + + if(meshFrsMaterials.empty()) + { + meshFrsMaterials.push_back(tmpMat); + shape->setFrsMaterial(tmpMat); + } else { + // find if the material is aleady in the list + unsigned i=0; + bool found = false; + + for(vector<FrsMaterial>::iterator it=meshFrsMaterials.begin(), itend=meshFrsMaterials.end(); + it!=itend; + ++it){ + if(*it == tmpMat){ + currentMIndex = i; + found = true; + break; + } + ++i; + } + + if(!found){ + meshFrsMaterials.push_back(tmpMat); + currentMIndex = meshFrsMaterials.size()-1; + } + } + + unsigned j; + fv[0] = vlr->v1; + fv[1] = vlr->v2; + fv[2] = vlr->v3; + float *pv_ptr[3]; + for(i=0; i<3; ++i) // we parse the vertices of the face f + { + + //lib3ds_vector_transform(pv, M, mesh->pointL[f->points[i]].pos); //fills the cells of the pv array + for(j=0; j<3; j++) + pv[j] = fv[i]->co[j]; + Mat4MulVecfl( M, pv); + + for(j=0; j<3; j++) // we parse the xyz coordinates of the vertex i + { + if(minBBox[j] > pv[j]) + minBBox[j] = pv[j]; + + if(maxBBox[j] < pv[j]) + maxBBox[j] = pv[j]; + + vert[i][j] = pv[j]; + } + + pv_ptr[i] = pv; + *pvi = currentIndex; + *pmi = currentMIndex; + + currentIndex +=3; + pv += 3; + + pvi++; + pmi++; + } + + currentIndex -= 9; + + float vec01[3]; + vec01[0] = pv_ptr[1][0] - pv_ptr[0][0]; + vec01[1] = pv_ptr[1][1] - pv_ptr[0][1]; + vec01[2] = pv_ptr[1][2] - pv_ptr[0][2]; + + float vec02[3]; + vec02[0] = pv_ptr[2][0] - pv_ptr[0][0]; + vec02[1] = pv_ptr[2][1] - pv_ptr[0][1]; + vec02[2] = pv_ptr[2][2] - pv_ptr[0][2]; + + float n[3]; + Crossf(n, vec01, vec02); + Normalize(n); + + for(i=0; i<3; ++i) { + for(j=0; j<3; ++j) { + pn[j] = n[j]; + } + *pni = currentIndex; + + pn += 3; + pni++; + + currentIndex +=3; + } + + for(i=0; i<3; i++) + { + norm = 0.0; + + for (unsigned j = 0; j < 3; j++) + norm += (vert[i][j] - vert[(i+1)%3][j])*(vert[i][j] - vert[(i+1)%3][j]); + + norm = sqrt(norm); + if(_minEdgeSize > norm) + _minEdgeSize = norm; + } + + ++_numFacesRead; + + + if(vlr->v4){ + + unsigned j; + fv[0] = vlr->v1; + fv[1] = vlr->v3; + fv[2] = vlr->v4; + float *pv_ptr[3]; + for(i=0; i<3; ++i) // we parse the vertices of the face f + { + + //lib3ds_vector_transform(pv, M, mesh->pointL[f->points[i]].pos); //fills the cells of the pv array + for(j=0; j<3; j++) + pv[j] = fv[i]->co[j]; + Mat4MulVecfl( M, pv); + + for(j=0; j<3; j++) // we parse the xyz coordinates of the vertex i + { + if(minBBox[j] > pv[j]) + minBBox[j] = pv[j]; + + if(maxBBox[j] < pv[j]) + maxBBox[j] = pv[j]; + + vert[i][j] = pv[j]; + } + + pv_ptr[i] = pv; + *pvi = currentIndex; + *pmi = currentMIndex; + + currentIndex +=3; + pv += 3; + + pvi++; + pmi++; + } + + currentIndex -= 9; + + float vec01[3]; + vec01[0] = pv_ptr[1][0] - pv_ptr[0][0]; + vec01[1] = pv_ptr[1][1] - pv_ptr[0][1]; + vec01[2] = pv_ptr[1][2] - pv_ptr[0][2]; + + float vec02[3]; + vec02[0] = pv_ptr[2][0] - pv_ptr[0][0]; + vec02[1] = pv_ptr[2][1] - pv_ptr[0][1]; + vec02[2] = pv_ptr[2][2] - pv_ptr[0][2]; + + float n[3]; + Crossf(n, vec01, vec02); + Normalize(n); + + for(i=0; i<3; ++i) { + for(j=0; j<3; ++j) { + pn[j] = n[j]; + } + *pni = currentIndex; + + pn += 3; + pni++; + + currentIndex +=3; + } + + for(i=0; i<3; i++) + { + norm = 0.0; + + for (unsigned j = 0; j < 3; j++) + norm += (vert[i][j] - vert[(i+1)%3][j])*(vert[i][j] - vert[(i+1)%3][j]); + + norm = sqrt(norm); + if(_minEdgeSize > norm) + _minEdgeSize = norm; + } + + ++_numFacesRead; + + + + } + + } + + // We might have several times the same vertex. We want a clean + // shape with no real-vertex. Here, we are making a cleaning + // pass. + real *cleanVertices = NULL; + unsigned cvSize; + unsigned *cleanVIndices = NULL; + + GeomCleaner::CleanIndexedVertexArray( + vertices, vSize, + VIndices, viSize, + &cleanVertices, &cvSize, + &cleanVIndices); + + real *cleanNormals = NULL; + unsigned cnSize; + unsigned *cleanNIndices = NULL; + + GeomCleaner::CleanIndexedVertexArray( + normals, nSize, + NIndices, niSize, + &cleanNormals, &cnSize, + &cleanNIndices); + + // format materials array + FrsMaterial** marray = new FrsMaterial*[meshFrsMaterials.size()]; + unsigned mindex=0; + for(vector<FrsMaterial>::iterator m=meshFrsMaterials.begin(), mend=meshFrsMaterials.end(); + m!=mend; + ++m){ + marray[mindex] = new FrsMaterial(*m); + ++mindex; + } + // deallocates memory: + delete [] vertices; + delete [] normals; + delete [] VIndices; + delete [] NIndices; + + // Create the IndexedFaceSet with the retrieved attributes + rep = new IndexedFaceSet(cleanVertices, cvSize, + cleanNormals, cnSize, + marray, meshFrsMaterials.size(), + 0, 0, + numFaces, numVertexPerFaces, faceStyle, + cleanVIndices, viSize, + cleanNIndices, niSize, + MIndices, viSize, + 0,0, + 0); + // sets the id of the rep + rep->setId(Id(id, 0)); + + const BBox<Vec3r> bbox = BBox<Vec3r>(Vec3r(minBBox[0], minBBox[1], minBBox[2]), + Vec3r(maxBBox[0], maxBBox[1], maxBBox[2])); + rep->setBBox(bbox); + shape->AddRep(rep); + + Matrix44r meshMat = Matrix44r::identity(); + currentMesh->setMatrix(meshMat); + currentMesh->Translate(0,0,0); + + currentMesh->AddChild(shape); + _Scene->AddChild(currentMesh); + +} |