Oolite 1.91.0.7645-241119-222d325
Loading...
Searching...
No Matches
OOMesh Class Reference

#include <OOMesh.h>

+ Inheritance diagram for OOMesh:
+ Collaboration diagram for OOMesh:

Instance Methods

(NSString *) - modelName
 
(void) - rebindMaterials
 
(NSDictionary *) - materials
 
(NSDictionary *) - shaders
 
(size_t) - vertexCount
 
(size_t) - faceCount
 
(Octree *) - octree
 
(BoundingBox) - findBoundingBoxRelativeToPosition:basis:ri:rj:selfPosition:selfBasis:si:sj:
 
(BoundingBox) - findSubentityBoundingBoxWithPosition:rotMatrix:
 
(OOMesh *) - meshRescaledBy:
 
(id) - init [implementation]
 
(void) - dealloc [implementation]
 
(NSString *) - descriptionComponents [implementation]
 
(id) - copyWithZone: [implementation]
 
(void) - renderOpaqueParts [implementation]
 
(BOOL) - hasOpaqueParts [implementation]
 
(unsigned) - octreeDepth [implementation]
 
(void) - setBindingTarget: [implementation]
 
(void) - dumpSelfState [implementation]
 
(NSSet *) - allTextures [implementation]
 
(size_t) - totalSize [implementation]
 
(BOOL) - suppressClangStuff [implementation]
 
(id) - initWithName:cacheKey:materialDictionary:shadersDictionary:smooth:shaderMacros:shaderBindingTarget:scaleFactor:cacheWriteable: [implementation]
 
(BOOL) - loadData:scaleFactor: [implementation]
 
(void) - checkNormalsAndAdjustWinding [implementation]
 
(void) - generateFaceTangents [implementation]
 
(void) - calculateVertexNormalsAndTangentsWithFaceRefs: [implementation]
 
(void) - calculateVertexTangentsWithFaceRefs: [implementation]
 
(void) - deleteDisplayLists [implementation]
 
(NSDictionary *) - modelData [implementation]
 
(BOOL) - setModelFromModelData:name: [implementation]
 
(void) - getNormal:andTangent:forVertex:inSmoothGroup: [implementation]
 
(BOOL) - setUpVertexArrays [implementation]
 
(void) - calculateBoundingVolumes [implementation]
 
(void) - rescaleByFactor: [implementation]
 
(void) - debugDrawNormals [implementation]
 
(void) - setRetainedObject:forKey: [implementation]
 
(void *) - allocateBytesWithSize:count:key: [implementation]
 
(BOOL) - allocateVertexBuffersWithCount: [implementation]
 
(BOOL) - allocateNormalBuffersWithCount: [implementation]
 
(BOOL) - allocateFaceBuffersWithCount: [implementation]
 
(BOOL) - allocateVertexArrayBuffersWithCount: [implementation]
 
(void) - renameTexturesFrom:to: [implementation]
 
(id) - mutableCopyWithZone: [implementation]
 
(void) - resetGraphicsState [implementation]
 
- Instance Methods inherited from OODrawable
(void) - renderTranslucentParts
 
(BOOL) - hasTranslucentParts
 
(GLfloat) - collisionRadius
 
(GLfloat) - maxDrawDistance
 
(BoundingBox) - boundingBox
 

Class Methods

(instancetype) + meshWithName:cacheKey:materialDictionary:shadersDictionary:smooth:shaderMacros:shaderBindingTarget:
 
(instancetype) + meshWithName:cacheKey:materialDictionary:shadersDictionary:smooth:shaderMacros:shaderBindingTarget:scaleFactor:cacheWriteable:
 
(OOMaterial *) + placeholderMaterial
 
(static NSString *) + NormalModeDescription [implementation]
 
(static float) + FaceArea [implementation]
 
(static float) + FaceAreaCorrect [implementation]
 

Private Attributes

uint8_t _normalMode: 2
 
uint8_t brokenInRender: 1
 
uint8_t listsReady: 1
 
OOMeshMaterialCount materialCount
 
OOMeshVertexCount vertexCount
 
OOMeshFaceCount faceCount
 
NSString * baseFile
 
NSString * baseFileOctreeCacheRef
 
BOOL _cacheWriteable
 
Vector * _vertices
 
Vector * _normals
 
Vector * _tangents
 
OOMeshFace_faces
 
OOMeshDisplayLists _displayLists
 
NSRange triangle_range [kOOMeshMaxMaterials]
 
NSString * materialKeys [kOOMeshMaxMaterials]
 
OOMaterialmaterials [kOOMeshMaxMaterials]
 
GLuint displayList0
 
GLfloat collisionRadius
 
GLfloat maxDrawDistance
 
BoundingBox boundingBox
 
Octreeoctree
 
NSMutableDictionary * _retainedObjects
 
NSDictionary * _materialDict
 
NSDictionary * _shadersDict
 
NSString * _cacheKey
 
NSDictionary * _shaderMacros
 
id _shaderBindingTarget
 
Vector _lastPosition
 
OOMatrix _lastRotMatrix
 
BoundingBox _lastBoundingBox
 

Detailed Description

Definition at line 89 of file OOMesh.h.

Method Documentation

◆ allocateBytesWithSize:count:key:

- (void *) allocateBytesWithSize: (size_t) size
count: (NSUInteger) count
key: (NSString *) key 
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

2141 :(size_t)size count:(NSUInteger)count key:(NSString *)key
2142{
2143 if (count == 0) { count=1; }
2144 size *= count;
2145 void *bytes = malloc(size);
2146 if (bytes != NULL)
2147 {
2148 Scribble(bytes, size);
2149 NSData *holder = [NSData dataWithBytesNoCopy:bytes length:size freeWhenDone:YES];
2150 [self setRetainedObject:holder forKey:key];
2151 }
2152 return bytes;
2153}
#define Scribble(bytes, size)
Definition OOMesh.m:2134
unsigned count
voidpf void uLong size
Definition ioapi.h:134

◆ allocateFaceBuffersWithCount:

- (BOOL) allocateFaceBuffersWithCount: (NSUInteger) count
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

2171 :(NSUInteger)count
2172{
2173 _faces = [self allocateBytesWithSize:sizeof *_faces count:faceCount key:@"faces"];
2174 return _faces != NULL;
2175}

◆ allocateNormalBuffersWithCount:

- (BOOL) allocateNormalBuffersWithCount: (NSUInteger) count
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

2163 :(NSUInteger)count
2164{
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;
2168}

◆ allocateVertexArrayBuffersWithCount:

- (BOOL) allocateVertexArrayBuffersWithCount: (NSUInteger) count
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

2178 :(NSUInteger)count
2179{
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"];
2185
2186 return _faces != NULL &&
2187 _displayLists.indexArray != NULL &&
2188 _displayLists.textureUVArray != NULL &&
2189 _displayLists.vertexArray != NULL &&
2190 _displayLists.normalArray != NULL &&
2191 _displayLists.tangentArray != NULL;
2192}

◆ allocateVertexBuffersWithCount:

- (BOOL) allocateVertexBuffersWithCount: (NSUInteger) count
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

2156 :(NSUInteger)count
2157{
2158 _vertices = [self allocateBytesWithSize:sizeof *_vertices count:vertexCount key:@"vertices"];
2159 return _vertices != NULL;
2160}

◆ allTextures

- (NSSet *) allTextures
implementation

Reimplemented from OODrawable.

Definition at line 341 of file OOMesh.m.

824{
825 NSMutableSet *result = [NSMutableSet set];
827 for (i = 0; i != materialCount; i++)
828 {
829 [result unionSet:[materials[i] allTextures]];
830 }
831
832 return result;
833}
uint8_t OOMeshMaterialCount
Definition OOMesh.h:58
OOMeshMaterialCount materialCount
Definition OOMesh.h:97

References kNormalModeExplicit, kNormalModePerFace, and kNormalModeSmooth.

◆ calculateBoundingVolumes

- (void) calculateBoundingVolumes
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

1983{
1985
1987 float d_squared, length_longest_axis, length_shortest_axis;
1988 GLfloat result;
1989
1990 result = 0.0f;
1991 if (vertexCount) bounding_box_reset_to_vector(&boundingBox, _vertices[0]);
1992 else bounding_box_reset(&boundingBox);
1993
1994 for (i = 0; i < vertexCount; i++)
1995 {
1996 d_squared = magnitude2(_vertices[i]);
1997 if (d_squared > result) result = d_squared;
1998 bounding_box_add_vector(&boundingBox, _vertices[i]);
1999 }
2000
2001 length_longest_axis = boundingBox.max.x - boundingBox.min.x;
2002 if (boundingBox.max.y - boundingBox.min.y > length_longest_axis)
2003 length_longest_axis = boundingBox.max.y - boundingBox.min.y;
2004 if (boundingBox.max.z - boundingBox.min.z > length_longest_axis)
2005 length_longest_axis = boundingBox.max.z - boundingBox.min.z;
2006
2007 length_shortest_axis = boundingBox.max.x - boundingBox.min.x;
2008 if (boundingBox.max.y - boundingBox.min.y < length_shortest_axis)
2009 length_shortest_axis = boundingBox.max.y - boundingBox.min.y;
2010 if (boundingBox.max.z - boundingBox.min.z < length_shortest_axis)
2011 length_shortest_axis = boundingBox.max.z - boundingBox.min.z;
2012
2013 d_squared = (length_longest_axis + length_shortest_axis) * (length_longest_axis + length_shortest_axis) * 0.25; // square of average length
2014 maxDrawDistance = d_squared * NO_DRAW_DISTANCE_FACTOR * NO_DRAW_DISTANCE_FACTOR; // no longer based on the collision radius
2015
2016 collisionRadius = sqrtf(result);
2017
2019}
#define NO_DRAW_DISTANCE_FACTOR
Definition Entity.h:46
#define OOJS_PROFILE_EXIT_VOID
#define OOJS_PROFILE_ENTER
uint32_t OOMeshVertexCount
Definition OOMesh.h:59
float x
BoundingBox boundingBox()
Definition OOMesh.m:2048

◆ calculateVertexNormalsAndTangentsWithFaceRefs:

- (void) calculateVertexNormalsAndTangentsWithFaceRefs: (VertexFaceRef *) faceRefs
implementation

Provided by category OOMesh(Private).

Definition at line 1739 of file OOMesh.m.

1749 :(VertexFaceRef *)faceRefs
1750{
1752
1753 NSParameterAssert(faceRefs != NULL);
1754
1755 NSUInteger i,j;
1756 float triangle_area[faceCount];
1757
1758 NSAssert1(_normals != NULL && _tangents != NULL, @"Normal/tangent buffers not allocated in %s", __PRETTY_FUNCTION__);
1759
1760 for (i = 0 ; i < faceCount; i++)
1761 {
1762 triangle_area[i] = FaceArea(_faces[i].vertex, _vertices);
1763 }
1764 for (i = 0; i < vertexCount; i++)
1765 {
1766 Vector normal_sum = kZeroVector;
1767 Vector tangent_sum = kZeroVector;
1768
1769 VertexFaceRef *vfr = &faceRefs[i];
1770 NSUInteger fIter, fCount = VFRGetCount(vfr);
1771 for (fIter = 0; fIter < fCount; fIter++)
1772 {
1773 j = VFRGetFaceAtIndex(vfr, fIter);
1774
1775 float t = triangle_area[j]; // weight sum by area
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));
1778 }
1779
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);
1783
1784 _normals[i] = normal_sum;
1785 _tangents[i] = tangent_sum;
1786 }
1787
1789}
static NSUInteger VFRGetCount(VertexFaceRef *vfr)
static NSUInteger VFRGetFaceAtIndex(VertexFaceRef *vfr, NSUInteger index)
const Vector kZeroVector
Definition OOVector.m:28
const Vector kBasisZVector
Definition OOVector.m:31
const Vector kBasisXVector
Definition OOVector.m:29
static float FaceArea(GLuint *vertIndices, Vector *vertices)
Definition OOMesh.m:1739

◆ calculateVertexTangentsWithFaceRefs:

- (void) calculateVertexTangentsWithFaceRefs: (VertexFaceRef *) faceRefs
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

1808 :(VertexFaceRef *)faceRefs
1809{
1811
1812 NSParameterAssert(faceRefs != NULL);
1813
1814 /* This is conceptually broken.
1815 At the moment, it's calculating one tangent per "input" vertex. It should
1816 be calculating one tangent per "real" vertex, where a "real" vertex is
1817 defined as a combination of position, normal, material and texture
1818 coordinates.
1819 Currently, we don't have a format with unique "real" vertices.
1820 This basically means explicit-normal models without explicit tangents
1821 can't usefully be normal mapped.
1822 I don't intend to do anything about this pre-MSNR, although it might be
1823 possible to fix it by moving tangent generation to the same stage as
1824 smooth-grouped normal generation.
1825 -- Ahruman 2010-05-22
1826 */
1827 NSUInteger i,j;
1828 float triangle_area[faceCount];
1829 for (i = 0 ; i < faceCount; i++)
1830 {
1831 triangle_area[i] = FaceAreaCorrect(_faces[i].vertex, _vertices);
1832 }
1833 for (i = 0; i < vertexCount; i++)
1834 {
1835 Vector tangent_sum = kZeroVector;
1836
1837 VertexFaceRef *vfr = &faceRefs[i];
1838 NSUInteger fIter, fCount = VFRGetCount(vfr);
1839 for (fIter = 0; fIter < fCount; fIter++)
1840 {
1841 j = VFRGetFaceAtIndex(vfr, fIter);
1842
1843 float t = triangle_area[j]; // weight sum by area
1844 tangent_sum = vector_add(tangent_sum, vector_multiply_scalar(_faces[j].tangent, t));
1845 }
1846
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);
1849
1850 _tangents[i] = tangent_sum;
1851 }
1852
1854}
static float FaceAreaCorrect(GLuint *vertIndices, Vector *vertices)
Definition OOMesh.m:1792

◆ checkNormalsAndAdjustWinding

- (void) checkNormalsAndAdjustWinding
implementation

Provided by category OOMesh(Private).

Definition at line 341 of file OOMesh.m.

1648{
1650
1651 Vector calculatedNormal;
1653
1654 NSParameterAssert(_normalMode != kNormalModeExplicit);
1655
1656 for (i = 0; i < faceCount; i++)
1657 {
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;
1663
1664 calculatedNormal = normal_to_surface(v2, v1, v0);
1665 if (vector_equal(norm, kZeroVector))
1666 {
1667 norm = vector_flip(calculatedNormal);
1668 _faces[i].normal = norm;
1669 }
1670
1671 /* FIXME: for 2.0, either require explicit normals for every model
1672 or change to: if (dot_product(norm, calculatedNormal) < 0.0f)
1673 -- Ahruman 2010-01-23
1674 */
1675 if (norm.x * calculatedNormal.x < 0 || norm.y * calculatedNormal.y < 0 || norm.z * calculatedNormal.z < 0)
1676 {
1677 // normal lies in the WRONG direction!
1678 // reverse the winding
1679 int v0 = _faces[i].vertex[0];
1680 _faces[i].vertex[0] = _faces[i].vertex[2];
1681 _faces[i].vertex[2] = v0;
1682
1683 GLfloat f0 = _faces[i].s[0];
1684 _faces[i].s[0] = _faces[i].s[2];
1685 _faces[i].s[2] = f0;
1686
1687 f0 = _faces[i].t[0];
1688 _faces[i].t[0] = _faces[i].t[2];
1689 _faces[i].t[2] = f0;
1690 }
1691 }
1692
1694}
uint32_t OOMeshFaceCount
Definition OOMesh.h:60
@ kNormalModeExplicit
Definition OOMesh.m:80

◆ copyWithZone:

- (id) copyWithZone: (NSZone *) zone
implementation

Definition at line 341 of file OOMesh.m.

360 :(NSZone *)zone
361{
362 if (zone == [self zone]) return [self retain]; // OK because we're immutable seen from the outside
363 else return [self mutableCopyWithZone:zone];
364}

◆ dealloc

- (void) dealloc
implementation

Definition at line 121 of file OOMesh.m.

308{
309 unsigned i;
310
314
315 [self deleteDisplayLists];
316
317 for (i = 0; i != kOOMeshMaxMaterials; ++i)
318 {
319 DESTROY(materials[i]);
321 }
322
324
326
332
333#if OOMESH_PROFILE
334 DESTROY(_stopwatch);
335#endif
336
337 [super dealloc];
338}
#define DESTROY(x)
Definition OOCocoa.h:77
@ kOOMeshMaxMaterials
Definition OOMesh.h:53
void unregisterClient:(id< OOGraphicsResetClient > client)
OOGraphicsResetManager * sharedManager()
NSMutableDictionary * _retainedObjects
Definition OOMesh.h:124
NSDictionary * _shaderMacros
Definition OOMesh.h:129
OOMaterial * materials[kOOMeshMaxMaterials]
Definition OOMesh.h:115
id _shaderBindingTarget
Definition OOMesh.h:130
NSString * materialKeys[kOOMeshMaxMaterials]
Definition OOMesh.h:114
Octree * octree
Definition OOMesh.h:122
NSString * _cacheKey
Definition OOMesh.h:128
NSDictionary * _materialDict
Definition OOMesh.h:126
NSDictionary * _shadersDict
Definition OOMesh.h:127
NSString * baseFileOctreeCacheRef
Definition OOMesh.h:102
NSString * baseFile
Definition OOMesh.h:101

◆ debugDrawNormals

- (void) debugDrawNormals
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

2056{
2057 GLuint i;
2058 Vector v, n, t, b;
2059 float length, blend;
2060 GLfloat color[3];
2061 OODebugWFState state;
2062
2064
2065 state = OODebugBeginWireframe(NO);
2066
2067 // Draw
2068 OOGLBEGIN(GL_LINES);
2069 for (i = 0; i < _displayLists.count; ++i)
2070 {
2071 v = _displayLists.vertexArray[i];
2072 n = _displayLists.normalArray[i];
2073 t = _displayLists.tangentArray[i];
2074 b = true_cross_product(n, t);
2075
2076 // Draw normal
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];
2082 glColor3fv(color);
2083
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);
2088
2089 // Draw tangent
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);
2094
2095 // Draw bitangent
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);
2100 }
2101 OOGLEND();
2102
2103 OODebugEndWireframe(state);
2104}
void OODebugEndWireframe(OODebugWFState state)
OODebugWFState OODebugBeginWireframe(BOOL ignoreZ)
#define OO_ENTER_OPENGL()
#define MIN(A, B)
Definition OOMaths.h:111
#define OOGLBEGIN
Definition OOOpenGL.h:253
#define OOGLEND
Definition OOOpenGL.h:254

◆ deleteDisplayLists

- (void) deleteDisplayLists
implementation

Provided by category OOMesh(Private).

Definition at line 341 of file OOMesh.m.

977{
978 if (listsReady)
979 {
981
982 OOGL(glDeleteLists(displayList0, materialCount));
983 listsReady = NO;
984 }
985}
#define OOGL(statement)
Definition OOOpenGL.h:251

◆ descriptionComponents

- (NSString *) descriptionComponents
implementation

Definition at line 341 of file OOMesh.m.

355{
356 return [NSString stringWithFormat:@"\"%@\", %zu vertices, %zu faces, radius: %g m normals: %@", [self modelName], [self vertexCount], [self faceCount], [self collisionRadius], NormalModeDescription(_normalMode)];
357}

◆ dumpSelfState

- (void) dumpSelfState
implementation

Reimplemented from OODrawable.

Definition at line 341 of file OOMesh.m.

812{
813 [super dumpSelfState];
814
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));
818}
#define OOLog(class, format,...)
Definition OOLogging.h:88
return nil
static NSString * NormalModeDescription(OOMeshNormalMode mode)
Definition OOMesh.m:341
uint8_t _normalMode
Definition OOMesh.h:93
OOMeshVertexCount vertexCount
Definition OOMesh.h:98
OOMeshFaceCount faceCount
Definition OOMesh.h:99

◆ FaceArea

+ (static float) FaceArea (GLuint *) vertIndices
(Vector *) vertices 
implementation

Provided by category OOMesh(Private).

Definition at line 1739 of file OOMesh.m.

1740{
1741 /* Calculate areas using Heron's formula. */
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);
1746}

◆ FaceAreaCorrect

+ (static float) FaceAreaCorrect (GLuint *) vertIndices
(Vector *) vertices 
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

1793{
1794 /* Calculate area of triangle.
1795 The magnitude of the cross product of two vectors is the area of
1796 the parallelogram they span. The area of a triangle is half the
1797 area of a parallelogram sharing two of its sides.
1798 Since we only use the area of the triangle as a weight factor,
1799 constant terms are irrelevant, so we don't bother halving the
1800 value.
1801 */
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));
1805}

◆ faceCount

- (size_t) faceCount

◆ findBoundingBoxRelativeToPosition:basis:ri:rj:selfPosition:selfBasis:si:sj:

- (BoundingBox) findBoundingBoxRelativeToPosition: (Vector) opv
basis: (Vector)
ri: (Vector)
rj: (Vector) rk
selfPosition: (Vector) position
selfBasis: (Vector)
si: (Vector)
sj: (Vector) sk 

Definition at line 341 of file OOMesh.m.

712 :(Vector)opv
713 basis:(Vector)ri :(Vector)rj :(Vector)rk
714 selfPosition:(Vector)position
715 selfBasis:(Vector)si :(Vector)sj :(Vector)sk
716{
717 BoundingBox result;
718 Vector pv, rv;
719
720 // FIXME: rewrite with matrices
721 Vector rpos = vector_subtract(position, opv); // model origin relative to opv
722
723 rv.x = dot_product(ri,rpos);
724 rv.y = dot_product(rj,rpos);
725 rv.z = dot_product(rk,rpos); // model origin rel to opv in ijk
726
727 if (EXPECT_NOT(vertexCount < 1))
728 {
729 bounding_box_reset_to_vector(&result, rv);
730 }
731 else
732 {
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; // _vertices[0] position rel to opv
736 rv.x = dot_product(ri, pv);
737 rv.y = dot_product(rj, pv);
738 rv.z = dot_product(rk, pv); // _vertices[0] position rel to opv in ijk
739 bounding_box_reset_to_vector(&result, rv);
740 }
741
743 for (i = 1; i < vertexCount; i++)
744 {
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);
752 }
753
754 return result;
755}
#define EXPECT_NOT(x)
float y
Vector * _vertices
Definition OOMesh.h:105

◆ findSubentityBoundingBoxWithPosition:rotMatrix:

- (BoundingBox) findSubentityBoundingBoxWithPosition: (Vector) position
rotMatrix: (OOMatrix) rotMatrix 

Definition at line 341 of file OOMesh.m.

758 :(Vector)position rotMatrix:(OOMatrix)rotMatrix
759{
760 // HACK! Should work out what the various bounding box things do and make it neat and consistent.
761 // FIXME: this is a bottleneck.
762// Try to fix bottleneck by caching for common case where subentity
763// pos+rot is constant from frame to frame. - CIM
764
765 if (vector_equal(position,_lastPosition) && OOMatrixEqual(rotMatrix,_lastRotMatrix))
766 {
767 return _lastBoundingBox;
768 }
769
770 BoundingBox result;
771 Vector v;
772
773 v = vector_add(position, OOVectorMultiplyMatrix(_vertices[0], rotMatrix));
774 bounding_box_reset_to_vector(&result,v);
775
777 for (i = 1; i < vertexCount; i++)
778 {
779 v = vector_add(position, OOVectorMultiplyMatrix(_vertices[i], rotMatrix));
780 bounding_box_add_vector(&result,v);
781 }
782
783 _lastBoundingBox = result;
784 _lastPosition = position;
785 _lastRotMatrix = rotMatrix;
786
787 return result;
788}
bool OOMatrixEqual(OOMatrix a, OOMatrix b)
Definition OOMatrix.m:96
Vector OOVectorMultiplyMatrix(Vector v, OOMatrix m)
Definition OOMatrix.m:129
Vector _lastPosition
Definition OOMesh.h:132
BoundingBox _lastBoundingBox
Definition OOMesh.h:134
OOMatrix _lastRotMatrix
Definition OOMesh.h:133

◆ generateFaceTangents

- (void) generateFaceTangents
implementation

Provided by category OOMesh(Private).

Definition at line 341 of file OOMesh.m.

1698{
1700
1702 for (i = 0; i < faceCount; i++)
1703 {
1704 OOMeshFace *face = _faces + i;
1705
1706 /* Generate tangents, i.e. vectors that run in the direction of the s
1707 texture coordinate. Based on code I found in a forum somewhere and
1708 then lost track of. Sorry to whomever I should be crediting.
1709 -- Ahruman 2008-11-23
1710 */
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;
1714
1715 // projAB = aB - (nA . vAB) * nA
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)));
1718
1719 // delta s/t
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];
1724
1725 if (dsAC * dtAB > dsAB * dtAC)
1726 {
1727 face->tangent = vector_normal(vector_subtract(vector_multiply_scalar(vProjAC, dtAB), vector_multiply_scalar(vProjAB, dtAC)));
1728 }
1729 else
1730 {
1731 face->tangent = vector_normal(vector_subtract(vector_multiply_scalar(vProjAB, dtAC), vector_multiply_scalar(vProjAC, dtAB)));
1732 }
1733 }
1734
1736}
Vector tangent
Definition OOMesh.h:71
GLuint vertex[3]
Definition OOMesh.h:68
Vector normal
Definition OOMesh.h:70
GLfloat t[3]
Definition OOMesh.h:73
GLfloat s[3]
Definition OOMesh.h:72

◆ getNormal:andTangent:forVertex:inSmoothGroup:

- (void) getNormal: (Vector *) outNormal
andTangent: (Vector *) outTangent
forVertex: (OOMeshVertexCount) v_index
inSmoothGroup: (OOMeshSmoothGroup) smoothGroup 
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

1858 :(Vector *)outNormal andTangent:(Vector *)outTangent forVertex:(OOMeshVertexCount)v_index inSmoothGroup:(OOMeshSmoothGroup)smoothGroup
1859{
1861
1862 assert(outNormal != NULL && outTangent != NULL);
1863
1864 NSUInteger j;
1865 Vector normal_sum = kZeroVector;
1866 Vector tangent_sum = kZeroVector;
1867 for (j = 0; j < faceCount; j++)
1868 {
1869 if (_faces[j].smoothGroup == smoothGroup)
1870 {
1871 if ((_faces[j].vertex[0] == v_index)||(_faces[j].vertex[1] == v_index)||(_faces[j].vertex[2] == v_index))
1872 {
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));
1876 }
1877 }
1878 }
1879
1880 *outNormal = vector_normal_or_fallback(normal_sum, kBasisZVector);
1881 *outTangent = vector_normal_or_fallback(tangent_sum, kBasisXVector);
1882
1884}
uint16_t OOMeshSmoothGroup
Definition OOMesh.h:57

◆ hasOpaqueParts

- (BOOL) hasOpaqueParts
implementation

Reimplemented from OODrawable.

Definition at line 341 of file OOMesh.m.

624{
625 return YES;
626}

◆ init

- (id) init
implementation

Definition at line 121 of file OOMesh.m.

288{
289 self = [super init];
290 if (self == nil) return nil;
291
292 baseFile = @"No Model";
293 baseFileOctreeCacheRef = @"No Model-0.000";
294 _cacheWriteable = YES;
295#if OO_MULTITEXTURE
296 _textureUnitCount = NSNotFound;
297#endif
298
300 _lastRotMatrix = kZeroMatrix; // not identity
302
303 return self;
304}
const OOMatrix kZeroMatrix
Definition OOMatrix.m:38
const BoundingBox kZeroBoundingBox
Definition OOVector.m:38
BOOL _cacheWriteable
Definition OOMesh.h:103

◆ initWithName:cacheKey:materialDictionary:shadersDictionary:smooth:shaderMacros:shaderBindingTarget:scaleFactor:cacheWriteable:

- (id) initWithName: (NSString *) name
cacheKey: (NSString *) cacheKey
materialDictionary: (NSDictionary *) materialDict
shadersDictionary: (NSDictionary *) shadersDict
smooth: (BOOL) smooth
shaderMacros: (NSDictionary *) macros
shaderBindingTarget: (id<OOWeakReferenceSupport>) object
scaleFactor: (float) scale
cacheWriteable: (BOOL) cacheWriteable 
implementation

Provided by category OOMesh(Private).

Definition at line 341 of file OOMesh.m.

873 :(NSString *)name
874 cacheKey:(NSString *)cacheKey
875materialDictionary:(NSDictionary *)materialDict
876 shadersDictionary:(NSDictionary *)shadersDict
877 smooth:(BOOL)smooth
878 shaderMacros:(NSDictionary *)macros
879shaderBindingTarget:(id<OOWeakReferenceSupport>)target
880 scaleFactor:(float)scale
881 cacheWriteable:(BOOL)cacheWriteable
882{
884
885 self = [super init];
886 if (self == nil) return nil;
887
888 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
889 _normalMode = smooth ? kNormalModeSmooth : kNormalModePerFace;
890 _cacheWriteable = cacheWriteable;
891
892#if OOMESH_PROFILE
893 _stopwatch = [[OOProfilingStopwatch alloc] init];
894#endif
895
896 if ([self loadData:name scaleFactor:scale])
897 {
898 [self calculateBoundingVolumes];
899 PROFILE(@"finished calculateBoundingVolumes (again\?\?)");
900
901 baseFile = [name copy];
902 baseFileOctreeCacheRef = [[NSString stringWithFormat:@"%@-%.3f", baseFile, scale] copy];
903
904 /* New in r3033: save the material-defining parameters here so we
905 can rebind the materials at any time.
906 -- Ahruman 2010-02-17
907 */
908 _materialDict = [materialDict copy];
909 _shadersDict = [shadersDict copy];
910 _cacheKey = [cacheKey copy];
911 _shaderMacros = [macros copy];
912 _shaderBindingTarget = [target weakRetain];
913
914 [self rebindMaterials];
915 PROFILE(@"finished material setup");
916
918 }
919 else
920 {
921 [self release];
922 self = nil;
923 }
924#if OOMESH_PROFILE
925 DESTROY(_stopwatch);
926#endif
927#if OO_MULTITEXTURE
928 if (EXPECT(self != nil))
929 {
930 _textureUnitCount = NSNotFound;
931 }
932#endif
933
934 [pool release];
935 return self;
936
938}
#define EXPECT(x)
#define OOJS_PROFILE_EXIT
#define PROFILE(tag)
Definition OOMesh.m:97
@ kNormalModeSmooth
Definition OOMesh.m:79
@ kNormalModePerFace
Definition OOMesh.m:78
void registerClient:(id< OOGraphicsResetClient > client)

◆ loadData:scaleFactor:

- (BOOL) loadData: (NSString *) filename
scaleFactor: (float) scale 
implementation

Provided by category OOMesh(Private).

Definition at line 341 of file OOMesh.m.

1162 :(NSString *)filename scaleFactor:(float)scale
1163{
1165
1166 NSScanner *scanner;
1167 NSDictionary *cacheData = nil;
1168 BOOL failFlag = NO;
1169 NSString *failString = @"***** ";
1170 unsigned i, j;
1171 NSMutableDictionary *texFileName2Idx = nil;
1172 NSString *cacheKey = nil;
1173 BOOL using_preloaded = NO;
1174
1175 cacheKey = [NSString stringWithFormat:@"%@:%u:%.3f", filename, _normalMode, scale];
1176 cacheData = [OOCacheManager meshDataForName:cacheKey];
1177 if (cacheData != nil)
1178 {
1179 if ([self setModelFromModelData:cacheData name:filename])
1180 {
1181 using_preloaded = YES;
1182 PROFILE(@"loaded from cache");
1183 OOLog(@"mesh.load.cached", @"Retrieved mesh \"%@\" from cache.", filename);
1184 }
1185 }
1186
1187 if (!using_preloaded)
1188 {
1189 OOLog(@"mesh.load.uncached", @"Mesh \"%@\" is not in cache, loading.", cacheKey);
1190
1191 NSCharacterSet *whitespaceCharSet = [NSCharacterSet whitespaceCharacterSet];
1192 NSCharacterSet *whitespaceAndNewlineCharSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
1193#if OOLITE_MAC_OS_X
1194 NSCharacterSet *newlineCharSet = [NSCharacterSet newlineCharacterSet];
1195#else
1196 static NSCharacterSet *newlineCharSet = nil;
1197 if (newlineCharSet == nil)
1198 {
1199 NSMutableCharacterSet *temp = [[whitespaceAndNewlineCharSet mutableCopy] autorelease];
1200 [temp formIntersectionWithCharacterSet:[whitespaceCharSet invertedSet]];
1201 newlineCharSet = [temp copy];
1202 }
1203#endif
1204
1205 texFileName2Idx = [NSMutableDictionary dictionary];
1206
1207 {
1208 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
1209 NSString *data = [ResourceManager stringFromFilesNamed:filename inFolder:@"Models" cache:NO];
1210 if (data == nil)
1211 {
1212 // Model not found
1213 OOLog(kOOLogMeshDataNotFound, @"***** ERROR: could not find %@", filename);
1214 OOStandardsError(@"Model file not found");
1215 return NO;
1216 }
1217
1218 // strip out comments and commas between values
1219 NSMutableArray *lines = [NSMutableArray arrayWithArray:[data componentsSeparatedByString:@"\n"]];
1220 for (i = 0; i < [lines count]; i++)
1221 {
1222 NSString *line = [lines objectAtIndex:i];
1223 NSArray *parts;
1224 //
1225 // comments
1226 //
1227 parts = [line componentsSeparatedByString:@"#"];
1228 line = [parts objectAtIndex:0];
1229 parts = [line componentsSeparatedByString:@"//"];
1230 line = [parts objectAtIndex:0];
1231 //
1232 // commas
1233 //
1234 line = [[line componentsSeparatedByString:@","] componentsJoinedByString:@" "];
1235 //
1236 [lines replaceObjectAtIndex:i withObject:line];
1237 }
1238
1239 data = [lines componentsJoinedByString:@"\n"];
1240 scanner = [NSScanner scannerWithString:data];
1241
1242 [scanner retain];
1243 [pool release];
1244 [scanner autorelease];
1245 }
1246
1247 PROFILE(@"finished preprocessing");
1248
1249 // get number of vertices
1250 //
1251 [scanner setScanLocation:0]; //reset
1252 if ([scanner scanString:@"NVERTS" intoString:NULL])
1253 {
1254 int n_v;
1255 if ([scanner scanInt:&n_v])
1256 vertexCount = n_v;
1257 else
1258 {
1259 failFlag = YES;
1260 failString = [NSString stringWithFormat:@"%@Failed to read value of NVERTS\n",failString];
1261 }
1262 }
1263 else
1264 {
1265 failFlag = YES;
1266 failString = [NSString stringWithFormat:@"%@Failed to read NVERTS\n",failString];
1267 }
1268
1269 if (![self allocateVertexBuffersWithCount:vertexCount])
1270 {
1271 OOLog(kOOLogAllocationFailure, @"***** ERROR: failed to allocate memory for model %@ (%u vertices).", filename, vertexCount);
1272 return NO;
1273 }
1274
1275 // get number of faces
1276 if ([scanner scanString:@"NFACES" intoString:NULL])
1277 {
1278 int n_f;
1279 if ([scanner scanInt:&n_f])
1280 {
1281 faceCount = n_f;
1282 }
1283 else
1284 {
1285 failFlag = YES;
1286 failString = [NSString stringWithFormat:@"%@Failed to read value of NFACES\n",failString];
1287 }
1288 }
1289 else
1290 {
1291 failFlag = YES;
1292 failString = [NSString stringWithFormat:@"%@Failed to read NFACES\n",failString];
1293 }
1294
1295 // Allocate face->vertex table.
1296 size_t faceRefSize = sizeof (VertexFaceRef) * vertexCount;
1297 VertexFaceRef *faceRefs = calloc(1, faceRefSize);
1298 if (faceRefs != NULL)
1299 {
1300 // use an NSData to effectively autorelease it.
1301 NSData *faceRefHolder = [NSData dataWithBytesNoCopy:faceRefs length:faceRefSize freeWhenDone:YES];
1302 if (faceRefHolder == nil)
1303 {
1304 free(faceRefs);
1305 faceRefs = NULL;
1306 }
1307 }
1308
1309 if (faceRefs == NULL || ![self allocateFaceBuffersWithCount:faceCount])
1310 {
1311 OOLog(kOOLogAllocationFailure, @"***** ERROR: failed to allocate memory for model %@ (%u vertices, %u faces).", filename, vertexCount, faceCount);
1312 return NO;
1313 }
1314
1315 // get vertex data
1316 if ([scanner scanString:@"VERTEX" intoString:NULL])
1317 {
1318 for (j = 0; j < vertexCount; j++)
1319 {
1320 float x, y, z;
1321 if (!failFlag)
1322 {
1323 if (![scanner scanFloat:&x]) failFlag = YES;
1324 if (![scanner scanFloat:&y]) failFlag = YES;
1325 if (![scanner scanFloat:&z]) failFlag = YES;
1326 if (!failFlag)
1327 {
1328 _vertices[j] = make_vector(x*scale, y*scale, z*scale);
1329 }
1330 else
1331 {
1332 failString = [NSString stringWithFormat:@"%@Failed to read a value for vertex[%d] in %@\n", failString, j, @"VERTEX"];
1333 }
1334 }
1335 }
1336 }
1337 else
1338 {
1339 failFlag = YES;
1340 failString = [NSString stringWithFormat:@"%@Failed to find VERTEX data\n",failString];
1341 }
1342
1343 // get face data
1344 if ([scanner scanString:@"FACES" intoString:NULL])
1345 {
1346 for (j = 0; j < faceCount; j++)
1347 {
1348 int r, g, b;
1349 float nx, ny, nz;
1350 int n_v;
1351 if (!failFlag)
1352 {
1353 // colors
1354 if (![scanner scanInt:&r]) failFlag = YES;
1355 if (![scanner scanInt:&g]) failFlag = YES;
1356 if (![scanner scanInt:&b]) failFlag = YES;
1357 if (!failFlag)
1358 {
1359 _faces[j].smoothGroup = r;
1360 }
1361 else
1362 {
1363 failString = [NSString stringWithFormat:@"%@Failed to read a color for face[%d] in FACES\n", failString, j];
1364 }
1365
1366 // normal
1367 if (![scanner scanFloat:&nx]) failFlag = YES;
1368 if (![scanner scanFloat:&ny]) failFlag = YES;
1369 if (![scanner scanFloat:&nz]) failFlag = YES;
1370 if (!failFlag)
1371 {
1372 _faces[j].normal = vector_normal(make_vector(nx, ny, nz));
1373 }
1374 else
1375 {
1376 failString = [NSString stringWithFormat:@"%@Failed to read a normal for face[%d] in FACES\n", failString, j];
1377 }
1378
1379 // vertices
1380 if ([scanner scanInt:&n_v])
1381 {
1382 if (n_v < 3)
1383 {
1384 failFlag = YES;
1385 failString = [NSString stringWithFormat:@"%@Face[%u] has fewer than three vertices.\n", failString, j];
1386 }
1387 else if (n_v > 3)
1388 {
1389 OOLogWARN(@"mesh.load.warning.nonTriangular", @"Face[%u] of %@ has %u vertices specified. Only the first three will be used.", j, baseFile, n_v);
1390 n_v = 3;
1391 }
1392 }
1393 else
1394 {
1395 failFlag = YES;
1396 failString = [NSString stringWithFormat:@"%@Failed to read number of vertices for face[%d] in FACES\n", failString, j];
1397 }
1398
1399 if (!failFlag)
1400 {
1401 int vi;
1402 for (i = 0; (int)i < n_v; i++)
1403 {
1404 if ([scanner scanInt:&vi])
1405 {
1406 _faces[j].vertex[i] = vi;
1407 if (faceRefs != NULL) VFRAddFace(&faceRefs[vi], j);
1408 }
1409 else
1410 {
1411 failFlag = YES;
1412 failString = [NSString stringWithFormat:@"%@Failed to read vertex[%d] for face[%d] in FACES\n", failString, i, j];
1413 }
1414 }
1415 }
1416 }
1417 }
1418 }
1419 else
1420 {
1421 failFlag = YES;
1422 failString = [NSString stringWithFormat:@"%@Failed to find FACES data\n",failString];
1423 }
1424
1425 // Get textures data.
1426 if ([scanner scanString:@"TEXTURES" intoString:NULL])
1427 {
1428 for (j = 0; j < faceCount; j++)
1429 {
1430 NSString *materialKey;
1431 float max_x, max_y;
1432 float s, t;
1433 if (!failFlag)
1434 {
1435 // materialKey
1436 //
1437 [scanner scanCharactersFromSet:whitespaceAndNewlineCharSet intoString:NULL];
1438 if (![scanner scanUpToCharactersFromSet:whitespaceCharSet intoString:&materialKey])
1439 {
1440 failFlag = YES;
1441 failString = [NSString stringWithFormat:@"%@Failed to read texture filename for face[%d] in TEXTURES\n", failString, j];
1442 }
1443 else
1444 {
1445 NSNumber *index = [texFileName2Idx objectForKey:materialKey];
1446 if (index != nil)
1447 {
1448 _faces[j].materialIndex = [index unsignedIntValue];
1449 }
1450 else
1451 {
1452 if (materialCount == kOOMeshMaxMaterials)
1453 {
1454 OOLog(kOOLogMeshTooManyMaterials, @"***** ERROR: model %@ has too many materials (maximum is %d)", filename, kOOMeshMaxMaterials);
1455 return NO;
1456 }
1457 _faces[j].materialIndex = materialCount;
1458 materialKeys[materialCount] = [materialKey retain];
1459 index = [NSNumber numberWithUnsignedInt:materialCount];
1460 [texFileName2Idx setObject:index forKey:materialKey];
1461 ++materialCount;
1462 }
1463 }
1464
1465 // texture size
1466 //
1467 if (!failFlag)
1468 {
1469 if (![scanner scanFloat:&max_x]) failFlag = YES;
1470 if (![scanner scanFloat:&max_y]) failFlag = YES;
1471 if (failFlag)
1472 failString = [NSString stringWithFormat:@"%@Failed to read texture size for max_x and max_y in face[%d] in TEXTURES\n", failString, j];
1473 }
1474
1475 // vertices
1476 //
1477 if (!failFlag)
1478 {
1479 for (i = 0; i < 3; i++)
1480 {
1481 if (![scanner scanFloat:&s]) failFlag = YES;
1482 if (![scanner scanFloat:&t]) failFlag = YES;
1483 if (!failFlag)
1484 {
1485 _faces[j].s[i] = s / max_x;
1486 _faces[j].t[i] = t / max_y;
1487 }
1488 else
1489 failString = [NSString stringWithFormat:@"%@Failed to read s t coordinates for vertex[%d] in face[%d] in TEXTURES\n", failString, i, j];
1490 }
1491 }
1492 }
1493 }
1494 }
1495 else
1496 {
1497 failFlag = YES;
1498 failString = [failString stringByAppendingString:@"Failed to find TEXTURES data (will use placeholder material)\n"];
1499 materialKeys[0] = @"_oo_placeholder_material";
1500 materialCount = 1;
1501
1502 for (j = 0; j < faceCount; j++)
1503 {
1504 _faces[j].materialIndex = 0;
1505 }
1506 }
1507
1508 if ([scanner scanString:@"NAMES" intoString:NULL])
1509 {
1510 unsigned int count;
1511 if (![scanner scanInt:(int *)&count])
1512 {
1513 failFlag = YES;
1514 failString = [failString stringByAppendingString:@"Expected count after NAMES\n"];
1515 }
1516 else
1517 {
1518 for (j = 0; j < count; j++)
1519 {
1520 NSString *name = nil;
1521 [scanner scanCharactersFromSet:whitespaceAndNewlineCharSet intoString:NULL];
1522 if (![scanner scanUpToCharactersFromSet:newlineCharSet intoString:&name])
1523 {
1524 failFlag = YES;
1525 failString = [failString stringByAppendingString:@"Expected file name\n"];
1526 }
1527 else
1528 {
1529 [self renameTexturesFrom:[NSString stringWithFormat:@"%u", j] to:name];
1530 }
1531 }
1532 }
1533 }
1534
1535 BOOL explicitTangents = NO;
1536
1537 // Get explicit normals.
1538 if ([scanner scanString:@"NORMALS" intoString:NULL])
1539 {
1540 _normalMode = kNormalModeExplicit;
1541 if (![self allocateNormalBuffersWithCount:vertexCount])
1542 {
1543 OOLog(kOOLogAllocationFailure, @"***** ERROR: failed to allocate memory for model %@ (%u vertices).", filename, vertexCount);
1544 return NO;
1545 }
1546
1547 for (j = 0; j < vertexCount; j++)
1548 {
1549 float x, y, z;
1550 if (!failFlag)
1551 {
1552 if (![scanner scanFloat:&x]) failFlag = YES;
1553 if (![scanner scanFloat:&y]) failFlag = YES;
1554 if (![scanner scanFloat:&z]) failFlag = YES;
1555 if (!failFlag)
1556 {
1557 _normals[j] = vector_normal(make_vector(x, y, z));
1558 }
1559 else
1560 {
1561 failString = [NSString stringWithFormat:@"%@Failed to read a value for vertex[%d] in %@\n", failString, j, @"NORMALS"];
1562 }
1563 }
1564 }
1565
1566 // Get explicit tangents (only together with vertices).
1567 if ([scanner scanString:@"TANGENTS" intoString:NULL])
1568 {
1569 for (j = 0; j < vertexCount; j++)
1570 {
1571 float x, y, z;
1572 if (!failFlag)
1573 {
1574 if (![scanner scanFloat:&x]) failFlag = YES;
1575 if (![scanner scanFloat:&y]) failFlag = YES;
1576 if (![scanner scanFloat:&z]) failFlag = YES;
1577 if (!failFlag)
1578 {
1579 _tangents[j] = vector_normal(make_vector(x, y, z));
1580 }
1581 else
1582 {
1583 failString = [NSString stringWithFormat:@"%@Failed to read a value for vertex[%d] in %@\n", failString, j, @"TANGENTS"];
1584 }
1585 }
1586 }
1587 }
1588 }
1589
1590 PROFILE(@"finished parsing");
1591
1592 if (IsLegacyNormalMode(_normalMode))
1593 {
1594 [self checkNormalsAndAdjustWinding];
1595 PROFILE(@"finished checkNormalsAndAdjustWinding");
1596 }
1597 if (!explicitTangents)
1598 {
1599 [self generateFaceTangents];
1600 PROFILE(@"finished generateFaceTangents");
1601 }
1602
1603 // check for smooth shading and recalculate normals
1604 if (_normalMode == kNormalModeSmooth)
1605 {
1606 if (![self allocateNormalBuffersWithCount:vertexCount])
1607 {
1608 OOLog(kOOLogAllocationFailure, @"***** ERROR: failed to allocate memory for model %@ (%u vertices).", filename, vertexCount);
1609 return NO;
1610 }
1611 [self calculateVertexNormalsAndTangentsWithFaceRefs:faceRefs];
1612 PROFILE(@"finished calculateVertexNormalsAndTangents");
1613
1614 }
1615 else if (IsPerVertexNormalMode(_normalMode) && !explicitTangents)
1616 {
1617 [self calculateVertexTangentsWithFaceRefs:faceRefs];
1618 PROFILE(@"finished calculateVertexTangents");
1619 }
1620
1621 // save the resulting data for possible reuse
1622 if (EXPECT(_cacheWriteable))
1623 {
1624 [OOCacheManager setMeshData:[self modelData] forName:cacheKey];
1625 PROFILE(@"saved to cache");
1626 }
1627
1628 if (failFlag)
1629 {
1630 OOLog(@"mesh.error", @"%@ ..... from %@ %@", failString, filename, (using_preloaded)? @"(from preloaded data)" :@"(from file)");
1631 }
1632 }
1633
1634 [self calculateBoundingVolumes];
1635 PROFILE(@"finished calculateBoundingVolumes");
1636
1637 // set up vertex arrays for drawing
1638 if (![self setUpVertexArrays]) return NO;
1639 PROFILE(@"finished setUpVertexArrays");
1640
1641 return YES;
1642
1644}
void OOStandardsError(NSString *message)
#define OOLogWARN(class, format,...)
Definition OOLogging.h:113
NSString *const kOOLogAllocationFailure
Definition OOLogging.m:649
static void VFRAddFace(VertexFaceRef *vfr, NSUInteger index)
static BOOL IsLegacyNormalMode(OOMeshNormalMode mode)
Definition OOMesh.m:188
static NSString *const kOOLogMeshTooManyMaterials
Definition OOMesh.m:85
static NSString *const kOOLogMeshDataNotFound
Definition OOMesh.m:84
struct VertexFaceRef VertexFaceRef
static BOOL IsPerVertexNormalMode(OOMeshNormalMode mode)
Definition OOMesh.m:210
BOOL setUpVertexArrays()
Definition OOMesh.m:1887
void setMeshData:forName:(NSDictionary *inData,[forName] NSString *inShipName)
Definition OOMesh.m:2224
NSDictionary * meshDataForName:(NSString *inShipName)
Definition OOMesh.m:2218
NSString * stringFromFilesNamed:inFolder:cache:(NSString *fileName,[inFolder] NSString *folderName,[cache] BOOL useCache)
const char * filename
Definition ioapi.h:133
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque

◆ materials

- (NSDictionary *) materials

◆ meshRescaledBy:

- (OOMesh *) meshRescaledBy: (GLfloat) scaleFactor

Definition at line 341 of file OOMesh.m.

791 :(GLfloat)scaleFactor
792{
793 OOMesh *result = [self mutableCopy];
794 [result rescaleByFactor:scaleFactor];
795 return [result autorelease];
796}
void rescaleByFactor:(GLfloat factor)
Definition OOMesh.m:2022

◆ meshWithName:cacheKey:materialDictionary:shadersDictionary:smooth:shaderMacros:shaderBindingTarget:

+ (instancetype) meshWithName: (NSString *) name
cacheKey: (NSString *) cacheKey
materialDictionary: (NSDictionary *) materialDict
shadersDictionary: (NSDictionary *) shadersDict
smooth: (BOOL) smooth
shaderMacros: (NSDictionary *) macros
shaderBindingTarget: (id<OOWeakReferenceSupport>) object 

Definition at line 121 of file OOMesh.m.

233 :(NSString *)name
234 cacheKey:(NSString *)cacheKey
235 materialDictionary:(NSDictionary *)materialDict
236 shadersDictionary:(NSDictionary *)shadersDict
237 smooth:(BOOL)smooth
238 shaderMacros:(NSDictionary *)macros
239 shaderBindingTarget:(id<OOWeakReferenceSupport>)object
240{
241 return [[[self alloc] initWithName:name
242 cacheKey:cacheKey
243 materialDictionary:materialDict
244 shadersDictionary:shadersDict
245 smooth:smooth
246 shaderMacros:macros
247 shaderBindingTarget:object
248 scaleFactor:1.0f
249 cacheWriteable:YES] autorelease];
250}

Referenced by ShipSetMaterialsInternal(), and VisualEffectSetMaterialsInternal().

+ Here is the caller graph for this function:

◆ meshWithName:cacheKey:materialDictionary:shadersDictionary:smooth:shaderMacros:shaderBindingTarget:scaleFactor:cacheWriteable:

+ (instancetype) meshWithName: (NSString *) name
cacheKey: (NSString *) cacheKey
materialDictionary: (NSDictionary *) materialDict
shadersDictionary: (NSDictionary *) shadersDict
smooth: (BOOL) smooth
shaderMacros: (NSDictionary *) macros
shaderBindingTarget: (id<OOWeakReferenceSupport>) object
scaleFactor: (float) factor
cacheWriteable: (BOOL) cacheWriteable 

Definition at line 121 of file OOMesh.m.

252 :(NSString *)name
253 cacheKey:(NSString *)cacheKey
254 materialDictionary:(NSDictionary *)materialDict
255 shadersDictionary:(NSDictionary *)shadersDict
256 smooth:(BOOL)smooth
257 shaderMacros:(NSDictionary *)macros
258 shaderBindingTarget:(id<OOWeakReferenceSupport>)object
259 scaleFactor:(float)scale
260 cacheWriteable:(BOOL)cacheWriteable
261{
262 return [[[self alloc] initWithName:name
263 cacheKey:cacheKey
264 materialDictionary:materialDict
265 shadersDictionary:shadersDict
266 smooth:smooth
267 shaderMacros:macros
268 shaderBindingTarget:object
269 scaleFactor:scale
270 cacheWriteable:cacheWriteable] autorelease];
271}

◆ modelData

- (NSDictionary *) modelData
implementation

Provided by category OOMesh(Private).

Definition at line 341 of file OOMesh.m.

997{
999
1000 NSNumber *vertCnt = nil,
1001 *faceCnt = nil;
1002 NSData *vertData = nil,
1003 *normData = nil,
1004 *tanData = nil,
1005 *faceData = nil;
1006 NSArray *mtlKeys = nil;
1007 NSNumber *normMode = nil;
1008
1009 BOOL includeNormals = IsPerVertexNormalMode(_normalMode);
1010
1011 // Prepare cache data elements.
1012 vertCnt = [NSNumber numberWithUnsignedInt:vertexCount];
1013 faceCnt = [NSNumber numberWithUnsignedInt:faceCount];
1014
1015 vertData = [_retainedObjects objectForKey:@"vertices"];
1016 faceData = [_retainedObjects objectForKey:@"faces"];
1017 if (includeNormals)
1018 {
1019 normData = [_retainedObjects objectForKey:@"normals"];
1020 tanData = [_retainedObjects objectForKey:@"tangents"];
1021 }
1022
1023 if (materialCount != 0)
1024 {
1025 mtlKeys = [NSArray arrayWithObjects:materialKeys count:materialCount];
1026 }
1027 else
1028 {
1029 mtlKeys = [NSArray array];
1030 }
1031 normMode = [NSNumber numberWithUnsignedChar:_normalMode];
1032
1033 // Ensure we have all the required data elements.
1034 if (vertCnt == nil ||
1035 faceCnt == nil ||
1036 vertData == nil ||
1037 faceData == nil ||
1038 mtlKeys == nil ||
1039 normMode == nil)
1040 {
1041 return nil;
1042 }
1043
1044 if (includeNormals)
1045 {
1046 if (normData == nil || tanData == nil) return nil;
1047 }
1048
1049 // All OK; stick 'em in a dictionary.
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",
1057 /* NOTE: order matters. Since normData and tanData
1058 are last, if they're nil the dictionary will be
1059 built without them, which is desired behaviour.
1060 */
1061 normData, @"normal data",
1062 tanData, @"tangent data",
1063 nil];
1064
1066}

◆ modelName

- (NSString *) modelName

Definition at line 341 of file OOMesh.m.

368{
369 return baseFile;
370}

◆ mutableCopyWithZone:

- (id) mutableCopyWithZone: (NSZone *) zone
implementation

Provided by category OOMesh(Private).

Definition at line 341 of file OOMesh.m.

941 :(NSZone *)zone
942{
943 OOMesh *result = nil;
945
946 result = (OOMesh *)NSCopyObject(self, 0, zone);
947
948 if (result != nil)
949 {
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];
959
960 for (i = 0; i != kOOMeshMaxMaterials; ++i)
961 {
962 [result->materialKeys[i] retain];
963 [result->materials[i] retain];
964 }
965
966 // Reset unsharable GL state
967 result->listsReady = NO;
968
970 }
971
972 return result;
973}
uint8_t listsReady
Definition OOMesh.h:95

◆ NormalModeDescription

+ (static NSString *) NormalModeDescription (OOMeshNormalMode) mode
implementation

Definition at line 341 of file OOMesh.m.

342{
343 switch (mode)
344 {
345 case kNormalModePerFace: return @"per-face";
346 case kNormalModeSmooth: return @"smooth";
347 case kNormalModeExplicit: return @"explicit";
348 }
349
350 return @"unknown";
351}
const char int mode
Definition ioapi.h:133

◆ octree

- (Octree *) octree

◆ octreeDepth

- (unsigned) octreeDepth
implementation

Definition at line 341 of file OOMesh.m.

642{
643 float threshold = kOctreeSizeThreshold;
644 unsigned result = kBaseOctreeDepth;
645 GLfloat xs, ys, zs, t, size;
646
647 bounding_box_get_dimensions(boundingBox, &xs, &ys, &zs);
648 // Shuffle dimensions around so zs is smallest
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; // Use average of two largest
652
654 else while (result < kMaxOctreeDepth)
655 {
656 if (size < threshold) break;
657 threshold *= 2.0f;
658 result++;
659 }
660
661 OOLog(@"mesh.load.octree.size", @"Selected octree depth %u for size %g for %@", result, size, baseFile);
662 return result;
663}
@ kBaseOctreeDepth
Definition OOMesh.m:68
@ kOctreeSmallSizeThreshold
Definition OOMesh.m:72
@ kSmallOctreeDepth
Definition OOMesh.m:70
@ kOctreeSizeThreshold
Definition OOMesh.m:71
@ kMaxOctreeDepth
Definition Octree.h:88
BoundingBox boundingBox
Definition OOMesh.h:120

◆ placeholderMaterial

+ (OOMaterial *) placeholderMaterial

Definition at line 121 of file OOMesh.m.

275{
277
279 {
280 placeholderMaterial = [[OOBasicMaterial alloc] initWithName:@"/placeholder/" configuration:[[ResourceManager materialDefaults] oo_dictionaryForKey:@"no-textures-material"]];
281 }
282
283 return placeholderMaterial;
284}
OOMaterial * placeholderMaterial()
Definition OOMesh.m:274
NSDictionary * materialDefaults()

◆ rebindMaterials

- (void) rebindMaterials

Definition at line 341 of file OOMesh.m.

568{
570 OOMaterial *material = nil;
571
572 if (materialCount != 0)
573 {
574 for (i = 0; i != materialCount; ++i)
575 {
576 OOMaterial *oldMaterial = materials[i];
577
578 if (![materialKeys[i] isEqualToString:@"_oo_placeholder_material"])
579 {
580 material = [OOMaterial materialWithName:materialKeys[i]
581 cacheKey:_cacheKey
582 materialDictionary:_materialDict
583 shadersDictionary:_shadersDict
584 macros:_shaderMacros
585 bindingTarget:[_shaderBindingTarget weakRefUnderlyingObject] // Windows DEP fix.
586 forSmoothedMesh:IsPerVertexNormalMode(_normalMode)];
587 }
588 else
589 {
590 material = nil;
591 }
592
593 if (material != nil)
594 {
595 materials[i] = [material retain];
596 }
597 else
598 {
599 materials[i] = [[OOMesh placeholderMaterial] retain];
600 }
601
602 /* Release is deferred to here to ensure we don't end up releasing
603 a texture that's not in the recent-cache and then reloading it.
604 */
605 [oldMaterial release];
606 }
607 }
608}
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)

◆ renameTexturesFrom:to:

- (void) renameTexturesFrom: (NSString *) from
to: (NSString *) to 
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

2195 :(NSString *)from to:(NSString *)to
2196{
2197 /* IMPORTANT: this has to be called before setUpMaterials..., so it can
2198 only be used during loading.
2199 */
2201 for (i = 0; i != materialCount; i++)
2202 {
2203 if ([materialKeys[i] isEqualToString:from])
2204 {
2205 [materialKeys[i] release];
2206 materialKeys[i] = [to copy];
2207 }
2208 }
2209}

◆ renderOpaqueParts

- (void) renderOpaqueParts
implementation

Reimplemented from OODrawable.

Definition at line 341 of file OOMesh.m.

386{
388
389 BOOL meshBelongsToVisualEffect = [_shaderBindingTarget isVisualEffect];
390
392
393 OOGL(glVertexPointer(3, GL_FLOAT, 0, _displayLists.vertexArray));
394 OOGL(glNormalPointer(GL_FLOAT, 0, _displayLists.normalArray));
395
396 // for visual effects enable blending. This will allow use of alpha
397 // channel in shaders - note, this is a bit of cheating the system,
398 // which expects blending to be disabled at this point
399 if (meshBelongsToVisualEffect)
400 {
401 OOGL(glEnable(GL_BLEND));
402 OOGL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
403 }
404
405#if OO_SHADERS
406 if ([[OOOpenGLExtensionManager sharedManager] shadersSupported])
407 {
408 OOGL(glEnableVertexAttribArrayARB(kTangentAttributeIndex));
409 OOGL(glVertexAttribPointerARB(kTangentAttributeIndex, 3, GL_FLOAT, GL_FALSE, 0, _displayLists.tangentArray));
410 }
411#endif
412
413 BOOL usingNormalsAsTexCoords = NO;
415
416 /* FIXME: really, really horrible hack to set up texture coordinates for
417 each texture unit. Very messy and still fails to handle some possibly-
418 basic stuff, like switching usingNormalsAsTexCoords per texture unit.
419 The right way to do this is probably to move attribute setup into the
420 material model.
421 -- Ahruman 2010-04-12
422 */
423#if OO_MULTITEXTURE
424 if (_textureUnitCount == NSNotFound)
425 {
426 _textureUnitCount = 0;
427 for (ti = 0; ti < materialCount; ti++)
428 {
429 NSUInteger count = [materials[ti] countOfTextureUnitsWithBaseCoordinates];
430 if (_textureUnitCount < count) _textureUnitCount = count;
431 }
432 }
433
434 NSUInteger unit;
435 if (_textureUnitCount <= 1)
436 {
437 OOGL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
438 }
439 else
440 {
441 /* It should not be possible to have multiple texture units if
442 texture combiners are not available.
443 */
444 NSAssert2([[OOOpenGLExtensionManager sharedManager] textureCombinersSupported], @"Mesh %@ uses %lu texture units, but multitexturing is not available.", [self shortDescription], _textureUnitCount);
445
446 for (unit = 0; unit < _textureUnitCount; unit++)
447 {
448 OOGL(glClientActiveTextureARB(GL_TEXTURE0_ARB + unit));
449 OOGL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
450 }
451 }
452#else
453 OOGL(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
454#endif
455
456 @try
457 {
458 if (!listsReady)
459 {
460 OOGL(displayList0 = glGenLists(materialCount));
461
462 // Ensure all textures are loaded
463 for (ti = 0; ti < materialCount; ti++)
464 {
465 [materials[ti] ensureFinishedLoading];
466 }
467 }
468
469 for (ti = 0; ti < materialCount; ti++)
470 {
471 BOOL wantsNormalsAsTextureCoordinates = [materials[ti] wantsNormalsAsTextureCoordinates];
472 if (ti == 0 || wantsNormalsAsTextureCoordinates != usingNormalsAsTexCoords)
473 {
474 // FIXME: enabling/disabling texturing should be handled by the material.
475#if OO_MULTITEXTURE
476 for (unit = 0; unit < _textureUnitCount; unit++)
477 {
478 if (_textureUnitCount > 1)
479 {
480 OOGL(glClientActiveTextureARB(GL_TEXTURE0_ARB + unit));
481 OOGL(glActiveTextureARB(GL_TEXTURE0_ARB + unit));
482 }
483#endif
484 if (!wantsNormalsAsTextureCoordinates)
485 {
486 OOGL(glDisable(GL_TEXTURE_CUBE_MAP));
487 OOGL(glTexCoordPointer(2, GL_FLOAT, 0, _displayLists.textureUVArray));
488 /* FIXME: Not including the line below breaks multitexturing in no-shaders mode.
489 However, the OpenGL state manager should probably be handling this;
490 TEXTURE_2D is part of OPENGL_STATE_OPAQUE, which has already been set.
491 - Nikos 20130103
492 */
493 OOGL(glEnable(GL_TEXTURE_2D));
494 }
495 else
496 {
497 OOGL(glDisable(GL_TEXTURE_2D));
498 OOGL(glTexCoordPointer(3, GL_FLOAT, 0, _displayLists.vertexArray));
499 OOGL(glEnable(GL_TEXTURE_CUBE_MAP));
500 }
501#if OO_MULTITEXTURE
502 }
503#endif
504 usingNormalsAsTexCoords = wantsNormalsAsTextureCoordinates;
505 }
506
507 [materials[ti] apply];
508 OOGL(glDrawArrays(GL_TRIANGLES, triangle_range[ti].location, triangle_range[ti].length));
509 }
510
511 listsReady = YES;
512 brokenInRender = NO;
513 }
514 @catch (NSException *exception)
515 {
516 if (!brokenInRender)
517 {
518 OOLog(kOOLogException, @"***** %s for %@ encountered exception: %@ : %@ *****", __PRETTY_FUNCTION__, self, [exception name], [exception reason]);
519 brokenInRender = YES;
520 }
521 if ([[exception name] hasPrefix:@"Oolite"]) [UNIVERSE handleOoliteException:exception]; // handle these ourself
522 else @throw exception; // pass these on
523 }
524
525#if OO_SHADERS
526 if ([[OOOpenGLExtensionManager sharedManager] shadersSupported])
527 {
528 OOGL(glDisableVertexAttribArrayARB(kTangentAttributeIndex));
529 }
530#endif
531
533 OOCheckOpenGLErrors(@"OOMesh after drawing %@", self);
534
535#if OO_MULTITEXTURE
536 if (_textureUnitCount <= 1)
537 {
538 OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
539 }
540 else
541 {
542 for (unit = 0; unit < _textureUnitCount; unit++)
543 {
544 OOGL(glClientActiveTextureARB(GL_TEXTURE0_ARB + unit));
545 OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
546 }
547
548 OOGL(glClientActiveTextureARB(GL_TEXTURE0_ARB));
549 OOGL(glActiveTextureARB(GL_TEXTURE0_ARB));
550 }
551#else
552 OOGL(glDisableClientState(GL_TEXTURE_COORD_ARRAY));
553#endif
554
555#ifndef NDEBUG
556 if (gDebugFlags & DEBUG_DRAW_NORMALS) [self debugDrawNormals];
557 if (gDebugFlags & DEBUG_OCTREE_DRAW) [[self octree] drawOctree];
558#endif
559
560 // visual effect - disable previously enabled blending
561 if (meshBelongsToVisualEffect) OOGL(glDisable(GL_BLEND));
562
564}
NSUInteger gDebugFlags
Definition main.m:7
@ DEBUG_OCTREE_DRAW
@ DEBUG_DRAW_NORMALS
NSString *const kOOLogException
Definition OOLogging.m:651
uint8_t OOMeshMaterialIndex
Definition OOMesh.h:58
@ OPENGL_STATE_OPAQUE
Definition OOOpenGL.h:123
#define OOVerifyOpenGLState()
Definition OOOpenGL.h:136
BOOL OOCheckOpenGLErrors(NSString *format,...)
Definition OOOpenGL.m:39
#define OOSetOpenGLState(STATE)
Definition OOOpenGL.h:135
void applyNone()
Definition OOMaterial.m:80
uint8_t brokenInRender
Definition OOMesh.h:94
GLuint displayList0
Definition OOMesh.h:116
NSRange triangle_range[kOOMeshMaxMaterials]
Definition OOMesh.h:113
OOMeshDisplayLists _displayLists
Definition OOMesh.h:111
Vector * tangentArray
Definition OOMesh.h:83
Vector * vertexArray
Definition OOMesh.h:81
GLfloat * textureUVArray
Definition OOMesh.h:80
Vector * normalArray
Definition OOMesh.h:82

◆ rescaleByFactor:

- (void) rescaleByFactor: (GLfloat) factor
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

2022 :(GLfloat)factor
2023{
2024 // Rescale base vertices used for geometry calculations.
2026 Vector *vertex = NULL;
2027
2028 for (i = 0; i < vertexCount; i++)
2029 {
2030 vertex = &_vertices[i];
2031 *vertex = vector_multiply_scalar(*vertex, factor);
2032 }
2033
2034 // Rescale actual display vertices.
2035 for (i = 0; i < _displayLists.count; i++)
2036 {
2037 vertex = &_displayLists.vertexArray[i];
2038 *vertex = vector_multiply_scalar(*vertex, factor);
2039 }
2040
2041 [self calculateBoundingVolumes];
2042 DESTROY(octree);
2043 DESTROY(baseFile); // Avoid octree cache.
2044 DESTROY(baseFileOctreeCacheRef);
2045}

◆ resetGraphicsState

- (void) resetGraphicsState
implementation

Provided by category OOMesh(Private).

Definition at line 341 of file OOMesh.m.

989{
990 [self deleteDisplayLists];
991 [self rebindMaterials];
992 _textureUnitCount = NSNotFound;
993}

◆ setBindingTarget:

- (void) setBindingTarget: (id<OOWeakReferenceSupport>) target
implementation

Reimplemented from OODrawable.

Definition at line 341 of file OOMesh.m.

799 :(id<OOWeakReferenceSupport>)target
800{
801 unsigned i;
802
803 for (i = 0; i != kOOMeshMaxMaterials; ++i)
804 {
805 [materials[i] setBindingTarget:target];
806 }
807}

◆ setModelFromModelData:name:

- (BOOL) setModelFromModelData: (NSDictionary*) dict
name: (NSString *) fileName 
implementation

Provided by category OOMesh(Private).

Definition at line 341 of file OOMesh.m.

1069 :(NSDictionary *)dict name:(NSString *)fileName
1070{
1072
1073 NSData *vertData = nil,
1074 *normData = nil,
1075 *tanData = nil,
1076 *faceData = nil;
1077 NSArray *mtlKeys = nil;
1078 NSString *key = nil;
1079 unsigned i;
1080
1081 if (dict == nil || ![dict isKindOfClass:[NSDictionary class]]) return NO;
1082
1083 vertexCount = [dict oo_unsignedIntForKey:@"vertex count"];
1084 faceCount = [dict oo_unsignedIntForKey:@"face count"];
1085
1086 if (vertexCount == 0 || faceCount == 0) return NO;
1087
1088 // Read data elements from dictionary.
1089 vertData = [dict oo_dataForKey:@"vertex data"];
1090 faceData = [dict oo_dataForKey:@"face data"];
1091
1092 mtlKeys = [dict oo_arrayForKey:@"material keys"];
1093 _normalMode = [dict oo_unsignedCharForKey:@"normal mode"];
1094 BOOL includeNormals = IsPerVertexNormalMode(_normalMode);
1095
1096 // Ensure we have all the required data elements.
1097 if (vertData == nil ||
1098 faceData == nil ||
1099 mtlKeys == nil)
1100 {
1101 OOLog(@"mesh.load.error.badCacheData", @"Ignoring bad cache data for mesh \"%@\".", fileName);
1102 return NO;
1103 }
1104
1105 if (includeNormals)
1106 {
1107 normData = [dict oo_dataForKey:@"normal data"];
1108 tanData = [dict oo_dataForKey:@"tangent data"];
1109 if (normData == nil || tanData == nil)
1110 {
1111 OOLog(@"mesh.load.error.badCacheData", @"Ignoring bad normal/tangent cache data for mesh \"%@\".", fileName);
1112 return NO;
1113 }
1114 }
1115
1116 // Ensure data objects are of correct size.
1117 if ([vertData length] != sizeof *_vertices * vertexCount) return NO;
1118 if ([faceData length] != sizeof *_faces * faceCount) return NO;
1119 if (includeNormals)
1120 {
1121 if ([normData length] != sizeof *_normals * vertexCount) return NO;
1122 if ([tanData length] != sizeof *_tangents * vertexCount) return NO;
1123 }
1124
1125 // Retain data.
1126 _vertices = (Vector *)[vertData bytes];
1127 [self setRetainedObject:vertData forKey:@"vertices"];
1128 _faces = (OOMeshFace *)[faceData bytes];
1129 [self setRetainedObject:faceData forKey:@"faces"];
1130 if (includeNormals)
1131 {
1132 _normals = (Vector *)[normData bytes];
1133 [self setRetainedObject:normData forKey:@"normals"];
1134 _tangents = (Vector *)[tanData bytes];
1135 [self setRetainedObject:tanData forKey:@"tangents"];
1136 }
1137 else
1138 {
1139 _normals = NULL;
1140 _tangents = NULL;
1141 }
1142
1143 // Copy material keys.
1144 materialCount = [mtlKeys count];
1145 for (i = 0; i != materialCount; ++i)
1146 {
1147 key = [mtlKeys oo_stringAtIndex:i];
1148 if (key != nil) materialKeys[i] = [key copy];
1149 else
1150 {
1151 OOLog(@"mesh.load.error.badCacheData", @"Ignoring bad cache data for mesh \"%@\".", fileName);
1152 return NO;
1153 }
1154 }
1155
1156 return YES;
1157
1159}

◆ setRetainedObject:forKey:

- (void) setRetainedObject: (id) object
forKey: (NSString *) key 
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

2108 :(id)object forKey:(NSString *)key
2109{
2110 assert(key != nil);
2111
2112 if (object != nil)
2113 {
2114 if (_retainedObjects == nil) _retainedObjects = [[NSMutableDictionary alloc] init];
2115 [_retainedObjects setObject:object forKey:key];
2116 }
2117}

◆ setUpVertexArrays

- (BOOL) setUpVertexArrays
implementation

Provided by category OOMesh(Private).

Definition at line 1792 of file OOMesh.m.

1888{
1890
1891 NSUInteger fi, vi, mi;
1892
1893 if (![self allocateVertexArrayBuffersWithCount:faceCount]) return NO;
1894
1895 // if smoothed, find any vertices that are between faces of different
1896 // smoothing groups and mark them as being on an edge and therefore NOT
1897 // smooth shaded
1898 BOOL is_edge_vertex[vertexCount];
1899 GLfloat smoothGroup[vertexCount];
1900 for (vi = 0; vi < vertexCount; vi++)
1901 {
1902 is_edge_vertex[vi] = NO;
1903 smoothGroup[vi] = -1;
1904 }
1905 if (_normalMode == kNormalModeSmooth)
1906 {
1907 for (fi = 0; fi < faceCount; fi++)
1908 {
1909 GLfloat rv = _faces[fi].smoothGroup;
1910 int i;
1911 for (i = 0; i < 3; i++)
1912 {
1913 vi = _faces[fi].vertex[i];
1914 if (smoothGroup[vi] < 0.0) // unassigned
1915 smoothGroup[vi] = rv;
1916 else if (smoothGroup[vi] != rv) // a different colour
1917 is_edge_vertex[vi] = YES;
1918 }
1919 }
1920 }
1921
1922
1923 // base model, flat or smooth shaded, all triangles
1924 int tri_index = 0;
1925 int uv_index = 0;
1926 int vertex_index = 0;
1927
1928 // Iterate over material names
1929 for (mi = 0; mi != materialCount; ++mi)
1930 {
1931 triangle_range[mi].location = tri_index;
1932
1933 for (fi = 0; fi < faceCount; fi++)
1934 {
1935 Vector normal, tangent;
1936
1937 if (_faces[fi].materialIndex == mi)
1938 {
1939 for (vi = 0; vi < 3; vi++)
1940 {
1941 int v = _faces[fi].vertex[vi];
1942 if (IsPerVertexNormalMode(_normalMode))
1943 {
1944 if (is_edge_vertex[v])
1945 {
1946 [self getNormal:&normal andTangent:&tangent forVertex:v inSmoothGroup:_faces[fi].smoothGroup];
1947 }
1948 else
1949 {
1950 NSAssert1(_normals != NULL && _tangents != NULL, @"Normal/tangent buffers not allocated in %s", __PRETTY_FUNCTION__);
1951
1952 normal = _normals[v];
1953 tangent = _tangents[v];
1954 }
1955 }
1956 else
1957 {
1958 normal = _faces[fi].normal;
1959 tangent = _faces[fi].tangent;
1960 }
1961
1962 // FIXME: avoid redundant vertices so index array is actually useful.
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];
1969 }
1970 }
1971 }
1972 triangle_range[mi].length = tri_index - triangle_range[mi].location;
1973 }
1974
1975 _displayLists.count = tri_index; // total number of triangle vertices
1976 return YES;
1977
1979}

◆ shaders

- (NSDictionary *) shaders

Definition at line 341 of file OOMesh.m.

618{
619 return _shadersDict;
620}

Referenced by ShipSetMaterialsInternal(), VisualEffectGetShaders(), and VisualEffectSetMaterialsInternal().

+ Here is the caller graph for this function:

◆ suppressClangStuff

- (BOOL) suppressClangStuff
implementation

Definition at line 341 of file OOMesh.m.

864{
865 return _normals && _tangents && _faces && boundingBox.min.x;
866}
OOMeshFace * _faces
Definition OOMesh.h:108
Vector * _tangents
Definition OOMesh.h:107
Vector * _normals
Definition OOMesh.h:106

◆ totalSize

- (size_t) totalSize
implementation

Reimplemented from OODrawable.

Definition at line 341 of file OOMesh.m.

837{
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;
843
844 result += _displayLists.count * (sizeof (GLint) + sizeof (GLfloat) + sizeof (Vector) * 3);
845
847 for (i = 0; i != materialCount; i++)
848 {
849 result += [materials[i] oo_objectSize];
850 }
851
852 result += [octree totalSize];
853 return result;
854}
size_t totalSize()
Definition OOMesh.m:836

◆ vertexCount

- (size_t) vertexCount

Member Data Documentation

◆ _cacheKey

- (NSString*) _cacheKey
private

Definition at line 128 of file OOMesh.h.

◆ _cacheWriteable

- (BOOL) _cacheWriteable
private

Definition at line 103 of file OOMesh.h.

◆ _displayLists

- (OOMeshDisplayLists) _displayLists
private

Definition at line 111 of file OOMesh.h.

◆ _faces

- (OOMeshFace*) _faces
private

Definition at line 108 of file OOMesh.h.

◆ _lastBoundingBox

- (BoundingBox) _lastBoundingBox
private

Definition at line 134 of file OOMesh.h.

◆ _lastPosition

- (Vector) _lastPosition
private

Definition at line 132 of file OOMesh.h.

◆ _lastRotMatrix

- (OOMatrix) _lastRotMatrix
private

Definition at line 133 of file OOMesh.h.

◆ _materialDict

- (NSDictionary*) _materialDict
private

Definition at line 126 of file OOMesh.h.

◆ _normalMode

- (uint8_t) _normalMode
private

Definition at line 93 of file OOMesh.h.

◆ _normals

- (Vector*) _normals
private

Definition at line 106 of file OOMesh.h.

◆ _retainedObjects

- (NSMutableDictionary*) _retainedObjects
private

Definition at line 124 of file OOMesh.h.

◆ _shaderBindingTarget

- (id) _shaderBindingTarget
private

Definition at line 130 of file OOMesh.h.

◆ _shaderMacros

- (NSDictionary*) _shaderMacros
private

Definition at line 129 of file OOMesh.h.

◆ _shadersDict

- (NSDictionary*) _shadersDict
private

Definition at line 127 of file OOMesh.h.

◆ _tangents

- (Vector*) _tangents
private

Definition at line 107 of file OOMesh.h.

◆ _vertices

- (Vector*) _vertices
private

Definition at line 105 of file OOMesh.h.

◆ baseFile

- (NSString*) baseFile
private

Definition at line 101 of file OOMesh.h.

◆ baseFileOctreeCacheRef

- (NSString*) baseFileOctreeCacheRef
private

Definition at line 102 of file OOMesh.h.

◆ boundingBox

- (BoundingBox) boundingBox
private

Provided by category OOMesh(Private).

Definition at line 120 of file OOMesh.h.

◆ brokenInRender

- (uint8_t) brokenInRender
private

Definition at line 94 of file OOMesh.h.

◆ collisionRadius

- (GLfloat) collisionRadius
private

Definition at line 118 of file OOMesh.h.

◆ displayList0

- (GLuint) displayList0
private

Definition at line 116 of file OOMesh.h.

◆ faceCount

- (size_t) faceCount
private

Definition at line 99 of file OOMesh.h.

◆ listsReady

- (uint8_t) listsReady
private

Definition at line 95 of file OOMesh.h.

◆ materialCount

- (OOMeshMaterialCount) materialCount
private

Definition at line 97 of file OOMesh.h.

◆ materialKeys

- (NSString* materialKeys[kOOMeshMaxMaterials])
private

Definition at line 114 of file OOMesh.h.

◆ materials

- (NSDictionary *) materials
private

◆ maxDrawDistance

- (GLfloat) maxDrawDistance
private

Definition at line 119 of file OOMesh.h.

◆ octree

- (Octree *) octree
private

Definition at line 122 of file OOMesh.h.

◆ triangle_range

- (NSRange triangle_range[kOOMeshMaxMaterials])
private

Definition at line 113 of file OOMesh.h.

◆ vertexCount

- (size_t) vertexCount
private

Definition at line 98 of file OOMesh.h.


The documentation for this class was generated from the following files: