130@interface OOMesh (Private) <NSMutableCopying, OOGraphicsResetClient>
132- (id)initWithName:(NSString *)name
133 cacheKey:(NSString *)cacheKey
134materialDictionary:(NSDictionary *)materialDict
135 shadersDictionary:(NSDictionary *)shadersDict
137 shaderMacros:(NSDictionary *)macros
138shaderBindingTarget:(
id<OOWeakReferenceSupport>)object
139 scaleFactor:(
float)scale
140 cacheWriteable:(BOOL)cacheWriteable;
142- (BOOL) loadData:(NSString *)filename scaleFactor:(
float)scale;
145- (void) calculateVertexNormalsAndTangentsWithFaceRefs:(
VertexFaceRef *)faceRefs;
146- (void) calculateVertexTangentsWithFaceRefs:(
VertexFaceRef *)faceRefs;
151- (BOOL) setModelFromModelData:(NSDictionary*) dict name:(NSString *)fileName;
159- (void) rescaleByFactor:(GLfloat)factor;
166- (void) setRetainedObject:(
id)object forKey:(NSString *)key;
167- (
void *) allocateBytesWithSize:(
size_t)size count:(NSUInteger)count key:(NSString *)key;
170- (BOOL) allocateVertexBuffersWithCount:(NSUInteger)count;
171- (BOOL) allocateNormalBuffersWithCount:(NSUInteger)count;
172- (BOOL) allocateFaceBuffersWithCount:(NSUInteger)count;
173- (BOOL) allocateVertexArrayBuffersWithCount:(NSUInteger)count;
175- (void) renameTexturesFrom:(NSString *)from to:(NSString *)to;
180@interface OOCacheManager (OOMesh)
182+ (NSDictionary *)meshDataForName:(NSString *)inShipName;
183+ (void)setMeshData:(NSDictionary *)inData forName:(NSString *)inShipName;
204 [NSException raise:NSInvalidArgumentException format:@"Unexpected normal mode in %s", __PRETTY_FUNCTION__];
225 [NSException raise:NSInvalidArgumentException format:@"Unexpected normal mode in %s", __PRETTY_FUNCTION__];
233+ (instancetype) meshWithName:(NSString *)name
234 cacheKey:(NSString *)cacheKey
235 materialDictionary:(NSDictionary *)materialDict
236 shadersDictionary:(NSDictionary *)shadersDict
238 shaderMacros:(NSDictionary *)macros
239 shaderBindingTarget:(
id<OOWeakReferenceSupport>)object
241 return [[[
self alloc] initWithName:name
243 materialDictionary:materialDict
244 shadersDictionary:shadersDict
247 shaderBindingTarget:object
249 cacheWriteable:YES] autorelease];
252+ (instancetype) meshWithName:(NSString *)name
253 cacheKey:(NSString *)cacheKey
254 materialDictionary:(NSDictionary *)materialDict
255 shadersDictionary:(NSDictionary *)shadersDict
257 shaderMacros:(NSDictionary *)macros
258 shaderBindingTarget:(
id<OOWeakReferenceSupport>)object
259 scaleFactor:(
float)scale
260 cacheWriteable:(BOOL)cacheWriteable
262 return [[[
self alloc] initWithName:name
264 materialDictionary:materialDict
265 shadersDictionary:shadersDict
268 shaderBindingTarget:object
270 cacheWriteable:cacheWriteable] autorelease];
278 if (placeholderMaterial ==
nil)
283 return placeholderMaterial;
290 if (
self ==
nil)
return nil;
292 baseFile =
@"No Model";
293 baseFileOctreeCacheRef =
@"No Model-0.000";
294 _cacheWriteable = YES;
296 _textureUnitCount = NSNotFound;
311 DESTROY(baseFileOctreeCacheRef);
315 [
self deleteDisplayLists];
354- (NSString *)descriptionComponents
356 return [NSString stringWithFormat:@"\"%@\", %zu vertices, %zu faces, radius: %g m normals: %@", [
self modelName], [
self vertexCount], [
self faceCount], [
self collisionRadius], NormalModeDescription(_normalMode)];
360- (id)copyWithZone:(NSZone *)zone
362 if (zone == [
self zone])
return [
self retain];
363 else return [
self mutableCopyWithZone:zone];
367- (NSString *) modelName
385- (void)renderOpaqueParts
389 BOOL meshBelongsToVisualEffect = [_shaderBindingTarget isVisualEffect];
393 OOGL(glVertexPointer(3, GL_FLOAT, 0, _displayLists.vertexArray));
394 OOGL(glNormalPointer(GL_FLOAT, 0, _displayLists.normalArray));
399 if (meshBelongsToVisualEffect)
401 OOGL(glEnable(GL_BLEND));
402 OOGL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
408 OOGL(glEnableVertexAttribArrayARB(kTangentAttributeIndex));
409 OOGL(glVertexAttribPointerARB(kTangentAttributeIndex, 3, GL_FLOAT, GL_FALSE, 0, _displayLists.tangentArray));
413 BOOL usingNormalsAsTexCoords = NO;
424 if (_textureUnitCount == NSNotFound)
426 _textureUnitCount = 0;
427 for (ti = 0; ti < materialCount; ti++)
429 NSUInteger
count = [materials[ti] countOfTextureUnitsWithBaseCoordinates];
430 if (_textureUnitCount <
count) _textureUnitCount =
count;
435 if (_textureUnitCount <= 1)
437 OOGL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
444 NSAssert2([[
OOOpenGLExtensionManager sharedManager] textureCombinersSupported],
@"Mesh %@ uses %lu texture units, but multitexturing is not available.", [
self shortDescription], _textureUnitCount);
446 for (unit = 0; unit < _textureUnitCount; unit++)
448 OOGL(glClientActiveTextureARB(GL_TEXTURE0_ARB + unit));
449 OOGL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
453 OOGL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
460 OOGL(displayList0 = glGenLists(materialCount));
463 for (ti = 0; ti < materialCount; ti++)
465 [materials[ti] ensureFinishedLoading];
469 for (ti = 0; ti < materialCount; ti++)
471 BOOL wantsNormalsAsTextureCoordinates = [materials[ti] wantsNormalsAsTextureCoordinates];
472 if (ti == 0 || wantsNormalsAsTextureCoordinates != usingNormalsAsTexCoords)
476 for (unit = 0; unit < _textureUnitCount; unit++)
478 if (_textureUnitCount > 1)
480 OOGL(glClientActiveTextureARB(GL_TEXTURE0_ARB + unit));
481 OOGL(glActiveTextureARB(GL_TEXTURE0_ARB + unit));
484 if (!wantsNormalsAsTextureCoordinates)
486 OOGL(glDisable(GL_TEXTURE_CUBE_MAP));
487 OOGL(glTexCoordPointer(2, GL_FLOAT, 0, _displayLists.textureUVArray));
493 OOGL(glEnable(GL_TEXTURE_2D));
497 OOGL(glDisable(GL_TEXTURE_2D));
498 OOGL(glTexCoordPointer(3, GL_FLOAT, 0, _displayLists.vertexArray));
499 OOGL(glEnable(GL_TEXTURE_CUBE_MAP));
504 usingNormalsAsTexCoords = wantsNormalsAsTextureCoordinates;
507 [materials[ti] apply];
508 OOGL(glDrawArrays(GL_TRIANGLES, triangle_range[ti].location, triangle_range[ti].length));
514 @catch (NSException *exception)
518 OOLog(
kOOLogException,
@"***** %s for %@ encountered exception: %@ : %@ *****", __PRETTY_FUNCTION__,
self, [exception name], [exception reason]);
519 brokenInRender = YES;
521 if ([[exception name] hasPrefix:
@"Oolite"]) [UNIVERSE handleOoliteException:exception];
522 else @throw exception;
528 OOGL(glDisableVertexAttribArrayARB(kTangentAttributeIndex));
536 if (_textureUnitCount <= 1)
538 OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
542 for (unit = 0; unit < _textureUnitCount; unit++)
544 OOGL(glClientActiveTextureARB(GL_TEXTURE0_ARB + unit));
545 OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
548 OOGL(glClientActiveTextureARB(GL_TEXTURE0_ARB));
549 OOGL(glActiveTextureARB(GL_TEXTURE0_ARB));
552 OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
561 if (meshBelongsToVisualEffect)
OOGL(glDisable(GL_BLEND));
567- (void) rebindMaterials
572 if (materialCount != 0)
574 for (i = 0; i != materialCount; ++i)
578 if (![materialKeys[i] isEqualToString:
@"_oo_placeholder_material"])
595 materials[i] = [material retain];
605 [oldMaterial release];
611- (NSDictionary *) materials
613 return _materialDict;
617- (NSDictionary *) shaders
623- (BOOL)hasOpaqueParts
628- (GLfloat)collisionRadius
630 return collisionRadius;
634- (GLfloat)maxDrawDistance
636 return maxDrawDistance;
640#if ADAPTIVE_OCTREE_DEPTH
641- (unsigned) octreeDepth
645 GLfloat xs, ys, zs, t,
size;
647 bounding_box_get_dimensions(boundingBox, &xs, &ys, &zs);
649 if (xs < zs) { t = zs; zs = xs; xs = t; }
650 if (ys < zs) { t = zs; zs = ys; ys = t; }
651 size = (xs + ys) / 2.0f;
656 if (
size < threshold)
break;
661 OOLog(
@"mesh.load.octree.size",
@"Selected octree depth %u for size %g for %@", result,
size, baseFile);
665- (unsigned) octreeDepth
679 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
683 for (i = 0; i < faceCount; i++)
687 tri.v[0] = _vertices[_faces[i].vertex[0]];
688 tri.v[1] = _vertices[_faces[i].vertex[1]];
689 tri.v[2] = _vertices[_faces[i].vertex[2]];
695 if (
EXPECT(_cacheWriteable))
704 OOLog(
@"mesh.load.octreeCached",
@"Retrieved octree \"%@\
" from cache.", baseFileOctreeCacheRef);
712- (BoundingBox) findBoundingBoxRelativeToPosition:(Vector)opv
713 basis:(Vector)ri :(Vector)rj :(Vector)rk
714 selfPosition:(Vector)position
715 selfBasis:(Vector)si :(Vector)sj :(Vector)sk
721 Vector rpos = vector_subtract(position, opv);
723 rv.x = dot_product(ri,rpos);
724 rv.y = dot_product(rj,rpos);
725 rv.z = dot_product(rk,rpos);
729 bounding_box_reset_to_vector(&result, rv);
733 pv.x = rpos.x + si.
x * _vertices[0].
x + sj.
x * _vertices[0].
y + sk.
x * _vertices[0].z;
734 pv.y = rpos.y + si.
y * _vertices[0].
x + sj.
y * _vertices[0].
y + sk.
y * _vertices[0].z;
735 pv.z = rpos.z + si.z * _vertices[0].
x + sj.z * _vertices[0].
y + sk.z * _vertices[0].z;
736 rv.x = dot_product(ri, pv);
737 rv.y = dot_product(rj, pv);
738 rv.z = dot_product(rk, pv);
739 bounding_box_reset_to_vector(&result, rv);
743 for (i = 1; i < vertexCount; i++)
745 pv.x = rpos.x + si.
x * _vertices[i].
x + sj.
x * _vertices[i].
y + sk.
x * _vertices[i].z;
746 pv.y = rpos.y + si.
y * _vertices[i].
x + sj.
y * _vertices[i].
y + sk.
y * _vertices[i].z;
747 pv.z = rpos.z + si.z * _vertices[i].
x + sj.z * _vertices[i].
y + sk.z * _vertices[i].z;
748 rv.x = dot_product(ri, pv);
749 rv.y = dot_product(rj, pv);
750 rv.z = dot_product(rk, pv);
751 bounding_box_add_vector(&result, rv);
758- (BoundingBox)findSubentityBoundingBoxWithPosition:(Vector)position rotMatrix:(OOMatrix)rotMatrix
765 if (vector_equal(position,_lastPosition) &&
OOMatrixEqual(rotMatrix,_lastRotMatrix))
767 return _lastBoundingBox;
774 bounding_box_reset_to_vector(&result,v);
777 for (i = 1; i < vertexCount; i++)
780 bounding_box_add_vector(&result,v);
783 _lastBoundingBox = result;
784 _lastPosition = position;
785 _lastRotMatrix = rotMatrix;
791- (
OOMesh *)meshRescaledBy:(GLfloat)scaleFactor
793 OOMesh *result = [
self mutableCopy];
795 return [result autorelease];
799- (void)setBindingTarget:(
id<OOWeakReferenceSupport>)target
805 [materials[i] setBindingTarget:target];
813 [
super dumpSelfState];
815 if (baseFile !=
nil)
OOLog(
@"dumpState.mesh",
@"Model file: %@", baseFile);
816 OOLog(
@"dumpState.mesh",
@"Vertex count: %u, face count: %u", vertexCount, faceCount);
817 OOLog(
@"dumpState.mesh",
@"Normals: %@", NormalModeDescription(_normalMode));
823- (NSSet *) allTextures
825 NSMutableSet *result = [NSMutableSet set];
827 for (i = 0; i != materialCount; i++)
829 [result unionSet:[materials[i] allTextures]];
838 size_t result = [
super totalSize];
839 if (_vertices != NULL) result +=
sizeof *_vertices * vertexCount;
840 if (_normals != NULL) result +=
sizeof *_normals * vertexCount;
841 if (_tangents != NULL) result +=
sizeof *_tangents * vertexCount;
842 if (_faces != NULL) result +=
sizeof *_faces * faceCount;
844 result += _displayLists.
count * (sizeof (GLint) + sizeof (GLfloat) + sizeof (Vector) * 3);
847 for (i = 0; i != materialCount; i++)
849 result += [materials[i] oo_objectSize];
852 result += [octree totalSize];
863- (BOOL) suppressClangStuff
865 return _normals && _tangents && _faces && boundingBox.min.x;
871@implementation OOMesh (Private)
873- (id)initWithName:(NSString *)name
874 cacheKey:(NSString *)cacheKey
875materialDictionary:(NSDictionary *)materialDict
876 shadersDictionary:(NSDictionary *)shadersDict
878 shaderMacros:(NSDictionary *)macros
879shaderBindingTarget:(
id<OOWeakReferenceSupport>)target
880 scaleFactor:(
float)scale
881 cacheWriteable:(BOOL)cacheWriteable
886 if (
self ==
nil)
return nil;
888 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
890 _cacheWriteable = cacheWriteable;
896 if ([
self loadData:name scaleFactor:scale])
898 [
self calculateBoundingVolumes];
899 PROFILE(
@"finished calculateBoundingVolumes (again\?\?)");
901 baseFile = [name copy];
902 baseFileOctreeCacheRef = [[NSString stringWithFormat:@"%@-%.3f", baseFile, scale] copy];
908 _materialDict = [materialDict copy];
909 _shadersDict = [shadersDict copy];
910 _cacheKey = [cacheKey copy];
911 _shaderMacros = [macros copy];
912 _shaderBindingTarget = [target weakRetain];
914 [
self rebindMaterials];
915 PROFILE(
@"finished material setup");
930 _textureUnitCount = NSNotFound;
941- (id)mutableCopyWithZone:(NSZone *)zone
946 result = (
OOMesh *)NSCopyObject(
self, 0, zone);
950 [result->baseFile retain];
951 [result->baseFileOctreeCacheRef retain];
952 [result->octree retain];
953 [result->_retainedObjects retain];
954 [result->_materialDict retain];
955 [result->_shadersDict retain];
956 [result->_cacheKey retain];
957 [result->_shaderMacros retain];
958 [result->_shaderBindingTarget retain];
962 [result->materialKeys[i] retain];
963 [result->materials[i] retain];
982 OOGL(glDeleteLists(displayList0, materialCount));
990 [
self deleteDisplayLists];
991 [
self rebindMaterials];
992 _textureUnitCount = NSNotFound;
1000 NSNumber *vertCnt =
nil,
1002 NSData *vertData =
nil,
1006 NSArray *mtlKeys =
nil;
1007 NSNumber *normMode =
nil;
1012 vertCnt = [NSNumber numberWithUnsignedInt:vertexCount];
1013 faceCnt = [NSNumber numberWithUnsignedInt:faceCount];
1015 vertData = [_retainedObjects objectForKey:@"vertices"];
1016 faceData = [_retainedObjects objectForKey:@"faces"];
1019 normData = [_retainedObjects objectForKey:@"normals"];
1020 tanData = [_retainedObjects objectForKey:@"tangents"];
1023 if (materialCount != 0)
1025 mtlKeys = [NSArray arrayWithObjects:materialKeys count:materialCount];
1029 mtlKeys = [NSArray array];
1031 normMode = [NSNumber numberWithUnsignedChar:_normalMode];
1034 if (vertCnt ==
nil ||
1046 if (normData ==
nil || tanData ==
nil)
return nil;
1050 return [NSDictionary dictionaryWithObjectsAndKeys:
1051 vertCnt, @"vertex count",
1052 vertData, @"vertex data",
1053 faceCnt, @"face count",
1054 faceData, @"face data",
1055 mtlKeys, @"material keys",
1056 normMode, @"normal mode",
1061 normData, @"normal data",
1062 tanData, @"tangent data",
1069- (BOOL)setModelFromModelData:(NSDictionary *)dict name:(NSString *)fileName
1073 NSData *vertData =
nil,
1077 NSArray *mtlKeys =
nil;
1078 NSString *key =
nil;
1081 if (dict ==
nil || ![dict isKindOfClass:[NSDictionary
class]])
return NO;
1083 vertexCount = [dict oo_unsignedIntForKey:@"vertex count"];
1084 faceCount = [dict oo_unsignedIntForKey:@"face count"];
1086 if (vertexCount == 0 || faceCount == 0)
return NO;
1089 vertData = [dict oo_dataForKey:@"vertex data"];
1090 faceData = [dict oo_dataForKey:@"face data"];
1092 mtlKeys = [dict oo_arrayForKey:@"material keys"];
1093 _normalMode = [dict oo_unsignedCharForKey:@"normal mode"];
1097 if (vertData ==
nil ||
1101 OOLog(
@"mesh.load.error.badCacheData",
@"Ignoring bad cache data for mesh \"%@\
".", fileName);
1107 normData = [dict oo_dataForKey:@"normal data"];
1108 tanData = [dict oo_dataForKey:@"tangent data"];
1109 if (normData ==
nil || tanData ==
nil)
1111 OOLog(
@"mesh.load.error.badCacheData",
@"Ignoring bad normal/tangent cache data for mesh \"%@\
".", fileName);
1117 if ([vertData length] !=
sizeof *_vertices * vertexCount)
return NO;
1118 if ([faceData length] !=
sizeof *_faces * faceCount)
return NO;
1121 if ([normData length] !=
sizeof *_normals * vertexCount)
return NO;
1122 if ([tanData length] !=
sizeof *_tangents * vertexCount)
return NO;
1126 _vertices = (Vector *)[vertData bytes];
1127 [
self setRetainedObject:vertData forKey:@"vertices"];
1129 [
self setRetainedObject:faceData forKey:@"faces"];
1132 _normals = (Vector *)[normData bytes];
1133 [
self setRetainedObject:normData forKey:@"normals"];
1134 _tangents = (Vector *)[tanData bytes];
1135 [
self setRetainedObject:tanData forKey:@"tangents"];
1144 materialCount = [mtlKeys count];
1145 for (i = 0; i != materialCount; ++i)
1147 key = [mtlKeys oo_stringAtIndex:i];
1148 if (key !=
nil) materialKeys[i] = [key copy];
1151 OOLog(
@"mesh.load.error.badCacheData",
@"Ignoring bad cache data for mesh \"%@\
".", fileName);
1162- (BOOL)loadData:(NSString *)filename scaleFactor:(
float)scale
1167 NSDictionary *cacheData =
nil;
1169 NSString *failString =
@"***** ";
1171 NSMutableDictionary *texFileName2Idx =
nil;
1172 NSString *cacheKey =
nil;
1173 BOOL using_preloaded = NO;
1175 cacheKey = [NSString stringWithFormat:@"%@:%u:%.3f", filename, _normalMode, scale];
1177 if (cacheData !=
nil)
1179 if ([
self setModelFromModelData:cacheData name:
filename])
1181 using_preloaded = YES;
1182 PROFILE(
@"loaded from cache");
1183 OOLog(
@"mesh.load.cached",
@"Retrieved mesh \"%@\
" from cache.",
filename);
1187 if (!using_preloaded)
1189 OOLog(
@"mesh.load.uncached",
@"Mesh \"%@\
" is not in cache, loading.", cacheKey);
1191 NSCharacterSet *whitespaceCharSet = [NSCharacterSet whitespaceCharacterSet];
1192 NSCharacterSet *whitespaceAndNewlineCharSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
1194 NSCharacterSet *newlineCharSet = [NSCharacterSet newlineCharacterSet];
1196 static NSCharacterSet *newlineCharSet =
nil;
1197 if (newlineCharSet ==
nil)
1199 NSMutableCharacterSet *temp = [[whitespaceAndNewlineCharSet mutableCopy] autorelease];
1200 [temp formIntersectionWithCharacterSet:[whitespaceCharSet invertedSet]];
1201 newlineCharSet = [temp copy];
1205 texFileName2Idx = [NSMutableDictionary dictionary];
1208 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
1219 NSMutableArray *lines = [NSMutableArray arrayWithArray:[data componentsSeparatedByString:@"\n"]];
1220 for (i = 0; i < [lines count]; i++)
1222 NSString *line = [lines objectAtIndex:i];
1227 parts = [line componentsSeparatedByString:@"#"];
1228 line = [parts objectAtIndex:0];
1229 parts = [line componentsSeparatedByString:@"//"];
1230 line = [parts objectAtIndex:0];
1234 line = [[line componentsSeparatedByString:@","] componentsJoinedByString:@" "];
1236 [lines replaceObjectAtIndex:i withObject:line];
1239 data = [lines componentsJoinedByString:@"\n"];
1240 scanner = [NSScanner scannerWithString:data];
1244 [scanner autorelease];
1247 PROFILE(
@"finished preprocessing");
1251 [scanner setScanLocation:0];
1252 if ([scanner scanString:
@"NVERTS" intoString:NULL])
1255 if ([scanner scanInt:&n_v])
1260 failString = [NSString stringWithFormat:@"%@Failed to read value of NVERTS\n",failString];
1266 failString = [NSString stringWithFormat:@"%@Failed to read NVERTS\n",failString];
1269 if (![
self allocateVertexBuffersWithCount:vertexCount])
1276 if ([scanner scanString:
@"NFACES" intoString:NULL])
1279 if ([scanner scanInt:&n_f])
1286 failString = [NSString stringWithFormat:@"%@Failed to read value of NFACES\n",failString];
1292 failString = [NSString stringWithFormat:@"%@Failed to read NFACES\n",failString];
1298 if (faceRefs != NULL)
1301 NSData *faceRefHolder = [NSData dataWithBytesNoCopy:faceRefs length:faceRefSize freeWhenDone:YES];
1302 if (faceRefHolder ==
nil)
1309 if (faceRefs == NULL || ![
self allocateFaceBuffersWithCount:faceCount])
1316 if ([scanner scanString:
@"VERTEX" intoString:NULL])
1318 for (j = 0; j < vertexCount; j++)
1323 if (![scanner scanFloat:&
x]) failFlag = YES;
1324 if (![scanner scanFloat:&
y]) failFlag = YES;
1325 if (![scanner scanFloat:&z]) failFlag = YES;
1328 _vertices[j] = make_vector(
x*scale,
y*scale, z*scale);
1332 failString = [NSString stringWithFormat:@"%@Failed to read a value for vertex[%d] in %@\n", failString, j, @"VERTEX"];
1340 failString = [NSString stringWithFormat:@"%@Failed to find VERTEX data\n",failString];
1344 if ([scanner scanString:
@"FACES" intoString:NULL])
1346 for (j = 0; j < faceCount; j++)
1354 if (![scanner scanInt:&r]) failFlag = YES;
1355 if (![scanner scanInt:&g]) failFlag = YES;
1356 if (![scanner scanInt:&b]) failFlag = YES;
1359 _faces[j].smoothGroup = r;
1363 failString = [NSString stringWithFormat:@"%@Failed to read a color for face[%d] in FACES\n", failString, j];
1367 if (![scanner scanFloat:&nx]) failFlag = YES;
1368 if (![scanner scanFloat:&ny]) failFlag = YES;
1369 if (![scanner scanFloat:&nz]) failFlag = YES;
1372 _faces[j].normal = vector_normal(make_vector(nx, ny, nz));
1376 failString = [NSString stringWithFormat:@"%@Failed to read a normal for face[%d] in FACES\n", failString, j];
1380 if ([scanner scanInt:&n_v])
1385 failString = [NSString stringWithFormat:@"%@Face[%u] has fewer than three vertices.\n", failString, j];
1389 OOLogWARN(
@"mesh.load.warning.nonTriangular",
@"Face[%u] of %@ has %u vertices specified. Only the first three will be used.", j, baseFile, n_v);
1396 failString = [NSString stringWithFormat:@"%@Failed to read number of vertices for face[%d] in FACES\n", failString, j];
1402 for (i = 0; (
int)i < n_v; i++)
1404 if ([scanner scanInt:&vi])
1406 _faces[j].vertex[i] = vi;
1407 if (faceRefs != NULL)
VFRAddFace(&faceRefs[vi], j);
1412 failString = [NSString stringWithFormat:@"%@Failed to read vertex[%d] for face[%d] in FACES\n", failString, i, j];
1422 failString = [NSString stringWithFormat:@"%@Failed to find FACES data\n",failString];
1426 if ([scanner scanString:
@"TEXTURES" intoString:NULL])
1428 for (j = 0; j < faceCount; j++)
1430 NSString *materialKey;
1437 [scanner scanCharactersFromSet:whitespaceAndNewlineCharSet intoString:NULL];
1438 if (![scanner scanUpToCharactersFromSet:whitespaceCharSet intoString:&materialKey])
1441 failString = [NSString stringWithFormat:@"%@Failed to read texture filename for face[%d] in TEXTURES\n", failString, j];
1445 NSNumber *index = [texFileName2Idx objectForKey:materialKey];
1448 _faces[j].materialIndex = [index unsignedIntValue];
1457 _faces[j].materialIndex = materialCount;
1458 materialKeys[materialCount] = [materialKey retain];
1459 index = [NSNumber numberWithUnsignedInt:materialCount];
1460 [texFileName2Idx setObject:index forKey:materialKey];
1469 if (![scanner scanFloat:&max_x]) failFlag = YES;
1470 if (![scanner scanFloat:&max_y]) failFlag = YES;
1472 failString = [NSString stringWithFormat:@"%@Failed to read texture size for max_x and max_y in face[%d] in TEXTURES\n", failString, j];
1479 for (i = 0; i < 3; i++)
1481 if (![scanner scanFloat:&s]) failFlag = YES;
1482 if (![scanner scanFloat:&t]) failFlag = YES;
1485 _faces[j].s[i] = s / max_x;
1486 _faces[j].t[i] = t / max_y;
1489 failString = [NSString stringWithFormat:@"%@Failed to read s t coordinates for vertex[%d] in face[%d] in TEXTURES\n", failString, i, j];
1498 failString = [failString stringByAppendingString:@"Failed to find TEXTURES data (will use placeholder material)\n"];
1499 materialKeys[0] =
@"_oo_placeholder_material";
1502 for (j = 0; j < faceCount; j++)
1504 _faces[j].materialIndex = 0;
1508 if ([scanner scanString:
@"NAMES" intoString:NULL])
1511 if (![scanner scanInt:(
int *)&
count])
1514 failString = [failString stringByAppendingString:@"Expected count after NAMES\n"];
1518 for (j = 0; j <
count; j++)
1520 NSString *name =
nil;
1521 [scanner scanCharactersFromSet:whitespaceAndNewlineCharSet intoString:NULL];
1522 if (![scanner scanUpToCharactersFromSet:newlineCharSet intoString:&name])
1525 failString = [failString stringByAppendingString:@"Expected file name\n"];
1529 [
self renameTexturesFrom:[NSString stringWithFormat:@"%u", j] to:name];
1535 BOOL explicitTangents = NO;
1538 if ([scanner scanString:
@"NORMALS" intoString:NULL])
1541 if (![
self allocateNormalBuffersWithCount:vertexCount])
1547 for (j = 0; j < vertexCount; j++)
1552 if (![scanner scanFloat:&
x]) failFlag = YES;
1553 if (![scanner scanFloat:&
y]) failFlag = YES;
1554 if (![scanner scanFloat:&z]) failFlag = YES;
1557 _normals[j] = vector_normal(make_vector(
x,
y, z));
1561 failString = [NSString stringWithFormat:@"%@Failed to read a value for vertex[%d] in %@\n", failString, j, @"NORMALS"];
1567 if ([scanner scanString:
@"TANGENTS" intoString:NULL])
1569 for (j = 0; j < vertexCount; j++)
1574 if (![scanner scanFloat:&
x]) failFlag = YES;
1575 if (![scanner scanFloat:&
y]) failFlag = YES;
1576 if (![scanner scanFloat:&z]) failFlag = YES;
1579 _tangents[j] = vector_normal(make_vector(
x,
y, z));
1583 failString = [NSString stringWithFormat:@"%@Failed to read a value for vertex[%d] in %@\n", failString, j, @"TANGENTS"];
1594 [
self checkNormalsAndAdjustWinding];
1595 PROFILE(
@"finished checkNormalsAndAdjustWinding");
1597 if (!explicitTangents)
1599 [
self generateFaceTangents];
1600 PROFILE(
@"finished generateFaceTangents");
1606 if (![
self allocateNormalBuffersWithCount:vertexCount])
1611 [
self calculateVertexNormalsAndTangentsWithFaceRefs:faceRefs];
1612 PROFILE(
@"finished calculateVertexNormalsAndTangents");
1617 [
self calculateVertexTangentsWithFaceRefs:faceRefs];
1618 PROFILE(
@"finished calculateVertexTangents");
1622 if (
EXPECT(_cacheWriteable))
1630 OOLog(
@"mesh.error",
@"%@ ..... from %@ %@", failString,
filename, (using_preloaded)?
@"(from preloaded data)" :
@"(from file)");
1634 [
self calculateBoundingVolumes];
1635 PROFILE(
@"finished calculateBoundingVolumes");
1639 PROFILE(
@"finished setUpVertexArrays");
1651 Vector calculatedNormal;
1656 for (i = 0; i < faceCount; i++)
1658 Vector v0, v1, v2, norm;
1659 v0 = _vertices[_faces[i].vertex[0]];
1660 v1 = _vertices[_faces[i].vertex[1]];
1661 v2 = _vertices[_faces[i].vertex[2]];
1662 norm = _faces[i].normal;
1664 calculatedNormal = normal_to_surface(v2, v1, v0);
1667 norm = vector_flip(calculatedNormal);
1668 _faces[i].normal = norm;
1675 if (norm.x * calculatedNormal.x < 0 || norm.y * calculatedNormal.y < 0 || norm.z * calculatedNormal.z < 0)
1679 int v0 = _faces[i].vertex[0];
1680 _faces[i].vertex[0] = _faces[i].vertex[2];
1681 _faces[i].vertex[2] = v0;
1683 GLfloat f0 = _faces[i].s[0];
1684 _faces[i].s[0] = _faces[i].s[2];
1685 _faces[i].s[2] = f0;
1687 f0 = _faces[i].t[0];
1688 _faces[i].t[0] = _faces[i].t[2];
1689 _faces[i].t[2] = f0;
1702 for (i = 0; i < faceCount; i++)
1711 Vector vAB = vector_subtract(_vertices[face->
vertex[1]], _vertices[face->
vertex[0]]);
1712 Vector vAC = vector_subtract(_vertices[face->
vertex[2]], _vertices[face->
vertex[0]]);
1713 Vector nA = face->
normal;
1716 Vector vProjAB = vector_subtract(vAB, vector_multiply_scalar(nA, dot_product(nA, vAB)));
1717 Vector vProjAC = vector_subtract(vAC, vector_multiply_scalar(nA, dot_product(nA, vAC)));
1720 GLfloat dsAB = face->
s[1] - face->s[0];
1721 GLfloat dsAC = face->
s[2] - face->s[0];
1722 GLfloat dtAB = face->
t[1] - face->t[0];
1723 GLfloat dtAC = face->
t[2] - face->t[0];
1725 if (dsAC * dtAB > dsAB * dtAC)
1727 face->
tangent = vector_normal(vector_subtract(vector_multiply_scalar(vProjAC, dtAB), vector_multiply_scalar(vProjAB, dtAC)));
1731 face->
tangent = vector_normal(vector_subtract(vector_multiply_scalar(vProjAB, dtAC), vector_multiply_scalar(vProjAC, dtAB)));
1739static float FaceArea(GLuint *vertIndices, Vector *vertices)
1742 float a2 = distance2(vertices[vertIndices[0]], vertices[vertIndices[1]]);
1743 float b2 = distance2(vertices[vertIndices[1]], vertices[vertIndices[2]]);
1744 float c2 = distance2(vertices[vertIndices[2]], vertices[vertIndices[0]]);
1745 return sqrt((2.0f * (a2 * b2 + b2 * c2 + c2 * a2) - (a2 * a2 + b2 * b2 +c2 * c2)) * 0.0625f);
1749- (void) calculateVertexNormalsAndTangentsWithFaceRefs:(
VertexFaceRef *)faceRefs
1753 NSParameterAssert(faceRefs != NULL);
1756 float triangle_area[faceCount];
1758 NSAssert1(_normals != NULL && _tangents != NULL,
@"Normal/tangent buffers not allocated in %s", __PRETTY_FUNCTION__);
1760 for (i = 0 ; i < faceCount; i++)
1762 triangle_area[i] =
FaceArea(_faces[i].vertex, _vertices);
1764 for (i = 0; i < vertexCount; i++)
1771 for (fIter = 0; fIter < fCount; fIter++)
1775 float t = triangle_area[j];
1776 normal_sum = vector_add(normal_sum, vector_multiply_scalar(_faces[j].normal, t));
1777 tangent_sum = vector_add(tangent_sum, vector_multiply_scalar(_faces[j].tangent, t));
1780 normal_sum = vector_normal_or_fallback(normal_sum,
kBasisZVector);
1781 tangent_sum = vector_subtract(tangent_sum, vector_multiply_scalar(normal_sum, dot_product(tangent_sum, normal_sum)));
1782 tangent_sum = vector_normal_or_fallback(tangent_sum,
kBasisXVector);
1784 _normals[i] = normal_sum;
1785 _tangents[i] = tangent_sum;
1802 Vector AB = vector_subtract(vertices[vertIndices[1]], vertices[vertIndices[0]]);
1803 Vector AC = vector_subtract(vertices[vertIndices[2]], vertices[vertIndices[0]]);
1804 return magnitude(true_cross_product(AB, AC));
1808- (void) calculateVertexTangentsWithFaceRefs:(
VertexFaceRef *)faceRefs
1812 NSParameterAssert(faceRefs != NULL);
1828 float triangle_area[faceCount];
1829 for (i = 0 ; i < faceCount; i++)
1833 for (i = 0; i < vertexCount; i++)
1839 for (fIter = 0; fIter < fCount; fIter++)
1843 float t = triangle_area[j];
1844 tangent_sum = vector_add(tangent_sum, vector_multiply_scalar(_faces[j].tangent, t));
1847 tangent_sum = vector_subtract(tangent_sum, vector_multiply_scalar(_normals[i], dot_product(_normals[i], tangent_sum)));
1848 tangent_sum = vector_normal_or_fallback(tangent_sum,
kBasisXVector);
1850 _tangents[i] = tangent_sum;
1862 assert(outNormal != NULL && outTangent != NULL);
1867 for (j = 0; j < faceCount; j++)
1869 if (_faces[j].smoothGroup == smoothGroup)
1871 if ((_faces[j].vertex[0] == v_index)||(_faces[j].vertex[1] == v_index)||(_faces[j].vertex[2] == v_index))
1873 float area =
FaceArea(_faces[j].vertex, _vertices);
1874 normal_sum = vector_add(normal_sum, vector_multiply_scalar(_faces[j].normal, area));
1875 tangent_sum = vector_add(tangent_sum, vector_multiply_scalar(_faces[j].tangent, area));
1880 *outNormal = vector_normal_or_fallback(normal_sum,
kBasisZVector);
1881 *outTangent = vector_normal_or_fallback(tangent_sum,
kBasisXVector);
1891 NSUInteger fi, vi, mi;
1893 if (![
self allocateVertexArrayBuffersWithCount:faceCount])
return NO;
1898 BOOL is_edge_vertex[vertexCount];
1899 GLfloat smoothGroup[vertexCount];
1900 for (vi = 0; vi < vertexCount; vi++)
1902 is_edge_vertex[vi] = NO;
1903 smoothGroup[vi] = -1;
1907 for (fi = 0; fi < faceCount; fi++)
1909 GLfloat rv = _faces[fi].smoothGroup;
1911 for (i = 0; i < 3; i++)
1913 vi = _faces[fi].vertex[i];
1914 if (smoothGroup[vi] < 0.0)
1915 smoothGroup[vi] = rv;
1916 else if (smoothGroup[vi] != rv)
1917 is_edge_vertex[vi] = YES;
1926 int vertex_index = 0;
1929 for (mi = 0; mi != materialCount; ++mi)
1931 triangle_range[mi].location = tri_index;
1933 for (fi = 0; fi < faceCount; fi++)
1935 Vector normal, tangent;
1937 if (_faces[fi].materialIndex == mi)
1939 for (vi = 0; vi < 3; vi++)
1941 int v = _faces[fi].vertex[vi];
1944 if (is_edge_vertex[v])
1946 [
self getNormal:&normal andTangent:&tangent forVertex:v inSmoothGroup:_faces[fi].smoothGroup];
1950 NSAssert1(_normals != NULL && _tangents != NULL,
@"Normal/tangent buffers not allocated in %s", __PRETTY_FUNCTION__);
1952 normal = _normals[v];
1953 tangent = _tangents[v];
1958 normal = _faces[fi].normal;
1959 tangent = _faces[fi].tangent;
1963 _displayLists.indexArray[tri_index++] = vertex_index;
1964 _displayLists.normalArray[vertex_index] = normal;
1965 _displayLists.tangentArray[vertex_index] = tangent;
1966 _displayLists.vertexArray[vertex_index++] = _vertices[v];
1967 _displayLists.textureUVArray[uv_index++] = _faces[fi].s[vi];
1968 _displayLists.textureUVArray[uv_index++] = _faces[fi].t[vi];
1972 triangle_range[mi].length = tri_index - triangle_range[mi].location;
1975 _displayLists.count = tri_index;
1987 float d_squared, length_longest_axis, length_shortest_axis;
1991 if (vertexCount) bounding_box_reset_to_vector(&
boundingBox, _vertices[0]);
1994 for (i = 0; i < vertexCount; i++)
1996 d_squared = magnitude2(_vertices[i]);
1997 if (d_squared > result) result = d_squared;
1998 bounding_box_add_vector(&
boundingBox, _vertices[i]);
2013 d_squared = (length_longest_axis + length_shortest_axis) * (length_longest_axis + length_shortest_axis) * 0.25;
2016 collisionRadius = sqrtf(result);
2022- (void) rescaleByFactor:(GLfloat)factor
2026 Vector *vertex = NULL;
2028 for (i = 0; i < vertexCount; i++)
2030 vertex = &_vertices[i];
2031 *vertex = vector_multiply_scalar(*vertex, factor);
2035 for (i = 0; i < _displayLists.count; i++)
2037 vertex = &_displayLists.vertexArray[i];
2038 *vertex = vector_multiply_scalar(*vertex, factor);
2041 [
self calculateBoundingVolumes];
2044 DESTROY(baseFileOctreeCacheRef);
2059 float length, blend;
2069 for (i = 0; i < _displayLists.count; ++i)
2071 v = _displayLists.vertexArray[i];
2072 n = _displayLists.normalArray[i];
2073 t = _displayLists.tangentArray[i];
2074 b = true_cross_product(n, t);
2077 length = magnitude2(n);
2078 blend = fabs(length - 1) * 5.0;
2079 color[0] =
MIN(blend, 1.0f);
2080 color[1] = 1.0f - color[0];
2081 color[2] = color[1];
2084 glVertex3f(v.x, v.y, v.z);
2085 scale_vector(&n, 5.0f);
2086 n = vector_add(n, v);
2087 glVertex3f(n.x, n.y, n.z);
2090 glColor3f(1.0f, 1.0f, 0.0f);
2091 t = vector_add(v, vector_multiply_scalar(t, 3.0f));
2092 glVertex3f(v.x, v.y, v.z);
2093 glVertex3f(t.x, t.y, t.z);
2096 glColor3f(0.0f, 1.0f, 0.0f);
2097 b = vector_add(v, vector_multiply_scalar(b, 3.0f));
2098 glVertex3f(v.x, v.y, v.z);
2099 glVertex3f(b.x, b.y, b.z);
2108- (void) setRetainedObject:(
id)object forKey:(NSString *)key
2114 if (_retainedObjects ==
nil) _retainedObjects = [[NSMutableDictionary alloc] init];
2115 [_retainedObjects setObject:object forKey:key];
2123 #if OOLITE_BIG_ENDIAN
2124 enum { kScribble = 0xFEEDFACE };
2126 enum { kScribble = 0xCEFAEDFE };
2129 size /=
sizeof (uint32_t);
2130 uint32_t *mem = bytes;
2131 while (
size--) *mem++ = kScribble;
2134#define Scribble(bytes, size) do {} while (0)
2141- (
void *) allocateBytesWithSize:(
size_t)size count:(NSUInteger)count key:(NSString *)key
2145 void *bytes = malloc(
size);
2149 NSData *holder = [NSData dataWithBytesNoCopy:bytes length:size freeWhenDone:YES];
2150 [
self setRetainedObject:holder forKey:key];
2156- (BOOL) allocateVertexBuffersWithCount:(NSUInteger)count
2158 _vertices = [
self allocateBytesWithSize:sizeof *_vertices count:vertexCount key:@"vertices"];
2159 return _vertices != NULL;
2163- (BOOL) allocateNormalBuffersWithCount:(NSUInteger)count
2165 _normals = [
self allocateBytesWithSize:sizeof *_normals count:vertexCount key:@"normals"];
2166 _tangents = [
self allocateBytesWithSize:sizeof *_tangents count:vertexCount key:@"tangents"];
2167 return _normals != NULL && _tangents != NULL;
2171- (BOOL) allocateFaceBuffersWithCount:(NSUInteger)count
2173 _faces = [
self allocateBytesWithSize:sizeof *_faces count:faceCount key:@"faces"];
2174 return _faces != NULL;
2178- (BOOL) allocateVertexArrayBuffersWithCount:(NSUInteger)count
2180 _displayLists.indexArray = [
self allocateBytesWithSize:sizeof *_displayLists.indexArray count:count * 3 key:@"indexArray"];
2181 _displayLists.textureUVArray = [
self allocateBytesWithSize:sizeof *_displayLists.textureUVArray count:count * 6 key:@"textureUVArray"];
2182 _displayLists.vertexArray = [
self allocateBytesWithSize:sizeof *_displayLists.vertexArray count:count * 3 key:@"vertexArray"];
2183 _displayLists.normalArray = [
self allocateBytesWithSize:sizeof *_displayLists.normalArray count:count * 3 key:@"normalArray"];
2184 _displayLists.tangentArray = [
self allocateBytesWithSize:sizeof *_displayLists.tangentArray count:count * 3 key:@"tangentArray"];
2186 return _faces != NULL &&
2187 _displayLists.indexArray != NULL &&
2188 _displayLists.textureUVArray != NULL &&
2189 _displayLists.vertexArray != NULL &&
2190 _displayLists.normalArray != NULL &&
2191 _displayLists.tangentArray != NULL;
2195- (void) renameTexturesFrom:(NSString *)from to:(NSString *)to
2201 for (i = 0; i != materialCount; i++)
2203 if ([materialKeys[i] isEqualToString:from])
2205 [materialKeys[i] release];
2206 materialKeys[i] = [to copy];
2216@implementation OOCacheManager (OOMesh)
2218+ (NSDictionary *)meshDataForName:(NSString *)inShipName
2220 return [[
self sharedCache] objectForKey:inShipName inCache:kOOCacheMeshes];
2224+ (void)setMeshData:(NSDictionary *)inData forName:(NSString *)inShipName
2226 if (inData !=
nil && inShipName !=
nil)
2228 [[
self sharedCache] setObject:inData forKey:inShipName inCache:kOOCacheMeshes];
2237@implementation OOCacheManager (Octree)
2239+ (
Octree *)octreeForModel:(NSString *)inKey
2241 NSDictionary *dict =
nil;
2244 if (inKey ==
nil)
return nil;
2246 dict = [[
self sharedCache] objectForKey:inKey inCache:kOOCacheOctrees];
2249 result = [[
Octree alloc] initWithDictionary:dict];
2250 [result autorelease];
2257+ (void)setOctree:(
Octree *)inOctree forModel:(NSString *)inKey
2259 if (inOctree !=
nil && inKey !=
nil)
2268 NSCParameterAssert(vfr != NULL);
2277 [vfr->extra addObject:[NSNumber numberWithInteger:index]];
2284 NSCParameterAssert(vfr != NULL);
2292 NSCParameterAssert(vfr != NULL && index <
VFRGetCount(vfr));
2294 if (index < vfr->internCount)
return vfr->
internFaces[index];
2295 else return [vfr->extra oo_unsignedIntegerAtIndex:index - vfr->internCount];