| File: | src/limn/obj.c |
| Location: | line 218, column 23 |
| Description: | Access to field 'vertIdxArr' results in a dereference of a null pointer (loaded from variable 'part') |
| 1 | /* | |||
| 2 | Teem: Tools to process and visualize scientific data and images . | |||
| 3 | Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago | |||
| 4 | Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann | |||
| 5 | Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah | |||
| 6 | ||||
| 7 | This library is free software; you can redistribute it and/or | |||
| 8 | modify it under the terms of the GNU Lesser General Public License | |||
| 9 | (LGPL) as published by the Free Software Foundation; either | |||
| 10 | version 2.1 of the License, or (at your option) any later version. | |||
| 11 | The terms of redistributing and/or modifying this software also | |||
| 12 | include exceptions to the LGPL that facilitate static linking. | |||
| 13 | ||||
| 14 | This library is distributed in the hope that it will be useful, | |||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| 17 | Lesser General Public License for more details. | |||
| 18 | ||||
| 19 | You should have received a copy of the GNU Lesser General Public License | |||
| 20 | along with this library; if not, write to Free Software Foundation, Inc., | |||
| 21 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| 22 | */ | |||
| 23 | ||||
| 24 | ||||
| 25 | #include "limn.h" | |||
| 26 | ||||
| 27 | /* restricted to this file now since here is the only place its needed */ | |||
| 28 | typedef union { | |||
| 29 | limnVertex **vert; | |||
| 30 | limnEdge **edge; | |||
| 31 | limnFace **face; | |||
| 32 | limnLook **look; | |||
| 33 | limnPart ***partp; | |||
| 34 | void **v; | |||
| 35 | } limnPtrPtrUnion; | |||
| 36 | ||||
| 37 | int | |||
| 38 | limnObjectLookAdd(limnObject *obj) { | |||
| 39 | int lookIdx; | |||
| 40 | limnLook *look; | |||
| 41 | ||||
| 42 | lookIdx = airArrayLenIncr(obj->lookArr, 1); | |||
| 43 | look = &(obj->look[lookIdx]); | |||
| 44 | ELL_4V_SET(look->rgba, 1, 1, 1, 1)((look->rgba)[0] = (1), (look->rgba)[1] = (1), (look-> rgba)[2] = (1), (look->rgba)[3] = (1)); | |||
| 45 | ELL_3V_SET(look->kads, 0.0, 1.0, 0.0)((look->kads)[0] = (0.0), (look->kads)[1] = (1.0), (look ->kads)[2] = (0.0)); | |||
| 46 | look->spow = 50; | |||
| 47 | return lookIdx; | |||
| 48 | } | |||
| 49 | ||||
| 50 | ||||
| 51 | limnObject * | |||
| 52 | limnObjectNew(int incr, int doEdges) { | |||
| 53 | limnObject *obj; | |||
| 54 | limnPtrPtrUnion lppu; | |||
| 55 | ||||
| 56 | obj = AIR_CALLOC(1, limnObject)(limnObject*)(calloc((1), sizeof(limnObject))); | |||
| 57 | obj->vert = NULL((void*)0); | |||
| 58 | obj->edge = NULL((void*)0); | |||
| 59 | obj->face = NULL((void*)0); | |||
| 60 | obj->faceSort = NULL((void*)0); | |||
| 61 | obj->part = NULL((void*)0); | |||
| 62 | obj->partPool = NULL((void*)0); | |||
| 63 | obj->look = NULL((void*)0); | |||
| 64 | ||||
| 65 | /* create all various airArrays */ | |||
| 66 | obj->vertArr = airArrayNew((lppu.vert = &(obj->vert), lppu.v), | |||
| 67 | &(obj->vertNum), | |||
| 68 | sizeof(limnVertex), incr); | |||
| 69 | obj->edgeArr = airArrayNew((lppu.edge = &(obj->edge), lppu.v), | |||
| 70 | &(obj->edgeNum), | |||
| 71 | sizeof(limnEdge), incr); | |||
| 72 | obj->faceArr = airArrayNew((lppu.face = &(obj->face), lppu.v), | |||
| 73 | &(obj->faceNum), | |||
| 74 | sizeof(limnFace), incr); | |||
| 75 | obj->partArr = airArrayNew((lppu.partp = &(obj->part), lppu.v), | |||
| 76 | &(obj->partNum), | |||
| 77 | sizeof(limnPart*), incr); | |||
| 78 | obj->partPoolArr = airArrayNew((lppu.partp = &(obj->partPool), lppu.v), | |||
| 79 | &(obj->partPoolNum), | |||
| 80 | sizeof(limnPart*), incr); | |||
| 81 | obj->lookArr = airArrayNew((lppu.look = &(obj->look), lppu.v), | |||
| 82 | &(obj->lookNum), | |||
| 83 | sizeof(limnLook), incr); | |||
| 84 | ||||
| 85 | /* create (default) look 0 */ | |||
| 86 | limnObjectLookAdd(obj); | |||
| 87 | ||||
| 88 | obj->vertSpace = limnSpaceUnknown; | |||
| 89 | obj->setVertexRGBAFromLook = AIR_FALSE0; | |||
| 90 | obj->doEdges = doEdges; | |||
| 91 | obj->incr = incr; | |||
| 92 | ||||
| 93 | return obj; | |||
| 94 | } | |||
| 95 | ||||
| 96 | limnPart * | |||
| 97 | _limnObjectPartNew(int incr) { | |||
| 98 | limnPart *part; | |||
| 99 | airPtrPtrUnion appu; | |||
| 100 | ||||
| 101 | part = AIR_CALLOC(1, limnPart)(limnPart*)(calloc((1), sizeof(limnPart))); | |||
| 102 | if (part) { | |||
| 103 | part->vertIdx = NULL((void*)0); | |||
| 104 | part->edgeIdx = NULL((void*)0); | |||
| 105 | part->faceIdx = NULL((void*)0); | |||
| 106 | part->vertIdxArr = airArrayNew((appu.ui = &(part->vertIdx), appu.v), | |||
| 107 | &(part->vertIdxNum), | |||
| 108 | sizeof(int), incr); | |||
| 109 | part->edgeIdxArr = airArrayNew((appu.ui = &(part->edgeIdx), appu.v), | |||
| 110 | &(part->edgeIdxNum), | |||
| 111 | sizeof(int), incr); | |||
| 112 | part->faceIdxArr = airArrayNew((appu.ui = &(part->faceIdx), appu.v), | |||
| 113 | &(part->faceIdxNum), | |||
| 114 | sizeof(int), incr); | |||
| 115 | } | |||
| 116 | return part; | |||
| 117 | } | |||
| 118 | ||||
| 119 | limnPart * | |||
| 120 | _limnObjectPartNix(limnPart *part) { | |||
| 121 | ||||
| 122 | if (part) { | |||
| 123 | airArrayNuke(part->vertIdxArr); | |||
| 124 | airArrayNuke(part->edgeIdxArr); | |||
| 125 | airArrayNuke(part->faceIdxArr); | |||
| 126 | airFree(part); | |||
| 127 | } | |||
| 128 | return NULL((void*)0); | |||
| 129 | } | |||
| 130 | ||||
| 131 | void | |||
| 132 | _limnObjectFaceEmpty(limnFace *face) { | |||
| 133 | ||||
| 134 | if (face) { | |||
| 135 | airFree(face->vertIdx); | |||
| 136 | airFree(face->edgeIdx); | |||
| 137 | } | |||
| 138 | return; | |||
| 139 | } | |||
| 140 | ||||
| 141 | limnObject * | |||
| 142 | limnObjectNix(limnObject *obj) { | |||
| 143 | unsigned int partIdx, faceIdx; | |||
| 144 | ||||
| 145 | if (obj) { | |||
| 146 | for (partIdx=0; partIdx<obj->partNum; partIdx++) { | |||
| 147 | _limnObjectPartNix(obj->part[partIdx]); | |||
| 148 | } | |||
| 149 | airArrayNuke(obj->partArr); | |||
| 150 | for (partIdx=0; partIdx<obj->partPoolNum; partIdx++) { | |||
| 151 | _limnObjectPartNix(obj->partPool[partIdx]); | |||
| 152 | } | |||
| 153 | airArrayNuke(obj->partPoolArr); | |||
| 154 | for (faceIdx=0; faceIdx<obj->faceNum; faceIdx++) { | |||
| 155 | _limnObjectFaceEmpty(obj->face + faceIdx); | |||
| 156 | } | |||
| 157 | airArrayNuke(obj->faceArr); | |||
| 158 | airArrayNuke(obj->vertArr); | |||
| 159 | airArrayNuke(obj->edgeArr); | |||
| 160 | airFree(obj->faceSort); | |||
| 161 | airArrayNuke(obj->lookArr); | |||
| 162 | airFree(obj); | |||
| 163 | } | |||
| 164 | return NULL((void*)0); | |||
| 165 | } | |||
| 166 | ||||
| 167 | void | |||
| 168 | limnObjectEmpty(limnObject *obj) { | |||
| 169 | unsigned int partIdx, faceIdx; | |||
| 170 | ||||
| 171 | for (partIdx=0; partIdx<obj->partNum; partIdx++) { | |||
| 172 | _limnObjectPartNix(obj->part[partIdx]); | |||
| 173 | } | |||
| 174 | airArrayLenSet(obj->partArr, 0); | |||
| 175 | for (partIdx=0; partIdx<obj->partPoolNum; partIdx++) { | |||
| 176 | _limnObjectPartNix(obj->partPool[partIdx]); | |||
| 177 | } | |||
| 178 | airArrayLenSet(obj->partPoolArr, 0); | |||
| 179 | for (faceIdx=0; faceIdx<obj->faceNum; faceIdx++) { | |||
| 180 | _limnObjectFaceEmpty(obj->face + faceIdx); | |||
| 181 | } | |||
| 182 | airArrayLenSet(obj->faceArr, 0); | |||
| 183 | airArrayLenSet(obj->vertArr, 0); | |||
| 184 | airArrayLenSet(obj->edgeArr, 0); | |||
| 185 | airFree(obj->faceSort); | |||
| 186 | /* leaves (default) look 0 */ | |||
| 187 | airArrayLenSet(obj->lookArr, 1); | |||
| 188 | ||||
| 189 | /* don't touch state flags */ | |||
| 190 | ||||
| 191 | return; | |||
| 192 | } | |||
| 193 | ||||
| 194 | /* | |||
| 195 | ******** limnObjectPreSet | |||
| 196 | ** | |||
| 197 | ** an attempt at pre-allocating everything that will be needed in a | |||
| 198 | ** limnObject, so that there will be no calloc/memcpy overhead associated | |||
| 199 | ** with growing any of the airArrays inside | |||
| 200 | */ | |||
| 201 | int | |||
| 202 | limnObjectPreSet(limnObject *obj, unsigned int partNum, | |||
| 203 | unsigned int lookNum, unsigned int vertPerPart, | |||
| 204 | unsigned int edgePerPart, unsigned int facePerPart) { | |||
| 205 | limnPart *part; | |||
| 206 | unsigned int partIdx; | |||
| 207 | ||||
| 208 | limnObjectEmpty(obj); | |||
| 209 | airArrayLenPreSet(obj->vertArr, partNum*vertPerPart); | |||
| 210 | airArrayLenPreSet(obj->edgeArr, partNum*edgePerPart); | |||
| 211 | airArrayLenPreSet(obj->faceArr, partNum*facePerPart); | |||
| 212 | airArrayLenPreSet(obj->lookArr, lookNum); | |||
| 213 | airArrayLenPreSet(obj->partArr, partNum); | |||
| 214 | ||||
| 215 | airArrayLenSet(obj->partPoolArr, partNum); | |||
| 216 | for (partIdx=0; partIdx<partNum; partIdx++) { | |||
| ||||
| 217 | part = obj->partPool[partIdx] = _limnObjectPartNew(obj->incr); | |||
| 218 | airArrayLenPreSet(part->vertIdxArr, vertPerPart); | |||
| ||||
| 219 | airArrayLenPreSet(part->edgeIdxArr, edgePerPart); | |||
| 220 | airArrayLenPreSet(part->faceIdxArr, facePerPart); | |||
| 221 | } | |||
| 222 | ||||
| 223 | return 0; | |||
| 224 | } | |||
| 225 | ||||
| 226 | int | |||
| 227 | limnObjectPartAdd(limnObject *obj) { | |||
| 228 | unsigned int partIdx; | |||
| 229 | limnPart *part; | |||
| 230 | ||||
| 231 | partIdx = airArrayLenIncr(obj->partArr, 1); | |||
| 232 | if (obj->partPoolNum > 0) { | |||
| 233 | part = obj->part[partIdx] = obj->partPool[obj->partPoolNum - 1]; | |||
| 234 | airArrayLenIncr(obj->partPoolArr, -1); | |||
| 235 | airArrayLenSet(part->vertIdxArr, 0); | |||
| 236 | airArrayLenSet(part->edgeIdxArr, 0); | |||
| 237 | airArrayLenSet(part->faceIdxArr, 0); | |||
| 238 | } else { | |||
| 239 | /* there are no available parts in the pool */ | |||
| 240 | part = obj->part[partIdx] = _limnObjectPartNew(obj->incr); | |||
| 241 | } | |||
| 242 | part->lookIdx = 0; | |||
| 243 | part->depth = AIR_NAN(airFloatQNaN.f); | |||
| 244 | return partIdx; | |||
| 245 | } | |||
| 246 | ||||
| 247 | int | |||
| 248 | limnObjectVertexNumPreSet(limnObject *obj, unsigned int partIdx, | |||
| 249 | unsigned int vertNum) { | |||
| 250 | limnPart *part; | |||
| 251 | ||||
| 252 | part = obj->part[partIdx]; | |||
| 253 | airArrayLenPreSet(obj->vertArr, vertNum); | |||
| 254 | airArrayLenPreSet(part->vertIdxArr, vertNum); | |||
| 255 | return 0; | |||
| 256 | } | |||
| 257 | ||||
| 258 | int | |||
| 259 | limnObjectVertexAdd(limnObject *obj, unsigned int partIdx, | |||
| 260 | float x, float y, float z) { | |||
| 261 | limnPart *part; | |||
| 262 | limnVertex *vert; | |||
| 263 | int vertIdx, vertIdxIdx; | |||
| 264 | ||||
| 265 | part = obj->part[partIdx]; | |||
| 266 | vertIdx = airArrayLenIncr(obj->vertArr, 1); | |||
| 267 | vert = obj->vert + vertIdx; | |||
| 268 | vertIdxIdx = airArrayLenIncr(part->vertIdxArr, 1); | |||
| 269 | part->vertIdx[vertIdxIdx] = vertIdx; | |||
| 270 | ELL_4V_SET(vert->world, x, y, z, 1)((vert->world)[0] = (x), (vert->world)[1] = (y), (vert-> world)[2] = (z), (vert->world)[3] = (1)); | |||
| 271 | ELL_4V_SET(vert->coord, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN)((vert->coord)[0] = ((airFloatQNaN.f)), (vert->coord)[1 ] = ((airFloatQNaN.f)), (vert->coord)[2] = ((airFloatQNaN. f)), (vert->coord)[3] = ((airFloatQNaN.f))); | |||
| 272 | /* HEY: this is kind of lame: this information is set in | |||
| 273 | a rather sneaky way, and the setVertexRGBAFromLook is | |||
| 274 | pretty clearly a hack */ | |||
| 275 | if (obj->setVertexRGBAFromLook) { | |||
| 276 | ELL_4V_COPY(vert->rgba, obj->look[part->lookIdx].rgba)((vert->rgba)[0] = (obj->look[part->lookIdx].rgba)[0 ], (vert->rgba)[1] = (obj->look[part->lookIdx].rgba) [1], (vert->rgba)[2] = (obj->look[part->lookIdx].rgba )[2], (vert->rgba)[3] = (obj->look[part->lookIdx].rgba )[3]); | |||
| 277 | } else { | |||
| 278 | ELL_4V_SET(vert->rgba, 1, 1, 1, 1)((vert->rgba)[0] = (1), (vert->rgba)[1] = (1), (vert-> rgba)[2] = (1), (vert->rgba)[3] = (1)); | |||
| 279 | } | |||
| 280 | /* ELL_3V_SET(vert->view, AIR_NAN, AIR_NAN, AIR_NAN); */ | |||
| 281 | /* ELL_3V_SET(vert->screen, AIR_NAN, AIR_NAN, AIR_NAN); */ | |||
| 282 | ELL_3V_SET(vert->worldNormal, AIR_NAN, AIR_NAN, AIR_NAN)((vert->worldNormal)[0] = ((airFloatQNaN.f)), (vert->worldNormal )[1] = ((airFloatQNaN.f)), (vert->worldNormal)[2] = ((airFloatQNaN .f))); | |||
| 283 | ||||
| 284 | return vertIdx; | |||
| 285 | } | |||
| 286 | ||||
| 287 | int | |||
| 288 | limnObjectEdgeAdd(limnObject *obj, unsigned int partIdx, | |||
| 289 | unsigned int lookIdx, unsigned int faceIdx, | |||
| 290 | unsigned int vertIdx0, unsigned int vertIdx1) { | |||
| 291 | int tmp, edgeIdx=-42; | |||
| 292 | unsigned int edgeIdxIdx; | |||
| 293 | limnEdge *edge=NULL((void*)0); | |||
| 294 | limnPart *part; | |||
| 295 | ||||
| 296 | part = obj->part[partIdx]; | |||
| 297 | if (vertIdx0 > vertIdx1) { | |||
| 298 | ELL_SWAP2(vertIdx0, vertIdx1, tmp)((tmp)=(vertIdx0),(vertIdx0)=(vertIdx1),(vertIdx1)=(tmp)); | |||
| 299 | } | |||
| 300 | ||||
| 301 | /* do a linear search through this part's existing edges */ | |||
| 302 | for (edgeIdxIdx=0; edgeIdxIdx<part->edgeIdxNum; edgeIdxIdx++) { | |||
| 303 | edgeIdx = part->edgeIdx[edgeIdxIdx]; | |||
| 304 | edge = obj->edge + edgeIdx; | |||
| 305 | if (edge->vertIdx[0] == vertIdx0 | |||
| 306 | && edge->vertIdx[1] == vertIdx1) { | |||
| 307 | break; | |||
| 308 | } | |||
| 309 | } | |||
| 310 | if (edgeIdxIdx == part->edgeIdxNum) { | |||
| 311 | /* edge not found, add it */ | |||
| 312 | edgeIdx = airArrayLenIncr(obj->edgeArr, 1); | |||
| 313 | edge = obj->edge + edgeIdx; | |||
| 314 | edgeIdxIdx = airArrayLenIncr(part->edgeIdxArr, 1); | |||
| 315 | part->edgeIdx[edgeIdxIdx] = edgeIdx; | |||
| 316 | edge->vertIdx[0] = vertIdx0; | |||
| 317 | edge->vertIdx[1] = vertIdx1; | |||
| 318 | edge->faceIdx[0] = faceIdx; | |||
| 319 | edge->faceIdx[1] = -1; | |||
| 320 | edge->lookIdx = lookIdx; | |||
| 321 | edge->partIdx = partIdx; | |||
| 322 | edge->type = limnEdgeTypeUnknown; | |||
| 323 | edge->once = AIR_FALSE0; | |||
| 324 | } else { | |||
| 325 | /* edge already exists; "edge", "edgeIdx", and "edgeIdxIdx" are all set */ | |||
| 326 | edge->faceIdx[1] = faceIdx; | |||
| 327 | } | |||
| 328 | ||||
| 329 | return edgeIdx; | |||
| 330 | } | |||
| 331 | ||||
| 332 | int | |||
| 333 | limnObjectFaceNumPreSet(limnObject *obj, unsigned int partIdx, | |||
| 334 | unsigned int faceNum) { | |||
| 335 | limnPart *part; | |||
| 336 | ||||
| 337 | part = obj->part[partIdx]; | |||
| 338 | airArrayLenPreSet(obj->faceArr, faceNum); | |||
| 339 | airArrayLenPreSet(part->faceIdxArr, faceNum); | |||
| 340 | return 0; | |||
| 341 | } | |||
| 342 | ||||
| 343 | int | |||
| 344 | limnObjectFaceAdd(limnObject *obj, unsigned int partIdx, | |||
| 345 | unsigned int lookIdx, unsigned int sideNum, | |||
| 346 | unsigned int *vertIdx) { | |||
| 347 | limnFace *face; | |||
| 348 | limnPart *part; | |||
| 349 | unsigned int faceIdx, faceIdxIdx, sideIdx; | |||
| 350 | ||||
| 351 | part = obj->part[partIdx]; | |||
| 352 | faceIdx = airArrayLenIncr(obj->faceArr, 1); | |||
| 353 | face = obj->face + faceIdx; | |||
| 354 | faceIdxIdx = airArrayLenIncr(part->faceIdxArr, 1); | |||
| 355 | part->faceIdx[faceIdxIdx] = faceIdx; | |||
| 356 | ||||
| 357 | face->vertIdx = AIR_CALLOC(sideNum, unsigned int)(unsigned int*)(calloc((sideNum), sizeof(unsigned int))); | |||
| 358 | face->sideNum = sideNum; | |||
| 359 | if (obj->doEdges) { | |||
| 360 | face->edgeIdx = AIR_CALLOC(sideNum, unsigned int)(unsigned int*)(calloc((sideNum), sizeof(unsigned int))); | |||
| 361 | } | |||
| 362 | for (sideIdx=0; sideIdx<sideNum; sideIdx++) { | |||
| 363 | face->vertIdx[sideIdx] = vertIdx[sideIdx]; | |||
| 364 | if (obj->doEdges) { | |||
| 365 | face->edgeIdx[sideIdx] = | |||
| 366 | limnObjectEdgeAdd(obj, partIdx, 0, faceIdx, | |||
| 367 | vertIdx[sideIdx], | |||
| 368 | vertIdx[AIR_MOD((int)sideIdx+1, (int)sideNum)(((int)sideIdx+1)%((int)sideNum) >= 0 ? ((int)sideIdx+1)%( (int)sideNum) : (int)sideNum + ((int)sideIdx+1)%((int)sideNum ))]); | |||
| 369 | } | |||
| 370 | } | |||
| 371 | ELL_3V_SET(face->worldNormal, AIR_NAN, AIR_NAN, AIR_NAN)((face->worldNormal)[0] = ((airFloatQNaN.f)), (face->worldNormal )[1] = ((airFloatQNaN.f)), (face->worldNormal)[2] = ((airFloatQNaN .f))); | |||
| 372 | ELL_3V_SET(face->screenNormal, AIR_NAN, AIR_NAN, AIR_NAN)((face->screenNormal)[0] = ((airFloatQNaN.f)), (face->screenNormal )[1] = ((airFloatQNaN.f)), (face->screenNormal)[2] = ((airFloatQNaN .f))); | |||
| 373 | /* HEY: its potentially confusing that obj->setVertexRGBAFromLook only | |||
| 374 | has an effect with whole parts, and not individual faces */ | |||
| 375 | face->lookIdx = lookIdx; | |||
| 376 | face->partIdx = partIdx; | |||
| 377 | face->visible = AIR_FALSE0; | |||
| 378 | face->depth = AIR_NAN(airFloatQNaN.f); | |||
| 379 | ||||
| 380 | return faceIdx; | |||
| 381 | } | |||
| 382 |