60#define ADAPTIVE_OCTREE_DEPTH 1
89#define PROFILE(tag) do { _stopwatchLastTime = Profile(tag, _stopwatch, _stopwatchLastTime); } while (0)
93 OOLog(
@"mesh.profile",
@"Mesh profile: stage %@, %g seconds (delta %g)", tag, now, now - lastTime);
97#define PROFILE(tag) do {} while (0)
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__];
231@implementation OOMesh
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];
290 if (
self ==
nil)
return nil;
296 _textureUnitCount = NSNotFound;
360- (id)copyWithZone:(NSZone *)zone
362 if (zone == [
self zone])
return [
self retain];
389 BOOL meshBelongsToVisualEffect = [_shaderBindingTarget isVisualEffect];
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;
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));
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));
493 OOGL(glEnable(GL_TEXTURE_2D));
497 OOGL(glDisable(GL_TEXTURE_2D));
499 OOGL(glEnable(GL_TEXTURE_CUBE_MAP));
504 usingNormalsAsTexCoords = wantsNormalsAsTextureCoordinates;
514 @catch (NSException *exception)
518 OOLog(
kOOLogException,
@"***** %s for %@ encountered exception: %@ : %@ *****", __PRETTY_FUNCTION__,
self, [exception name], [exception reason]);
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));
578 if (![
materialKeys[i] isEqualToString:
@"_oo_placeholder_material"])
640#if ADAPTIVE_OCTREE_DEPTH
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
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);
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);
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
774 bounding_box_reset_to_vector(&result,v);
780 bounding_box_add_vector(&result,v);
791- (
OOMesh *)meshRescaledBy:(GLfloat)scaleFactor
793 OOMesh *result = [
self mutableCopy];
795 return [
result autorelease];
799- (void)setBindingTarget:(
id<OOWeakReferenceSupport>)target
844 result +=
_displayLists.count * (
sizeof (GLint) +
sizeof (GLfloat) +
sizeof (Vector) * 3);
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;
890 _cacheWriteable = cacheWriteable;
896 if ([
self loadData:name scaleFactor:scale])
899 PROFILE(
@"finished calculateBoundingVolumes (again\?\?)");
901 baseFile = [
name copy];
902 baseFileOctreeCacheRef = [[
NSString stringWithFormat:@"%@-%.3f", baseFile, scale] copy];
911 _shaderMacros = [
macros copy];
912 _shaderBindingTarget = [
target weakRetain];
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];
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];
982 OOGL(glDeleteLists(displayList0, materialCount));
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];
1023 if (materialCount != 0)
1025 mtlKeys = [
NSArray arrayWithObjects:materialKeys count:materialCount];
1031 normMode = [
NSNumber numberWithUnsignedChar:_normalMode];
1034 if (vertCnt ==
nil ||
1046 if (normData ==
nil || tanData ==
nil)
return nil;
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];
1132 _normals = (Vector *)[normData bytes];
1134 _tangents = (Vector *)[tanData bytes];
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)
1201 newlineCharSet = [
temp copy];
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];
1247 PROFILE(
@"finished preprocessing");
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];
1448 _faces[
j].materialIndex = [
index unsignedIntValue];
1457 _faces[
j].materialIndex = materialCount;
1459 index = [
NSNumber numberWithUnsignedInt:materialCount];
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"];
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"];
1595 PROFILE(
@"finished checkNormalsAndAdjustWinding");
1597 if (!explicitTangents)
1600 PROFILE(
@"finished generateFaceTangents");
1606 if (![
self allocateNormalBuffersWithCount:vertexCount])
1612 PROFILE(
@"finished calculateVertexNormalsAndTangents");
1618 PROFILE(
@"finished calculateVertexTangents");
1622 if (
EXPECT(_cacheWriteable))
1630 OOLog(
@"mesh.error",
@"%@ ..... from %@ %@", failString,
filename, (using_preloaded)?
@"(from preloaded data)" :
@"(from file)");
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);
1753 NSParameterAssert(faceRefs != NULL);
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));
1812 NSParameterAssert(faceRefs != NULL);
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;
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])
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;
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);
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
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];
2156- (BOOL) allocateVertexBuffersWithCount:(NSUInteger)count
2159 return _vertices != NULL;
2163- (BOOL) allocateNormalBuffersWithCount:(NSUInteger)count
2167 return _normals != NULL && _tangents != NULL;
2171- (BOOL) allocateFaceBuffersWithCount:(NSUInteger)count
2174 return _faces != NULL;
2178- (BOOL) allocateVertexArrayBuffersWithCount:(NSUInteger)count
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])
2206 materialKeys[
i] = [
to copy];
2216@implementation OOCacheManager (OOMesh)
2218+ (NSDictionary *)meshDataForName:(NSString *)inShipName
2224+ (void)setMeshData:(NSDictionary *)inData forName:(NSString *)inShipName
2226 if (inData !=
nil && inShipName !=
nil)
2237@implementation OOCacheManager (Octree)
2241 NSDictionary *dict =
nil;
2244 if (inKey ==
nil)
return nil;
2249 result = [[
Octree alloc] initWithDictionary:dict];
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));
2295 else return [
vfr->extra oo_unsignedIntegerAtIndex:index - vfr->internCount];
#define NO_DRAW_DISTANCE_FACTOR
void OODebugEndWireframe(OODebugWFState state)
OODebugWFState OODebugBeginWireframe(BOOL ignoreZ)
void OOStandardsError(NSString *message)
#define OOJS_PROFILE_EXIT
#define OOJS_PROFILE_EXIT_VOID
#define OOJS_PROFILE_ENTER
#define OOLogWARN(class, format,...)
NSString *const kOOLogException
#define OOLog(class, format,...)
NSString *const kOOLogAllocationFailure
#define OO_ENTER_OPENGL()
bool OOMatrixEqual(OOMatrix a, OOMatrix b)
Vector OOVectorMultiplyMatrix(Vector v, OOMatrix m)
const OOMatrix kZeroMatrix
uint16_t OOMeshSmoothGroup
uint32_t OOMeshVertexCount
uint8_t OOMeshMaterialIndex
uint8_t OOMeshMaterialCount
static void VFRAddFace(VertexFaceRef *vfr, NSUInteger index)
static NSUInteger VFRGetCount(VertexFaceRef *vfr)
static BOOL IsLegacyNormalMode(OOMeshNormalMode mode)
static NSString *const kOOLogMeshTooManyMaterials
static NSString *const kOOCacheOctrees
static NSString *const kOOLogMeshDataNotFound
static BOOL IsPerVertexNormalMode(OOMeshNormalMode mode)
@ kOctreeSmallSizeThreshold
#define Scribble(bytes, size)
static NSUInteger VFRGetFaceAtIndex(VertexFaceRef *vfr, NSUInteger index)
@ kVertexFaceDefInternalCount
static NSString *const kOOCacheMeshes
#define OOVerifyOpenGLState()
BOOL OOCheckOpenGLErrors(NSString *format,...)
#define OOSetOpenGLState(STATE)
const BoundingBox kZeroBoundingBox
const Vector kBasisZVector
const Vector kBasisXVector
static void VFRAddFace(VertexFaceRef *vfr, NSUInteger index)
static NSUInteger VFRGetFaceAtIndex(VertexFaceRef *vfr, NSUInteger index)
static NSUInteger VFRGetCount(VertexFaceRef *vfr)
void deleteDisplayLists()
void generateFaceTangents()
void checkNormalsAndAdjustWinding()
void resetGraphicsState()
static float FaceAreaCorrect(GLuint *vertIndices, Vector *vertices)
NSDictionary * modelData()
BoundingBox boundingBox()
void calculateBoundingVolumes()
static float FaceArea(GLuint *vertIndices, Vector *vertices)
void setObject:forKey:inCache:(id inElement,[forKey] NSString *inKey,[inCache] NSString *inCacheKey)
void setMeshData:forName:(NSDictionary *inData,[forName] NSString *inShipName)
void setOctree:forModel:(Octree *inOctree,[forModel] NSString *inKey)
NSDictionary * meshDataForName:(NSString *inShipName)
id objectForKey:inCache:(NSString *inKey,[inCache] NSString *inCacheKey)
Octree * octreeForModel:(NSString *inKey)
OOCacheManager * sharedCache()
void registerClient:(id< OOGraphicsResetClient > client)
void unregisterClient:(id< OOGraphicsResetClient > client)
OOGraphicsResetManager * sharedManager()
void ensureFinishedLoading()
OOMaterial * materialWithName:cacheKey:materialDictionary:shadersDictionary:macros:bindingTarget:forSmoothedMesh:(NSString *name,[cacheKey] NSString *cacheKey,[materialDictionary] NSDictionary *materialDict,[shadersDictionary] NSDictionary *shadersDict,[macros] NSDictionary *macros,[bindingTarget] id< OOWeakReferenceSupport > object,[forSmoothedMesh] BOOL smooth)
void setBindingTarget:(id< OOWeakReferenceSupport > target)
BOOL wantsNormalsAsTextureCoordinates()
Octree * findOctreeToDepth:(NSUInteger depth)
void addTriangle:(Triangle tri)
instancetype converterWithCapacity:(NSUInteger capacity)
void deleteDisplayLists()
NSString * descriptionComponents()
static NSString * NormalModeDescription(OOMeshNormalMode mode)
NSMutableDictionary * _retainedObjects
NSDictionary * _shaderMacros
OOMaterial * placeholderMaterial()
OOMaterial * materials[kOOMeshMaxMaterials]
NSString * materialKeys[kOOMeshMaxMaterials]
void setRetainedObject:forKey:(id object,[forKey] NSString *key)
void generateFaceTangents()
void rescaleByFactor:(GLfloat factor)
OOMeshMaterialCount materialCount
NSRange triangle_range[kOOMeshMaxMaterials]
void checkNormalsAndAdjustWinding()
NSDictionary * modelData()
BoundingBox _lastBoundingBox
void renameTexturesFrom:to:(NSString *from,[to] NSString *to)
NSDictionary * _materialDict
NSDictionary * _shadersDict
NSString * baseFileOctreeCacheRef
void calculateVertexTangentsWithFaceRefs:(VertexFaceRef *faceRefs)
OOMeshVertexCount vertexCount
void calculateBoundingVolumes()
OOMeshDisplayLists _displayLists
BOOL suppressClangStuff()
void calculateVertexNormalsAndTangentsWithFaceRefs:(VertexFaceRef *faceRefs)
void * allocateBytesWithSize:count:key:(size_t size,[count] NSUInteger count,[key] NSString *key)
id mutableCopyWithZone:(NSZone *zone)
OOMeshFaceCount faceCount
void getNormal:andTangent:forVertex:inSmoothGroup:(Vector *outNormal,[andTangent] Vector *outTangent,[forVertex] OOMeshVertexCount v_index,[inSmoothGroup] OOMeshSmoothGroup smoothGroup)
OOTimeDelta currentTime()
NSDictionary * dictionaryRepresentation()
NSDictionary * materialDefaults()
NSString * stringFromFilesNamed:inFolder:cache:(NSString *fileName,[inFolder] NSString *folderName,[cache] BOOL useCache)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
uint16_t internFaces[kVertexFaceDefInternalCount]