Fixed a bug in SilhouetteGeomEngine::ImageToWorldParameter() that caused
[blender.git] / source / blender / freestyle / intern / blender_interface / BlenderFileLoader.cpp
1 #include "BlenderFileLoader.h"
2
3 BlenderFileLoader::BlenderFileLoader(Render *re, SceneRenderLayer* srl)
4 {
5         _re = re;
6         _srl = srl;
7   _Scene = NULL;
8   _numFacesRead = 0;
9   _minEdgeSize = DBL_MAX;
10 }
11
12 BlenderFileLoader::~BlenderFileLoader()
13 {
14   _Scene = NULL;
15 }
16
17 NodeGroup* BlenderFileLoader::Load()
18 {
19         ObjectInstanceRen *obi;
20         ObjectRen *obr;
21
22         cout << "\n===  Importing triangular meshes into Blender  ===" << endl;
23
24         // creation of the scene root node
25         _Scene = new NodeGroup;
26
27         _viewplane_left=   _re->viewplane.xmin;
28         _viewplane_right=  _re->viewplane.xmax;
29         _viewplane_bottom= _re->viewplane.ymin;
30         _viewplane_top=    _re->viewplane.ymax;
31         _z_near= _re->clipsta;
32         _z_far=  _re->clipend;
33 #if 0
34         cout << "frustrum: l " << _viewplane_left << " r " << _viewplane_right
35                 << " b " << _viewplane_bottom << " t " << _viewplane_top
36                 << " n " << _z_near << " f " << _z_far << endl;
37 #endif
38
39         int id = 0;
40         for(obi= (ObjectInstanceRen *) _re->instancetable.first; obi; obi=obi->next) {
41                 if (!(obi->lay & _re->scene->lay & _srl->lay))
42                         continue;
43
44                 obr= obi->obr;
45                 
46                 if( obr->totvlak > 0)
47                         insertShapeNode(obr, ++id);
48                 else
49                         cout << "  Sorry, only vlak-based shapes are supported." << endl;
50         }
51
52         //Returns the built scene.
53         return _Scene;
54 }
55
56 void BlenderFileLoader::insertShapeNode(ObjectRen *obr, int id)
57 {
58                 VlakRen *vlr;
59         
60         float minBBox[3];
61         float maxBBox[3];
62         
63         NodeTransform *currentMesh = new NodeTransform;
64         NodeShape * shape;
65         
66         // Mesh *mesh = (Mesh *)ob->data;
67         //---------------------
68         // mesh => obr
69         
70         // builds the shape:
71         shape = new NodeShape;
72         
73         // 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)
74         // Lib3dsMatrix M;
75         // lib3ds_matrix_copy(M, mesh->matrix);
76         // lib3ds_matrix_inv(M);
77         //---------------------
78         // M allows to recover world coordinates from camera coordinates
79         // M => obr->ob->imat * obr->obmat  (multiplication from left to right)
80         float M[4][4];
81         mul_m4_m4m4(M, obr->ob->imat, obr->ob->obmat); 
82         
83         // We compute a normal per vertex and manages the smoothing of the shape:
84         // Lib3dsVector *normalL=(Lib3dsVector*)malloc(3*sizeof(Lib3dsVector)*mesh->faces);
85         // lib3ds_mesh_calculate_normals(mesh, normalL);
86         // mesh_calc_normals(mesh->mvert, mesh->totvert, mesh->mface, mesh->totface, NULL);
87         //---------------------
88         // already calculated and availabe in vlak ?    
89         
90         // We build the rep:
91         IndexedFaceSet *rep;
92         unsigned numFaces = 0;
93         for(int a=0; a < obr->totvlak; a++) {
94                 if((a & 255)==0) vlr= obr->vlaknodes[a>>8].vlak;
95                 else vlr++;
96         
97                 if(vlr->v4)
98                         numFaces += 2;
99                 else
100                         numFaces++;
101         }
102         
103         unsigned vSize = 3*3*numFaces;
104         float *vertices = new float[vSize];
105         unsigned nSize = vSize;
106         float *normals = new float[nSize];
107         unsigned *numVertexPerFaces = new unsigned[numFaces];
108         vector<FrsMaterial> meshFrsMaterials;
109         
110         IndexedFaceSet::TRIANGLES_STYLE *faceStyle = new IndexedFaceSet::TRIANGLES_STYLE[numFaces];
111         unsigned i;
112         for (i = 0; i <numFaces; i++) {
113           faceStyle[i] = IndexedFaceSet::TRIANGLES;
114           numVertexPerFaces[i] = 3;
115         }
116         
117         unsigned viSize = 3*numFaces;
118         unsigned *VIndices = new unsigned[viSize];
119         unsigned niSize = viSize;
120         unsigned *NIndices = new unsigned[niSize];
121         unsigned *MIndices = new unsigned[viSize]; // Material Indices
122         
123         
124         float *pv = vertices;
125         float *pn = normals;
126         unsigned *pvi = VIndices;
127         unsigned *pni = NIndices;
128         unsigned *pmi = MIndices;
129         
130         unsigned currentIndex = 0;
131         unsigned currentMIndex = 0;
132         
133         FrsMaterial tmpMat;
134         
135         // we want to find the min and max coordinates as we build the rep. 
136         // We initialize the min and max values whith the first vertex.
137         //lib3ds_vector_transform(pvtmp, M, mesh->pointL[mesh->faceL[0].points[0]].pos);
138         float pvtmp[3];
139         pvtmp[0] = obr->vertnodes[0].vert->co[0];
140         pvtmp[1] = obr->vertnodes[0].vert->co[1];
141         pvtmp[2] = obr->vertnodes[0].vert->co[2];
142         
143         mul_m4_v3( M, pvtmp);
144         
145         minBBox[0] = pvtmp[0];
146         maxBBox[0] = pvtmp[0];
147         minBBox[1] = pvtmp[1];
148         maxBBox[1] = pvtmp[1];
149         minBBox[2] = pvtmp[2];
150         maxBBox[2] = pvtmp[2];
151         
152         int p;
153         real vert[3][3];
154         real norm;
155         for(p=0; p < obr->totvlak; ++p) // we parse the faces of the mesh
156         {
157                         VertRen * fv[3];
158                 
159                   // Lib3dsFace *f=&mesh->faceL[p];
160                   // Lib3dsMaterial *mat=0;
161                         if((p & 255)==0) vlr = obr->vlaknodes[p>>8].vlak;
162                         else vlr++;
163                         Material *mat = vlr->mat;
164         
165                         if (mat) 
166                         {
167                             tmpMat.setDiffuse( mat->r, mat->g, mat->b, mat->alpha );
168                             tmpMat.setSpecular( mat->specr, mat->specg, mat->specb, mat->spectra);
169                             float s = 1.0 * (mat->har + 1) / 4 ; // in Blender: [1;511] => in OpenGL: [0;128]
170                             if(s > 128.f)
171                               s = 128.f;
172                             tmpMat.setShininess(s);
173                         }
174           
175                         if(meshFrsMaterials.empty())
176                         {
177                                 meshFrsMaterials.push_back(tmpMat);
178                         shape->setFrsMaterial(tmpMat);
179                         } else {
180                         // find if the material is aleady in the list
181                         unsigned i=0;
182                         bool found = false;
183                 
184                         for(vector<FrsMaterial>::iterator it=meshFrsMaterials.begin(), itend=meshFrsMaterials.end();
185                                 it!=itend;
186                                 ++it){
187                                         if(*it == tmpMat){
188                                                 currentMIndex = i;
189                                                 found = true;
190                                                 break;
191                                         }
192                                         ++i;
193                         }
194                 
195                         if(!found){
196                                 meshFrsMaterials.push_back(tmpMat);
197                                 currentMIndex = meshFrsMaterials.size()-1;
198                         }
199                         }
200         
201                         unsigned j;
202                         fv[0] = vlr->v1;
203                         fv[1] = vlr->v2;
204                         fv[2] = vlr->v3;
205                         float *pv_ptr[3];
206                         for(i=0; i<3; ++i) // we parse the vertices of the face f
207                         {
208         
209                                 //lib3ds_vector_transform(pv, M, mesh->pointL[f->points[i]].pos); //fills the cells of the pv array
210                                 for(j=0; j<3; j++)
211                                         pv[j] = fv[i]->co[j];
212                                 mul_m4_v3( M, pv);
213         
214                                 for(j=0; j<3; j++) // we parse the xyz coordinates of the vertex i
215                                 {
216                                         if(minBBox[j] > pv[j])
217                                         minBBox[j] = pv[j];
218         
219                                         if(maxBBox[j] < pv[j])
220                                         maxBBox[j] = pv[j];
221         
222                                         vert[i][j] = pv[j];
223                                 }
224                                 
225                                 pv_ptr[i] = pv;
226                                 *pvi = currentIndex;
227                                 *pmi = currentMIndex;
228
229                                 currentIndex +=3;
230                                 pv += 3;
231
232                                 pvi++;
233                                 pmi++;
234                         }
235                         
236                         currentIndex -= 9;
237                                                 
238                         float vec01[3];
239                         vec01[0] = pv_ptr[1][0] - pv_ptr[0][0]; 
240                         vec01[1] = pv_ptr[1][1] - pv_ptr[0][1];
241                         vec01[2] = pv_ptr[1][2] - pv_ptr[0][2];
242                         
243                         float vec02[3];
244                         vec02[0] = pv_ptr[2][0] - pv_ptr[0][0]; 
245                         vec02[1] = pv_ptr[2][1] - pv_ptr[0][1];
246                         vec02[2] = pv_ptr[2][2] - pv_ptr[0][2];
247                         
248                         float n[3];
249                         cross_v3_v3v3(n, vec01, vec02);
250                         normalize_v3(n);
251                         
252                         for(i=0; i<3; ++i) {
253                                 for(j=0; j<3; ++j) {
254                                         pn[j] = n[j];
255                                 }
256                                 *pni = currentIndex;
257
258                                 pn += 3;
259                                 pni++;
260
261                                 currentIndex +=3;
262                         }
263         
264                         for(i=0; i<3; i++)
265                         {
266                                 norm = 0.0;
267                                 
268                                 for (unsigned j = 0; j < 3; j++)
269                                         norm += (vert[i][j] - vert[(i+1)%3][j])*(vert[i][j] - vert[(i+1)%3][j]);
270                 
271                                 norm = sqrt(norm);
272                                 if(_minEdgeSize > norm)
273                                         _minEdgeSize = norm;
274                         }
275                         
276                         ++_numFacesRead;
277
278                         
279                         if(vlr->v4){
280
281                                 unsigned j;
282                                 fv[0] = vlr->v1;
283                                 fv[1] = vlr->v3;
284                                 fv[2] = vlr->v4;
285                                 float *pv_ptr[3];
286                                 for(i=0; i<3; ++i) // we parse the vertices of the face f
287                                 {
288
289                                         //lib3ds_vector_transform(pv, M, mesh->pointL[f->points[i]].pos); //fills the cells of the pv array
290                                         for(j=0; j<3; j++)
291                                                 pv[j] = fv[i]->co[j];
292                                         mul_m4_v3( M, pv);
293
294                                         for(j=0; j<3; j++) // we parse the xyz coordinates of the vertex i
295                                         {
296                                                 if(minBBox[j] > pv[j])
297                                                 minBBox[j] = pv[j];
298
299                                                 if(maxBBox[j] < pv[j])
300                                                 maxBBox[j] = pv[j];
301
302                                                 vert[i][j] = pv[j];
303                                         }
304
305                                         pv_ptr[i] = pv;
306                                         *pvi = currentIndex;
307                                         *pmi = currentMIndex;
308
309                                         currentIndex +=3;
310                                         pv += 3;
311
312                                         pvi++;
313                                         pmi++;
314                                 }
315
316                                 currentIndex -= 9;
317
318                                 float vec01[3];
319                                 vec01[0] = pv_ptr[1][0] - pv_ptr[0][0]; 
320                                 vec01[1] = pv_ptr[1][1] - pv_ptr[0][1];
321                                 vec01[2] = pv_ptr[1][2] - pv_ptr[0][2];
322
323                                 float vec02[3];
324                                 vec02[0] = pv_ptr[2][0] - pv_ptr[0][0]; 
325                                 vec02[1] = pv_ptr[2][1] - pv_ptr[0][1];
326                                 vec02[2] = pv_ptr[2][2] - pv_ptr[0][2];
327
328                                 float n[3];
329                                 cross_v3_v3v3(n, vec01, vec02);
330                                 normalize_v3(n);
331                                 
332                                 for(i=0; i<3; ++i) {
333                                         for(j=0; j<3; ++j) {
334                                                 pn[j] = n[j];
335                                         }
336                                         *pni = currentIndex;
337
338                                         pn += 3;
339                                         pni++;
340
341                                         currentIndex +=3;
342                                 }
343
344                                 for(i=0; i<3; i++)
345                                 {
346                                         norm = 0.0;
347
348                                         for (unsigned j = 0; j < 3; j++)
349                                                 norm += (vert[i][j] - vert[(i+1)%3][j])*(vert[i][j] - vert[(i+1)%3][j]);
350
351                                         norm = sqrt(norm);
352                                         if(_minEdgeSize > norm)
353                                                 _minEdgeSize = norm;
354                                 }
355
356                                 ++_numFacesRead;
357
358
359
360                         }
361         
362         }
363         
364         // We might have several times the same vertex. We want a clean 
365         // shape with no real-vertex. Here, we are making a cleaning 
366         // pass.
367         real *cleanVertices = NULL;
368         unsigned   cvSize;
369         unsigned   *cleanVIndices = NULL;
370         
371         GeomCleaner::CleanIndexedVertexArray(
372           vertices, vSize, 
373           VIndices, viSize,
374           &cleanVertices, &cvSize, 
375           &cleanVIndices);
376         
377         real *cleanNormals = NULL;
378         unsigned   cnSize;
379         unsigned   *cleanNIndices = NULL;
380         
381         GeomCleaner::CleanIndexedVertexArray(
382           normals, nSize, 
383           NIndices, niSize,
384           &cleanNormals, &cnSize, 
385           &cleanNIndices);
386         
387         // format materials array
388         FrsMaterial** marray = new FrsMaterial*[meshFrsMaterials.size()];
389         unsigned mindex=0;
390         for(vector<FrsMaterial>::iterator m=meshFrsMaterials.begin(), mend=meshFrsMaterials.end();
391             m!=mend;
392             ++m){
393           marray[mindex] = new FrsMaterial(*m);
394           ++mindex;
395         }
396         // deallocates memory:
397         delete [] vertices;
398         delete [] normals;
399         delete [] VIndices;
400         delete [] NIndices;
401         
402         // Create the IndexedFaceSet with the retrieved attributes
403         rep = new IndexedFaceSet(cleanVertices, cvSize, 
404                                  cleanNormals, cnSize,
405                                  marray, meshFrsMaterials.size(),
406                                  0, 0,
407                                  numFaces, numVertexPerFaces, faceStyle,
408                                  cleanVIndices, viSize,
409                                  cleanNIndices, niSize,
410                                  MIndices, viSize,
411                                  0,0,
412                                  0);
413         // sets the id of the rep
414         rep->setId(Id(id, 0));
415         
416         const BBox<Vec3r> bbox = BBox<Vec3r>(Vec3r(minBBox[0], minBBox[1], minBBox[2]), 
417                                              Vec3r(maxBBox[0], maxBBox[1], maxBBox[2]));
418         rep->setBBox(bbox);
419         shape->AddRep(rep);
420         
421         Matrix44r meshMat = Matrix44r::identity();
422         currentMesh->setMatrix(meshMat);
423         currentMesh->Translate(0,0,0);
424         
425         currentMesh->AddChild(shape);
426         _Scene->AddChild(currentMesh);
427         
428 }