2848
3092
return numleft;
2851
/* ************************* fluidsim bobj file handling **************************** */
2853
#ifndef DISABLE_ELBEEM
2857
#define snprintf _snprintf
2861
/* write .bobj.gz file for a mesh object */
2862
void writeBobjgz(char *filename, struct Object *ob, int useGlobalCoords, int append, float time)
2864
char debugStrBuffer[256];
2865
int wri,i,j,totvert,totface;
2873
//if(append)return; // DEBUG
2875
if(!ob->data || (ob->type!=OB_MESH)) {
2876
snprintf(debugStrBuffer,256,"Writing GZ_BOBJ Invalid object %s ...\n", ob->id.name);
2877
elbeemDebugOut(debugStrBuffer);
2880
if((ob->size[0]<0.0) || (ob->size[0]<0.0) || (ob->size[0]<0.0) ) {
2881
snprintf(debugStrBuffer,256,"\nfluidSim::writeBobjgz:: Warning object %s has negative scaling - check triangle ordering...?\n\n", ob->id.name);
2882
elbeemDebugOut(debugStrBuffer);
2885
snprintf(debugStrBuffer,256,"Writing GZ_BOBJ '%s' ... ",filename); elbeemDebugOut(debugStrBuffer);
2886
if(append) gzf = gzopen(filename, "a+b9");
2887
else gzf = gzopen(filename, "wb9");
2889
snprintf(debugStrBuffer,256,"writeBobjgz::error - Unable to open file for writing '%s'\n", filename);
2890
elbeemDebugOut(debugStrBuffer);
2894
dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
2895
//dm = mesh_create_derived_no_deform(ob,NULL);
2897
mvert = dm->getVertArray(dm);
2898
mface = dm->getFaceArray(dm);
2899
totvert = dm->getNumVerts(dm);
2900
totface = dm->getNumFaces(dm);
2902
// write time value for appended anim mesh
2904
gzwrite(gzf, &time, sizeof(time));
2907
// continue with verts/norms
2908
if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Writing GZ_BOBJ, Invalid int size %d...\n", wri); elbeemDebugOut(debugStrBuffer); return; } // paranoia check
2909
wri = dm->getNumVerts(dm);
2910
mvert = dm->getVertArray(dm);
2911
gzwrite(gzf, &wri, sizeof(wri));
2912
for(i=0; i<wri;i++) {
2913
VECCOPY(vec, mvert[i].co);
2914
if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, vec); }
2915
for(j=0; j<3; j++) {
2917
gzwrite(gzf, &wrf, sizeof( wrf ));
2921
// should be the same as Vertices.size
2923
gzwrite(gzf, &wri, sizeof(wri));
2924
EulToMat3(ob->rot, rotmat);
2925
for(i=0; i<wri;i++) {
2926
VECCOPY(vec, mvert[i].no);
2928
if(useGlobalCoords) { Mat3MulVecfl(rotmat, vec); }
2929
for(j=0; j<3; j++) {
2931
gzwrite(gzf, &wrf, sizeof( wrf ));
2935
// append only writes verts&norms
2937
//float side1[3],side2[3],norm1[3],norm2[3];
2940
// compute no. of triangles
2942
for(i=0; i<totface; i++) {
2944
if(mface[i].v4) { wri++; }
2946
gzwrite(gzf, &wri, sizeof(wri));
2947
for(i=0; i<totface; i++) {
2950
face[0] = mface[i].v1;
2951
face[1] = mface[i].v2;
2952
face[2] = mface[i].v3;
2953
face[3] = mface[i].v4;
2954
//snprintf(debugStrBuffer,256,"F %s %d = %d,%d,%d,%d \n",ob->id.name, i, face[0],face[1],face[2],face[3] ); elbeemDebugOut(debugStrBuffer);
2955
//VecSubf(side1, mvert[face[1]].co,mvert[face[0]].co);
2956
//VecSubf(side2, mvert[face[2]].co,mvert[face[0]].co);
2957
//Crossf(norm1,side1,side2);
2958
gzwrite(gzf, &(face[0]), sizeof( face[0] ));
2959
gzwrite(gzf, &(face[1]), sizeof( face[1] ));
2960
gzwrite(gzf, &(face[2]), sizeof( face[2] ));
2962
//VecSubf(side1, mvert[face[2]].co,mvert[face[0]].co);
2963
//VecSubf(side2, mvert[face[3]].co,mvert[face[0]].co);
2964
//Crossf(norm2,side1,side2);
2965
//inpf = Inpf(norm1,norm2);
2967
gzwrite(gzf, &(face[0]), sizeof( face[0] ));
2968
gzwrite(gzf, &(face[2]), sizeof( face[2] ));
2969
gzwrite(gzf, &(face[3]), sizeof( face[3] ));
2971
//gzwrite(gzf, &(face[0]), sizeof( face[0] ));
2972
//gzwrite(gzf, &(face[3]), sizeof( face[3] ));
2973
//gzwrite(gzf, &(face[2]), sizeof( face[2] ));
2979
snprintf(debugStrBuffer,256,"Done. #Vertices: %d, #Triangles: %d\n", totvert, totface );
2980
elbeemDebugOut(debugStrBuffer);
2986
void initElbeemMesh(struct Object *ob,
2987
int *numVertices, float **vertices,
2988
int *numTriangles, int **triangles,
2989
int useGlobalCoords)
2991
DerivedMesh *dm = NULL;
2994
int countTris=0, i, totvert, totface;
2998
dm = mesh_create_derived_render(ob, CD_MASK_BAREMESH);
2999
//dm = mesh_create_derived_no_deform(ob,NULL);
3001
mvert = dm->getVertArray(dm);
3002
mface = dm->getFaceArray(dm);
3003
totvert = dm->getNumVerts(dm);
3004
totface = dm->getNumFaces(dm);
3006
*numVertices = totvert;
3007
verts = MEM_callocN( totvert*3*sizeof(float), "elbeemmesh_vertices");
3008
for(i=0; i<totvert; i++) {
3009
VECCOPY( &verts[i*3], mvert[i].co);
3010
if(useGlobalCoords) { Mat4MulVecfl(ob->obmat, &verts[i*3]); }
3014
for(i=0; i<totface; i++) {
3016
if(mface[i].v4) { countTris++; }
3018
*numTriangles = countTris;
3019
tris = MEM_callocN( countTris*3*sizeof(int), "elbeemmesh_triangles");
3021
for(i=0; i<totface; i++) {
3023
face[0] = mface[i].v1;
3024
face[1] = mface[i].v2;
3025
face[2] = mface[i].v3;
3026
face[3] = mface[i].v4;
3028
tris[countTris*3+0] = face[0];
3029
tris[countTris*3+1] = face[1];
3030
tris[countTris*3+2] = face[2];
3033
tris[countTris*3+0] = face[0];
3034
tris[countTris*3+1] = face[2];
3035
tris[countTris*3+2] = face[3];
3044
/* read .bobj.gz file into a fluidsimDerivedMesh struct */
3045
Mesh* readBobjgz(char *filename, Mesh *orgmesh, float* bbstart, float *bbsize) //, fluidsimDerivedMesh *fsdm)
3048
char debugStrBuffer[256];
3051
const int debugBobjRead = 1;
3052
// init data from old mesh (materials,flags)
3053
MFace *origMFace = &((MFace*) orgmesh->mface)[0];
3056
MFace *fsface = NULL;
3060
if(!orgmesh) return NULL;
3061
if(!origMFace) return NULL;
3062
mat_nr = origMFace->mat_nr;
3063
flag = origMFace->flag;
3065
// similar to copy_mesh
3066
newmesh = MEM_dupallocN(orgmesh);
3067
newmesh->mat= orgmesh->mat;
3069
newmesh->mvert= NULL;
3070
newmesh->medge= NULL;
3071
newmesh->mface= NULL;
3072
newmesh->mtface= NULL;
3074
newmesh->dvert = NULL;
3076
newmesh->mcol= NULL;
3077
newmesh->msticky= NULL;
3078
newmesh->texcomesh= NULL;
3079
memset(&newmesh->vdata, 0, sizeof(newmesh->vdata));
3080
memset(&newmesh->edata, 0, sizeof(newmesh->edata));
3081
memset(&newmesh->fdata, 0, sizeof(newmesh->fdata));
3084
newmesh->totface = 0;
3085
newmesh->totvert = 0;
3086
newmesh->totedge = 0;
3087
newmesh->medge = NULL;
3090
snprintf(debugStrBuffer,256,"Reading '%s' GZ_BOBJ... ",filename); elbeemDebugOut(debugStrBuffer);
3091
gzf = gzopen(filename, "rb");
3092
// gzf = fopen(filename, "rb");
3093
// debug: fread(b,c,1,a) = gzread(a,b,c)
3095
//snprintf(debugStrBuffer,256,"readBobjgz::error - Unable to open file for reading '%s'\n", filename); // DEBUG
3100
//if(sizeof(wri)!=4) { snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, Invalid int size %d...\n", wri); return NULL; } // paranoia check
3101
gotBytes = gzread(gzf, &wri, sizeof(wri));
3102
newmesh->totvert = wri;
3103
newmesh->mvert = CustomData_add_layer(&newmesh->vdata, CD_MVERT, CD_CALLOC, NULL, newmesh->totvert);
3104
if(debugBobjRead){ snprintf(debugStrBuffer,256,"#vertices %d ", newmesh->totvert); elbeemDebugOut(debugStrBuffer); } //DEBUG
3105
for(i=0; i<newmesh->totvert;i++) {
3106
//if(debugBobjRead) snprintf(debugStrBuffer,256,"V %d = ",i);
3107
for(j=0; j<3; j++) {
3108
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
3109
newmesh->mvert[i].co[j] = wrf;
3110
//if(debugBobjRead) snprintf(debugStrBuffer,256,"%25.20f ", wrf);
3112
//if(debugBobjRead) snprintf(debugStrBuffer,256,"\n");
3115
// should be the same as Vertices.size
3116
gotBytes = gzread(gzf, &wri, sizeof(wri));
3117
if(wri != newmesh->totvert) {
3118
// complain #vertices has to be equal to #normals, reset&abort
3119
CustomData_free_layer_active(&newmesh->vdata, CD_MVERT, newmesh->totvert);
3121
snprintf(debugStrBuffer,256,"Reading GZ_BOBJ, #normals=%d, #vertices=%d, aborting...\n", wri,newmesh->totvert );
3124
for(i=0; i<newmesh->totvert;i++) {
3125
for(j=0; j<3; j++) {
3126
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
3127
newmesh->mvert[i].no[j] = (short)(wrf*32767.0f);
3128
//newmesh->mvert[i].no[j] = 0.5; // DEBUG tst
3130
//fprintf(stderr," DEBDPCN nm%d, %d = %d,%d,%d \n",
3131
//(int)(newmesh->mvert), i, newmesh->mvert[i].no[0], newmesh->mvert[i].no[1], newmesh->mvert[i].no[2]);
3133
//fprintf(stderr," DPCN 0 = %d,%d,%d \n", newmesh->mvert[0].no[0], newmesh->mvert[0].no[1], newmesh->mvert[0].no[2]);
3136
/* compute no. of triangles */
3137
gotBytes = gzread(gzf, &wri, sizeof(wri));
3138
newmesh->totface = wri;
3139
newmesh->mface = CustomData_add_layer(&newmesh->fdata, CD_MFACE, CD_CALLOC, NULL, newmesh->totface);
3140
if(debugBobjRead){ snprintf(debugStrBuffer,256,"#faces %d ", newmesh->totface); elbeemDebugOut(debugStrBuffer); } //DEBUG
3141
fsface = newmesh->mface;
3142
for(i=0; i<newmesh->totface; i++) {
3145
gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] ));
3146
gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] ));
3147
gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] ));
3150
fsface[i].v1 = face[0];
3151
fsface[i].v2 = face[1];
3152
fsface[i].v3 = face[2];
3153
fsface[i].v4 = face[3];
3156
// correct triangles with v3==0 for blender, cycle verts
3157
for(i=0; i<newmesh->totface; i++) {
3159
int temp = fsface[i].v1;
3160
fsface[i].v1 = fsface[i].v2;
3161
fsface[i].v2 = fsface[i].v3;
3162
fsface[i].v3 = temp;
3167
for(i=0;i<newmesh->totface;i++) {
3168
fsface[i].mat_nr = mat_nr;
3169
fsface[i].flag = flag;
3170
fsface[i].edcode = ME_V1V2 | ME_V2V3 | ME_V3V1;
3171
//snprintf(debugStrBuffer,256,"%d : %d,%d,%d\n", i,fsface[i].mat_nr, fsface[i].flag, fsface[i].edcode );
3174
snprintf(debugStrBuffer,256," (%d,%d) done\n", newmesh->totvert,newmesh->totface); elbeemDebugOut(debugStrBuffer); //DEBUG
3178
/* read zipped fluidsim velocities into the co's of the fluidsimsettings normals struct */
3179
void readVelgz(char *filename, Object *srcob)
3181
char debugStrBuffer[256];
3185
MVert *vverts = srcob->fluidsimSettings->meshSurfNormals;
3186
int len = strlen(filename);
3187
Mesh *mesh = srcob->data;
3188
// mesh and vverts have to be valid from loading...
3190
// clean up in any case
3191
for(i=0; i<mesh->totvert;i++) {
3192
for(j=0; j<3; j++) {
3193
vverts[i].co[j] = 0.;
3196
if(srcob->fluidsimSettings->domainNovecgen>0) return;
3199
//printf("readVelgz Eror: invalid filename '%s'\n",filename); // DEBUG
3203
// .bobj.gz , correct filename
3205
filename[len-6] = 'v';
3206
filename[len-5] = 'e';
3207
filename[len-4] = 'l';
3209
snprintf(debugStrBuffer,256,"Reading '%s' GZ_VEL... ",filename); elbeemDebugOut(debugStrBuffer);
3210
gzf = gzopen(filename, "rb");
3212
//printf("readVelgz Eror: unable to open file '%s'\n",filename); // DEBUG
3216
gzread(gzf, &wri, sizeof( wri ));
3217
if(wri != mesh->totvert) {
3218
//printf("readVelgz Eror: invalid no. of velocities %d vs. %d aborting.\n" ,wri ,mesh->totvert ); // DEBUG
3222
for(i=0; i<mesh->totvert;i++) {
3223
for(j=0; j<3; j++) {
3224
gzread(gzf, &wrf, sizeof( wrf ));
3225
vverts[i].co[j] = wrf;
3227
//if(i<20) fprintf(stderr, "GZ_VELload %d = %f,%f,%f \n",i,vverts[i].co[0],vverts[i].co[1],vverts[i].co[2]); // DEBUG
3234
/* ***************************** fluidsim derived mesh ***************************** */
3236
/* check which file to load, and replace old mesh of the object with it */
3237
/* this replacement is undone at the end of mesh_calc_modifiers */
3238
void loadFluidsimMesh(Object *srcob, int useRenderParams)
3241
float *bbStart = NULL, *bbSize = NULL;
3243
int displaymode = 0;
3244
int curFrame = G.scene->r.cfra - 1 /*G.scene->r.sfra*/; /* start with 0 at start frame */
3245
char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
3246
char debugStrBuffer[256];
3247
//snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d)\n", srcob->id.name, useRenderParams); // debug
3249
if((!srcob)||(!srcob->fluidsimSettings)) {
3250
snprintf(debugStrBuffer,256,"DEBUG - Invalid loadFluidsimMesh call, rp %d, dm %d)\n", useRenderParams, displaymode); // debug
3251
elbeemDebugOut(debugStrBuffer); // debug
3254
// make sure the original mesh data pointer is stored
3255
if(!srcob->fluidsimSettings->orgMesh) {
3256
srcob->fluidsimSettings->orgMesh = srcob->data;
3259
// free old mesh, if there is one (todo, check if it's still valid?)
3260
if(srcob->fluidsimSettings->meshSurface) {
3261
Mesh *freeFsMesh = srcob->fluidsimSettings->meshSurface;
3263
// similar to free_mesh(...) , but no things like unlink...
3264
CustomData_free(&freeFsMesh->vdata, freeFsMesh->totvert);
3265
CustomData_free(&freeFsMesh->edata, freeFsMesh->totedge);
3266
CustomData_free(&freeFsMesh->fdata, freeFsMesh->totface);
3267
MEM_freeN(freeFsMesh);
3269
if(srcob->data == srcob->fluidsimSettings->meshSurface)
3270
srcob->data = srcob->fluidsimSettings->orgMesh;
3271
srcob->fluidsimSettings->meshSurface = NULL;
3273
if(srcob->fluidsimSettings->meshSurfNormals) MEM_freeN(srcob->fluidsimSettings->meshSurfNormals);
3274
srcob->fluidsimSettings->meshSurfNormals = NULL;
3277
// init bounding box
3278
bbStart = srcob->fluidsimSettings->bbStart;
3279
bbSize = srcob->fluidsimSettings->bbSize;
3280
lastBB[0] = bbSize[0]; // TEST
3281
lastBB[1] = bbSize[1];
3282
lastBB[2] = bbSize[2];
3283
fluidsimGetAxisAlignedBB(srcob->fluidsimSettings->orgMesh, srcob->obmat, bbStart, bbSize, &srcob->fluidsimSettings->meshBB);
3284
// check free fsmesh... TODO
3286
if(!useRenderParams) {
3287
displaymode = srcob->fluidsimSettings->guiDisplayMode;
3289
displaymode = srcob->fluidsimSettings->renderDisplayMode;
3292
snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d), curFra=%d, sFra=%d #=%d \n",
3293
srcob->id.name, useRenderParams, displaymode, G.scene->r.cfra, G.scene->r.sfra, curFrame ); // debug
3294
elbeemDebugOut(debugStrBuffer); // debug
3296
strncpy(targetDir, srcob->fluidsimSettings->surfdataPath, FILE_MAXDIR);
3297
// use preview or final mesh?
3298
if(displaymode==1) {
3299
// just display original object
3300
srcob->data = srcob->fluidsimSettings->orgMesh;
3302
} else if(displaymode==2) {
3303
strcat(targetDir,"fluidsurface_preview_####");
3305
strcat(targetDir,"fluidsurface_final_####");
3307
BLI_convertstringcode(targetDir, G.sce);
3308
BLI_convertstringframe(targetDir, curFrame); // fixed #frame-no
3310
strcpy(targetFile,targetDir);
3311
strcat(targetFile, ".bobj.gz");
3313
snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d, dm %d) '%s' \n", srcob->id.name, useRenderParams, displaymode, targetFile); // debug
3314
elbeemDebugOut(debugStrBuffer); // debug
3316
if(displaymode!=2) { // dont add bounding box for final
3317
mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh ,NULL,NULL);
3319
mesh = readBobjgz(targetFile, srcob->fluidsimSettings->orgMesh, bbSize,bbSize );
3322
// switch, abort background rendering when fluidsim mesh is missing
3323
const char *strEnvName2 = "BLENDER_ELBEEMBOBJABORT"; // from blendercall.cpp
3324
if(G.background==1) {
3325
if(getenv(strEnvName2)) {
3326
int elevel = atoi(getenv(strEnvName2));
3328
printf("Env. var %s set, fluid sim mesh '%s' not found, aborting render...\n",strEnvName2, targetFile);
3334
// display org. object upon failure
3335
srcob->data = srcob->fluidsimSettings->orgMesh;
3339
if((mesh)&&(mesh->totvert>0)) {
3340
make_edges(mesh, 0); // 0 = make all edges draw
3342
srcob->fluidsimSettings->meshSurface = mesh;
3344
srcob->fluidsimSettings->meshSurfNormals = MEM_dupallocN(mesh->mvert);
3346
// load vertex velocities, if they exist...
3347
// TODO? use generate flag as loading flag as well?
3348
// warning, needs original .bobj.gz mesh loading filename
3349
if(displaymode==3) {
3350
readVelgz(targetFile, srcob);
3352
// no data for preview, only clear...
3354
for(i=0; i<mesh->totvert;i++) { for(j=0; j<3; j++) { srcob->fluidsimSettings->meshSurfNormals[i].co[j] = 0.; }}
3357
//fprintf(stderr,"LOADFLM DEBXHCH fs=%d 3:%d,%d,%d \n", (int)mesh, ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[0], ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[1], ((Mesh *)(srcob->fluidsimSettings->meshSurface))->mvert[3].no[2]);
3361
/* helper function */
3362
/* init axis aligned BB for mesh object */
3363
void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4],
3364
/*RET*/ float start[3], /*RET*/ float size[3], /*RET*/ struct Mesh **bbmesh )
3366
float bbsx=0.0, bbsy=0.0, bbsz=0.0;
3367
float bbex=1.0, bbey=1.0, bbez=1.0;
3371
VECCOPY(vec, mesh->mvert[0].co);
3372
Mat4MulVecfl(obmat, vec);
3373
bbsx = vec[0]; bbsy = vec[1]; bbsz = vec[2];
3374
bbex = vec[0]; bbey = vec[1]; bbez = vec[2];
3376
for(i=1; i<mesh->totvert;i++) {
3377
VECCOPY(vec, mesh->mvert[i].co);
3378
Mat4MulVecfl(obmat, vec);
3380
if(vec[0] < bbsx){ bbsx= vec[0]; }
3381
if(vec[1] < bbsy){ bbsy= vec[1]; }
3382
if(vec[2] < bbsz){ bbsz= vec[2]; }
3383
if(vec[0] > bbex){ bbex= vec[0]; }
3384
if(vec[1] > bbey){ bbey= vec[1]; }
3385
if(vec[2] > bbez){ bbez= vec[2]; }
3395
size[0] = bbex-bbsx;
3396
size[1] = bbey-bbsy;
3397
size[2] = bbez-bbsz;
3400
// init bounding box mesh?
3403
Mesh *newmesh = NULL;
3404
if(!(*bbmesh)) { newmesh = MEM_callocN(sizeof(Mesh), "fluidsimGetAxisAlignedBB_meshbb"); }
3405
else { newmesh = *bbmesh; }
3407
newmesh->totvert = 8;
3409
newmesh->mvert = CustomData_add_layer(&newmesh->vdata, CD_MVERT, CD_CALLOC, NULL, newmesh->totvert);
3410
for(i=0; i<8; i++) {
3411
for(j=0; j<3; j++) newmesh->mvert[i].co[j] = start[j];
3414
newmesh->totface = 6;
3416
newmesh->mface = CustomData_add_layer(&newmesh->fdata, CD_MFACE, CD_CALLOC, NULL, newmesh->totface);
3422
#else // DISABLE_ELBEEM
3424
/* dummy for mesh_calc_modifiers */
3425
void loadFluidsimMesh(Object *srcob, int useRenderParams) {
3428
#endif // DISABLE_ELBEEM
3095
/* ******************* GLSL ******************** */
3097
void DM_add_tangent_layer(DerivedMesh *dm)
3100
MTFace *mtface, *tf;
3102
MVert *mvert, *v1, *v2, *v3, *v4;
3103
MemArena *arena= NULL;
3104
VertexTangent **vtangents= NULL;
3105
float (*orco)[3]= NULL, (*tangent)[3];
3106
float *uv1, *uv2, *uv3, *uv4, *vtang;
3107
float fno[3], tang[3], uv[4][2];
3108
int i, j, len, mf_vi[4], totvert, totface;
3110
if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) != -1)
3113
/* check we have all the needed layers */
3114
totvert= dm->getNumVerts(dm);
3115
totface= dm->getNumFaces(dm);
3117
mvert= dm->getVertArray(dm);
3118
mface= dm->getFaceArray(dm);
3119
mtface= dm->getFaceDataArray(dm, CD_MTFACE);
3122
orco= dm->getVertDataArray(dm, CD_ORCO);
3127
/* create tangent layer */
3128
DM_add_face_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
3129
tangent= DM_get_face_data_layer(dm, CD_TANGENT);
3131
/* allocate some space */
3132
arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE);
3133
BLI_memarena_use_calloc(arena);
3134
vtangents= MEM_callocN(sizeof(VertexTangent*)*totvert, "VertexTangent");
3136
/* sum tangents at connected vertices */
3137
for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++) {
3144
CalcNormFloat4(v4->co, v3->co, v2->co, v1->co, fno);
3148
CalcNormFloat(v3->co, v2->co, v1->co, fno);
3158
uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
3159
spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]);
3160
spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]);
3161
spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]);
3163
spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]);
3166
tangent_from_uv(uv1, uv2, uv3, v1->co, v2->co, v3->co, fno, tang);
3167
sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
3168
sum_or_add_vertex_tangent(arena, &vtangents[mf->v2], tang, uv2);
3169
sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
3174
tangent_from_uv(uv1, uv3, uv4, v1->co, v3->co, v4->co, fno, tang);
3175
sum_or_add_vertex_tangent(arena, &vtangents[mf->v1], tang, uv1);
3176
sum_or_add_vertex_tangent(arena, &vtangents[mf->v3], tang, uv3);
3177
sum_or_add_vertex_tangent(arena, &vtangents[mf->v4], tang, uv4);
3181
/* write tangent to layer */
3182
for(i=0, tf=mtface, mf=mface; i < totface; mf++, tf++, i++, tangent+=4) {
3183
len= (mf->v4)? 4 : 3;
3192
uv1= uv[0]; uv2= uv[1]; uv3= uv[2]; uv4= uv[3];
3193
spheremap(orco[mf->v1][0], orco[mf->v1][1], orco[mf->v1][2], &uv[0][0], &uv[0][1]);
3194
spheremap(orco[mf->v2][0], orco[mf->v2][1], orco[mf->v2][2], &uv[1][0], &uv[1][1]);
3195
spheremap(orco[mf->v3][0], orco[mf->v3][1], orco[mf->v3][2], &uv[2][0], &uv[2][1]);
3197
spheremap(orco[mf->v4][0], orco[mf->v4][1], orco[mf->v4][2], &uv[3][0], &uv[3][1]);
3205
for(j=0; j<len; j++) {
3206
vtang= find_vertex_tangent(vtangents[mf_vi[j]], mtface ? tf->uv[j] : uv[j]);
3208
VECCOPY(tangent[j], vtang);
3209
Normalize(tangent[j]);
3213
BLI_memarena_free(arena);
3214
MEM_freeN(vtangents);
3217
void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs)
3219
CustomData *vdata, *fdata, *tfdata = NULL;
3222
/* From the layers requested by the GLSL shader, figure out which ones are
3223
* actually available for this derivedmesh, and retrieve the pointers */
3225
memset(attribs, 0, sizeof(DMVertexAttribs));
3227
vdata = &dm->vertData;
3228
fdata = &dm->faceData;
3230
/* ugly hack, editmesh derivedmesh doesn't copy face data, this way we
3231
* can use offsets instead */
3232
if(dm->release == emDM_release)
3233
tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata;
3237
/* add a tangent layer if necessary */
3238
for(b = 0; b < gattribs->totlayer; b++)
3239
if(gattribs->layer[b].type == CD_TANGENT)
3240
if(CustomData_get_layer_index(fdata, CD_TANGENT) == -1)
3241
DM_add_tangent_layer(dm);
3243
for(b = 0; b < gattribs->totlayer; b++) {
3244
if(gattribs->layer[b].type == CD_MTFACE) {
3245
/* uv coordinates */
3246
if(gattribs->layer[b].name[0])
3247
layer = CustomData_get_named_layer_index(tfdata, CD_MTFACE,
3248
gattribs->layer[b].name);
3250
layer = CustomData_get_active_layer_index(tfdata, CD_MTFACE);
3253
a = attribs->tottface++;
3255
attribs->tface[a].array = tfdata->layers[layer].data;
3256
attribs->tface[a].emOffset = tfdata->layers[layer].offset;
3257
attribs->tface[a].glIndex = gattribs->layer[b].glindex;
3260
else if(gattribs->layer[b].type == CD_MCOL) {
3262
if(gattribs->layer[b].name[0])
3263
layer = CustomData_get_named_layer_index(tfdata, CD_MCOL,
3264
gattribs->layer[b].name);
3266
layer = CustomData_get_active_layer_index(tfdata, CD_MCOL);
3269
a = attribs->totmcol++;
3271
attribs->mcol[a].array = tfdata->layers[layer].data;
3272
attribs->mcol[a].emOffset = tfdata->layers[layer].offset;
3273
attribs->mcol[a].glIndex = gattribs->layer[b].glindex;
3276
else if(gattribs->layer[b].type == CD_TANGENT) {
3278
layer = CustomData_get_layer_index(fdata, CD_TANGENT);
3281
attribs->tottang = 1;
3283
attribs->tang.array = fdata->layers[layer].data;
3284
attribs->tang.emOffset = fdata->layers[layer].offset;
3285
attribs->tang.glIndex = gattribs->layer[b].glindex;
3288
else if(gattribs->layer[b].type == CD_ORCO) {
3289
/* original coordinates */
3290
layer = CustomData_get_layer_index(vdata, CD_ORCO);
3293
attribs->totorco = 1;
3295
attribs->orco.array = vdata->layers[layer].data;
3296
attribs->orco.emOffset = vdata->layers[layer].offset;
3297
attribs->orco.glIndex = gattribs->layer[b].glindex;