/* * Functions for adding, removing, and looking up a file in the list */ static int addToOpenedList(ImodImageFile *iiFile) { if (!sOpenedFiles) sOpenedFiles = ilistNew(sizeof(ImodImageFile *), 4); if (sOpenedFiles && !ilistAppend(sOpenedFiles, &iiFile)) return 0; b3dError(stderr, "ERROR: iiOpen - Memory error adding new file to master list\n"); return 1; }
/*! Returns a duplicate of [list], or NULL for an error */ Ilist *ilistDup(Ilist *list) { void *dsave; Ilist *newList; if (!list) return(NULL); /* First get a new list, then copy the structure, saving the data pointer */ newList = ilistNew(list->dsize, list->store); if (!newList) return(NULL); dsave = newList->data; memcpy(newList, list, sizeof(Ilist)); newList->data = dsave; if (list->size) memcpy(newList->data, list->data, list->dsize * list->size); return(newList); }
/* Initialize check list: if it does not exist, allocate it and place TIFF and MRC functions on the list */ static int initCheckList() { IIFileCheckFunction func; if (sCheckList) return 0; sCheckList = ilistNew(sizeof(IIFileCheckFunction), 6); if (!sCheckList) return 1; func = iiTIFFCheck; ilistAppend(sCheckList, &func); func = iiMRCCheck; ilistAppend(sCheckList, &func); func = iiLikeMRCCheck; ilistAppend(sCheckList, &func); func = iiHDFCheck; ilistAppend(sCheckList, &func); /* Turn off tiff unknown tag warnings: no effect if caller suppressed all warnings */ tiffFilterWarnings(); return 0; }
/* * Reads a defocus file whose name is in fnDefocus and stores the values * in an Ilist of SavedDefocus structures, eliminating duplications if any. * The return value is the Ilist, which may be empty if the file does not * exist. */ Ilist *readDefocusFile(const char *fnDefocus, int &defVersion) { FILE *fp; SavedDefocus saved; char line[MAX_LINE]; int nchar, versTmp; float langtmp, hangtmp, defoctmp; Ilist *lstSaved = ilistNew(sizeof(SavedDefocus), 10); if (!lstSaved) exitError("Allocating list for angles and defocuses"); fp = fopen(fnDefocus, "r"); defVersion = 0; versTmp = 0; if (fp) { while (1) { nchar = fgetline(fp, line, MAX_LINE); if (nchar == -2) break; if (nchar == -1) exitError("Error reading defocus file %s", fnDefocus); if (nchar) { sscanf(line, "%d %d %f %f %f %d", &saved.startingSlice, &saved.endingSlice , &langtmp, &hangtmp, &defoctmp, &versTmp); if (!ilistSize(lstSaved)) defVersion = versTmp; saved.lAngle = langtmp; saved.hAngle = hangtmp; saved.defocus = defoctmp / 1000.; saved.startingSlice--; saved.endingSlice--; addItemToDefocusList(lstSaved, saved); } if (nchar < 0) break; } fclose(fp); } return lstSaved; }
// Add an item to the selection list void imodSelectionListAdd(ImodView *vi, Iindex newIndex) { int multiObject = 1; // Placekeeper for possible argument/preference Iindex *index; int i; // Clear list if a different object is given and multiobject not allowed if (ilistSize(vi->selectionList) && !multiObject) { index = (Iindex *)ilistFirst(vi->selectionList); if (index->object != newIndex.object) imodSelectionListClear(vi); } // create list if it does not exist if (!vi->selectionList) { vi->selectionList = ilistNew(sizeof(Iindex), 4); if (!vi->selectionList) return; // ERROR } // Look through list to see if contour is already there and update point for (i = 0; i < ilistSize(vi->selectionList); i++) { index = (Iindex *)ilistItem(vi->selectionList, i); if (index->object == newIndex.object && index->contour == newIndex.contour) { index->point = newIndex.point; imodTrace('S', "update %d %d %d", newIndex.object, newIndex.contour, newIndex.point); return; } } // Add index to list imodTrace('S', "adding %d %d %d", newIndex.object, newIndex.contour, newIndex.point); ilistAppend(vi->selectionList, &newIndex); dumpSelectionList(vi); }
/* * Analyze a mesh and pack it into VBOs if it qualifies */ int VertBufManager::analyzeMesh(Imesh *mesh, float zscale, int fillType, int useFillColor, DrawProps *defProps) { bool valid = true; RGBTmap colors; pair<RGBTmap::iterator,bool> mapret; RGBTmap::iterator mapit; VertBufData *vbd = mesh->vertBuf; RGBTindices rInd; Istore *stp; Istore store; int *mlist = mesh->list; DrawProps curProps; int i, j, cumInd, defInd, nextItemIndex, stateFlags, vertDflt, changeFlags, firstDflt; b3dUInt32 vertRGBT, firstRGBT; int remInd, curSave, curNext; int numDefaultTri = 0, numMixedTri = 0; int handleFlags, nonVboFlags = 0; if (fillType) handleFlags = (useFillColor ? CHANGED_FCOLOR : CHANGED_COLOR) | CHANGED_TRANS; else { handleFlags = CHANGED_COLOR | CHANGED_TRANS; nonVboFlags = CHANGED_3DWIDTH; } rInd.numFanInds = 0; // Check if there is a current VBO and it is all still valid packRGBT(defProps, useFillColor, firstRGBT); if (vbd && vbd->vbObj && fillType == vbd->fillType && (!ilistSize(mesh->store) || (vbd->useFillColor == useFillColor && vbd->defaultRGBT == firstRGBT)) && vbd->checksum == istoreChecksum(mesh->store)) { // If Z-scale still valid, return a -1; if have to fix the Z-scale, do it, return -2 if (fabs((double)(zscale - vbd->zscale)) < 1.e-4) return -1; b3dBindBuffer(GL_ARRAY_BUFFER, vbd->vbObj); if (loadVertexNormalArray(mesh, zscale, fillType)) { vbCleanupVBD(mesh); return 1; } vbd->zscale = zscale; return -2; } // Now proceed to full analysis nextItemIndex = istoreFirstChangeIndex(mesh->store); for (i = 0; i < mesh->lsize && valid; i++) { switch (mlist[i]) { case IMOD_MESH_BGNTRI: case IMOD_MESH_ENDTRI: case IMOD_MESH_BGNPOLY: case IMOD_MESH_NORMAL: case IMOD_MESH_BGNBIGPOLY: case IMOD_MESH_SWAP: valid = false; break; case IMOD_MESH_BGNPOLYNORM: i++; while (mlist[i] != IMOD_MESH_ENDPOLY && valid) { valid = (mlist[i] == mlist[i+1] + 1) && (mlist[i+2] == mlist[i+3] + 1) && (mlist[i+4] == mlist[i+5] + 1); i += 6; numDefaultTri++; } break; case IMOD_MESH_BGNPOLYNORM2: i++; while (mlist[i] != IMOD_MESH_ENDPOLY) { if (nextItemIndex < i || nextItemIndex > i + 2) { // Count a default triangle if no changes in this range numDefaultTri++; i += 3; } else { // Otherwise look at each vertex and get its properties if it is changed for (j = 0; j < 3; j++) { vertDflt = 1; if (i == nextItemIndex) { curProps = *defProps; stateFlags = 0; nextItemIndex = istoreNextChange(mesh->store, defProps, &curProps, &stateFlags, &changeFlags); if (stateFlags & handleFlags) { vertDflt = 0; packRGBT(&curProps, useFillColor, vertRGBT); } // Take triangle as mixed if it has unhandleable flags if (stateFlags & nonVboFlags) { firstDflt = -1; i++; continue; } } // For first vertex record the triangle properties, for later one record if // there is a mismatch from the first if (!j) { firstDflt = vertDflt; firstRGBT = vertRGBT; } else if (vertDflt != firstDflt || (!vertDflt && vertRGBT != firstRGBT)) { firstDflt = -1; } i++; } // Count whether it is a default or mixed triangle if (firstDflt < 0) { numMixedTri++; } else if (firstDflt > 0) { numDefaultTri++; } else { // For a special triangle, add to list of RGBT values with a count of 1 if it // is not on the list; if it is already on the list increment its count; rInd.firstElement = i; rInd.numInds = 1; mapret = colors.insert(pair<b3dUInt32,RGBTindices>(firstRGBT, rInd)); if (mapret.second == false) mapret.first->second.numInds++; } } } break; case IMOD_MESH_END: break; } } if (!valid) { vbCleanupVBD(mesh); return 3; } if (!colors.size() && !numDefaultTri) { vbCleanupVBD(mesh); return 2; } vbd = allocateVBDIfNeeded(&mesh->vertBuf); if (!vbd) return 1; // Now allocate whatever pieces are needed in there. Set remnant value in vbd first // Add up the special set sizes and re-initialize the counts to be starting indexes cumInd = numDefaultTri * 3; vbd->numRemnant = 0; if (numMixedTri) vbd->numRemnant = numMixedTri * 3 + 3; i = -1; if (allocateSpecialSets(vbd, colors.size(), cumInd, 0) || processMap(vbd, &colors, cumInd, 3, i)) { vbCleanupVBD(mesh); return 1; } imodTrace('b',"dfltInd %d spec sets %d cumind %d remnant %d", vbd->numIndDefault, vbd->numSpecialSets, cumInd, numMixedTri); // Create the store for remnants if (numMixedTri) { ilistDelete(vbd->remnantStore); vbd->remnantStore = ilistNew(sizeof(Istore), vbd->numRemnant / 8); if (!vbd->remnantStore) { vbCleanupVBD(mesh); return 1; } vbd->remnantStore->quantum = B3DMAX(vbd->remnantStore->quantum, vbd->numRemnant / 8); vbd->remnantIndList[0] = IMOD_MESH_BGNPOLYNORM2; } // Now get the vertex buffers themselves if (genAndBindBuffers(vbd, mesh->vsize, cumInd)) { vbCleanupVBD(mesh); return 1; } imodTrace('b',"vbObj %d ebObj %d", vbd->vbObj, vbd->ebObj); // Load the vertices and finish with buffer for now if (loadVertexNormalArray(mesh, zscale, fillType)) { vbCleanupVBD(mesh); return 1; } b3dBindBuffer(GL_ARRAY_BUFFER, 0); // Set the identifiers of this vb data vbd->zscale = zscale; vbd->fillType = fillType; vbd->useFillColor = useFillColor; packRGBT(defProps, useFillColor, vbd->defaultRGBT); vbd->checksum = istoreChecksum(mesh->store); // Get or use temporary array for indexes if (allocateTempInds(cumInd)) { vbCleanupVBD(mesh); return 1; } // No fine grain: copy all the indices into index array defInd = 0; if (!mesh->store) { i = 0; while (mlist[i] != IMOD_MESH_END) { if (mlist[i] == IMOD_MESH_BGNPOLYNORM) { i++; while (mlist[i] != IMOD_MESH_ENDPOLY) { i++; mInds[defInd++] = mlist[i++] / 2; } } else if (mlist[i] == IMOD_MESH_BGNPOLYNORM2) { i++; while (mlist[i] != IMOD_MESH_ENDPOLY) { mInds[defInd++] = mlist[i++] / 2; } } i++; } } else { // Otherwise process all triangles into index array or remnant arrays nextItemIndex = istoreFirstChangeIndex(mesh->store); remInd = 1; for (i = 0; i < mesh->lsize; i++) { switch (mlist[i]) { case IMOD_MESH_BGNPOLYNORM2: i++; while (mlist[i] != IMOD_MESH_ENDPOLY) { // Repeat the analysis to determine default, special, or mixed triangle curSave = mesh->store->current; if (nextItemIndex < i || nextItemIndex > i + 2) { firstDflt = 1; } else { // Otherwise look at each vertex and get its properties if it is changed for (j = 0; j < 3; j++) { vertDflt = 1; if (i + j == nextItemIndex) { curProps = *defProps; stateFlags = 0; nextItemIndex = istoreNextChange(mesh->store, defProps, &curProps, &stateFlags, &changeFlags); if (stateFlags & handleFlags) { vertDflt = 0; packRGBT(&curProps, useFillColor, vertRGBT); } if (stateFlags & nonVboFlags) { firstDflt = -1; continue; } } // For first vertex record the triangle properties, for later one stop if // there is a mismatch from the first if (!j) { firstDflt = vertDflt; firstRGBT = vertRGBT; } else if (vertDflt != firstDflt || (!vertDflt && vertRGBT != firstRGBT)) { firstDflt = -1; } } } // Save indexes for default or special triangles if (firstDflt > 0) { mInds[defInd++] = mlist[i++] / 2; mInds[defInd++] = mlist[i++] / 2; mInds[defInd++] = mlist[i++] / 2; } else if (firstDflt == 0) { mapit = colors.find(firstRGBT); mInds[mapit->second.numInds++] = mlist[i++] / 2; mInds[mapit->second.numInds++] = mlist[i++] / 2; mInds[mapit->second.numInds++] = mlist[i++] / 2; } else { // For mixed triangle, save the current pointer, copy the index for each // vertex to the remnant index array, and copy all stores for that vertex // to the remnant store, changing the index to the new value curNext = mesh->store->current; for (j = 0; j < 3; j++) { vbd->remnantIndList[remInd] = mlist[i]; while (curSave < curNext) { stp = istoreItem(mesh->store, curSave); if (stp->index.i == i) { store = *stp; store.index.i = remInd; if (istoreInsert(&vbd->remnantStore, &store)) { vbCleanupVBD(mesh); return 1; } curSave++; } else break; } i++; remInd++; } mesh->store->current = curNext; } } break; case IMOD_MESH_END: break; } } } if (vbd->numRemnant) { vbd->remnantIndList[remInd++] = IMOD_MESH_ENDPOLY; vbd->remnantIndList[remInd++] = IMOD_MESH_END; } b3dBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, cumInd * sizeof(GLuint), mInds); b3dBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); return 0; }