summaryrefslogtreecommitdiff
path: root/src/mesh/assimp-master/samples/SimpleAssimpViewX/MyDocument.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesh/assimp-master/samples/SimpleAssimpViewX/MyDocument.mm')
-rw-r--r--src/mesh/assimp-master/samples/SimpleAssimpViewX/MyDocument.mm808
1 files changed, 808 insertions, 0 deletions
diff --git a/src/mesh/assimp-master/samples/SimpleAssimpViewX/MyDocument.mm b/src/mesh/assimp-master/samples/SimpleAssimpViewX/MyDocument.mm
new file mode 100644
index 0000000..cbe0348
--- /dev/null
+++ b/src/mesh/assimp-master/samples/SimpleAssimpViewX/MyDocument.mm
@@ -0,0 +1,808 @@
+//
+// MyDocument.m
+// DisplayLinkAsyncMoviePlayer
+//
+// Created by vade on 10/26/10.
+// Copyright __MyCompanyName__ 2010 . All rights reserved.
+//
+
+#import "cimport.h"
+#import "config.h"
+#import "MyDocument.h"
+#import <OpenGL/CGLMacro.h>
+
+#pragma mark -
+#pragma mark Helper Functions
+
+#define aisgl_min(x,y) (x<y?x:y)
+#define aisgl_max(x,y) (y>x?y:x)
+
+static void color4_to_float4(const aiColor4D *c, float f[4])
+{
+ f[0] = c->r;
+ f[1] = c->g;
+ f[2] = c->b;
+ f[3] = c->a;
+}
+
+static void set_float4(float f[4], float a, float b, float c, float d)
+{
+ f[0] = a;
+ f[1] = b;
+ f[2] = c;
+ f[3] = d;
+}
+
+#pragma mark -
+#pragma mark CVDisplayLink Callback
+static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeStamp *inNow,const CVTimeStamp *inOutputTime,CVOptionFlags flagsIn,CVOptionFlags *flagsOut,void *displayLinkContext)
+{
+ CVReturn error = [(MyDocument*) displayLinkContext displayLinkRenderCallback:inOutputTime];
+ return error;
+}
+
+#pragma mark -
+
+@implementation MyDocument
+@synthesize _view;
+
+- (id)init
+{
+ self = [super init];
+ if (self != nil)
+ {
+ // initialization code
+ }
+ return self;
+}
+
+- (NSString *)windowNibName
+{
+ return @"MyDocument";
+}
+
+- (void)windowControllerDidLoadNib:(NSWindowController *)windowController
+{
+ [super windowControllerDidLoadNib:windowController];
+
+ NSOpenGLPixelFormatAttribute attributes[] =
+ {
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFAAccelerated,
+ NSOpenGLPFADepthSize, 24,
+ NSOpenGLPFAMultisample,
+ NSOpenGLPFASampleBuffers, 2,
+ (NSOpenGLPixelFormatAttribute) 0
+ };
+
+ _glPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
+
+ if(!_glPixelFormat)
+ NSLog(@"Error creating PF");
+
+ _glContext = [[NSOpenGLContext alloc] initWithFormat:_glPixelFormat shareContext:nil];
+
+ const GLint one = 1;
+
+ [_glContext setValues:&one forParameter:NSOpenGLCPSwapInterval];
+ [_glContext setView:_view];
+
+ // Set up initial GL state.
+ CGLContextObj cgl_ctx = (CGLContextObj)[_glContext CGLContextObj];
+
+ glEnable(GL_MULTISAMPLE);
+
+ glClearColor(0.3, 0.3, 0.3, 0.3);
+
+ // enable color tracking
+ //glEnable(GL_COLOR_MATERIAL);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glDepthMask(GL_TRUE);
+
+ glEnable(GL_NORMALIZE);
+ glEnable(GL_TEXTURE_2D);
+
+ glShadeModel(GL_SMOOTH);
+
+ glEnable(GL_LIGHTING);
+
+ GLfloat global_ambient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
+
+ GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
+ glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
+
+ GLfloat diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
+
+ GLfloat ambient[] = {0.2, 0.2f, 0.2f, 0.2f};
+ glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
+
+ GLfloat position[] = { 1.0f, 1.0f, 1.0f, 1.0f};
+ glLightfv(GL_LIGHT0, GL_POSITION, position);
+
+ glEnable(GL_LIGHT0);
+
+ // This is the only client state that always has to be set.
+ glEnableClientState(GL_VERTEX_ARRAY);
+
+ // end GL State setup.
+
+ // Display Link setup.
+ CVReturn error = kCVReturnSuccess;
+
+ error = CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
+ if(error == kCVReturnError)
+ NSLog(@"Error Creating DisplayLink");
+
+ error = CVDisplayLinkSetOutputCallback(_displayLink,MyDisplayLinkCallback, self);
+ if(error == kCVReturnError)
+ NSLog(@"Error Setting DisplayLink Callback");
+
+ error = CVDisplayLinkStart(_displayLink);
+ if(error == kCVReturnError)
+ NSLog(@"Error Starting DisplayLink");
+
+ NSOpenPanel* openPanel = [NSOpenPanel openPanel];
+
+ [openPanel beginSheetModalForWindow:[_view window] completionHandler:^(NSInteger result)
+ {
+ if (result == NSOKButton)
+ {
+ [openPanel orderOut:self]; // close panel before we might present an error
+
+ if([[NSFileManager defaultManager] fileExistsAtPath:[openPanel filename]])
+ {
+ // Load our new path.
+
+ // only ever give us triangles.
+ aiPropertyStore* props = aiCreatePropertyStore();
+ aiSetImportPropertyInteger(props, AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT );
+
+ NSUInteger aiPostProccesFlags;
+
+ switch (2)
+ {
+ case 0:
+ aiPostProccesFlags = aiProcessPreset_TargetRealtime_Fast;
+ break;
+ case 1:
+ aiPostProccesFlags = aiProcessPreset_TargetRealtime_Quality;
+ break;
+ case 2:
+ aiPostProccesFlags = aiProcessPreset_TargetRealtime_MaxQuality;
+ break;
+ default:
+ aiPostProccesFlags = aiProcessPreset_TargetRealtime_MaxQuality;
+ break;
+ }
+
+ // aiProcess_FlipUVs is needed for VAO / VBOs, not sure why.
+ _scene = (aiScene*) aiImportFileExWithProperties([[openPanel filename] cStringUsingEncoding:[NSString defaultCStringEncoding]], aiPostProccesFlags | aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_PreTransformVertices | 0, NULL, props);
+
+ aiReleasePropertyStore(props);
+
+ if (_scene)
+ {
+ textureDictionary = [[NSMutableDictionary alloc] initWithCapacity:5];
+
+ // Why do I need to cast this !?
+ CGLContextObj cgl_ctx = (CGLContextObj)[_glContext CGLContextObj];
+ CGLLockContext(cgl_ctx);
+
+ [self loadTexturesInContext:cgl_ctx withModelPath:[[openPanel filename] stringByStandardizingPath]];
+
+ //NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithPointer:cgl_ctx], @"context", [self.inputModelPath stringByStandardizingPath], @"path", nil ];
+ //[self performSelectorInBackground:@selector(loadTexturesInBackground:) withObject:userInfo];
+
+ [self getBoundingBoxWithMinVector:&scene_min maxVectr:&scene_max];
+ scene_center.x = (scene_min.x + scene_max.x) / 2.0f;
+ scene_center.y = (scene_min.y + scene_max.y) / 2.0f;
+ scene_center.z = (scene_min.z + scene_max.z) / 2.0f;
+
+ // optional normalized scaling
+ normalizedScale = scene_max.x-scene_min.x;
+ normalizedScale = aisgl_max(scene_max.y - scene_min.y,normalizedScale);
+ normalizedScale = aisgl_max(scene_max.z - scene_min.z,normalizedScale);
+ normalizedScale = 1.f / normalizedScale;
+
+ if(_scene->HasAnimations())
+ NSLog(@"scene has animations");
+
+ [self createGLResourcesInContext:cgl_ctx];
+ CGLUnlockContext(cgl_ctx);
+ }
+ }
+ }
+ }]; // end block handler
+}
+
+- (void) close
+{
+ CVDisplayLinkStop(_displayLink);
+ CVDisplayLinkRelease(_displayLink);
+
+ if(_scene)
+ {
+ aiReleaseImport(_scene);
+ _scene = NULL;
+
+ CGLContextObj cgl_ctx = (CGLContextObj)[_glContext CGLContextObj];
+ glDeleteTextures([textureDictionary count], textureIds);
+
+ [textureDictionary release];
+ textureDictionary = nil;
+
+ free(textureIds);
+ textureIds = NULL;
+
+ [self deleteGLResourcesInContext:cgl_ctx];
+ }
+
+ [_glContext release];
+ _glContext = nil;
+
+ [_glPixelFormat release];
+ _glPixelFormat = nil;
+
+ [super close];
+}
+
+- (CVReturn)displayLinkRenderCallback:(const CVTimeStamp *)timeStamp
+{
+ CVReturn rv = kCVReturnError;
+ NSAutoreleasePool *pool;
+
+ pool = [[NSAutoreleasePool alloc] init];
+ {
+ [self render];
+ rv = kCVReturnSuccess;
+ }
+ [pool release];
+ return rv;
+}
+
+- (void) render
+{
+ CGLContextObj cgl_ctx = (CGLContextObj)[_glContext CGLContextObj];
+ CGLLockContext(cgl_ctx);
+
+ [_glContext update];
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glViewport(0, 0, _view.frame.size.width, _view.frame.size.height);
+
+ GLfloat aspect = _view.frame.size.height/_view.frame.size.width;
+ glOrtho(-1, 1, - (aspect), aspect, -10, 10);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glTranslated(0.0, 0.0, 1.0);
+
+ // Draw our GL model.
+ if(_scene)
+ {
+ glScaled(normalizedScale , normalizedScale, normalizedScale);
+ // center the model
+ glTranslated( -scene_center.x, -scene_center.y, -scene_center.z);
+
+ glScaled(2.0, 2.0, 2.0);
+
+ static float i = 0;
+ i+=0.5;
+ glRotated(i, 0, 1, 0);
+
+ [self drawMeshesInContext:cgl_ctx];
+ }
+
+ CGLUnlockContext(cgl_ctx);
+
+ CGLFlushDrawable(cgl_ctx);
+}
+
+#pragma mark -
+#pragma mark Loading
+
+// Inspired by LoadAsset() & CreateAssetData() from AssimpView D3D project
+- (void) createGLResourcesInContext:(CGLContextObj)cgl_ctx
+{
+ // create new mesh helpers for each mesh, will populate their data later.
+ modelMeshes = [[NSMutableArray alloc] initWithCapacity:_scene->mNumMeshes];
+
+ // create OpenGL buffers and populate them based on each meshes pertinant info.
+ for (unsigned int i = 0; i < _scene->mNumMeshes; ++i)
+ {
+ NSLog(@"%u", i);
+
+ // current mesh we are introspecting
+ const aiMesh* mesh = _scene->mMeshes[i];
+
+ // the current meshHelper we will be populating data into.
+ MeshHelper* meshHelper = [[MeshHelper alloc] init];
+
+ // Handle material info
+
+ aiMaterial* mtl = _scene->mMaterials[mesh->mMaterialIndex];
+
+ // Textures
+ int texIndex = 0;
+ aiString texPath;
+
+ if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath))
+ {
+ NSString* textureKey = [NSString stringWithCString:texPath.data encoding:[NSString defaultCStringEncoding]];
+ //bind texture
+ NSNumber* textureNumber = (NSNumber*)[textureDictionary valueForKey:textureKey];
+
+ //NSLog(@"applyMaterialInContext: have texture %i", [textureNumber unsignedIntValue]);
+ meshHelper.textureID = [textureNumber unsignedIntValue];
+ }
+ else
+ meshHelper.textureID = 0;
+
+ // Colors
+
+ aiColor4D dcolor = aiColor4D(0.8f, 0.8f, 0.8f, 1.0f);
+ if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &dcolor))
+ [meshHelper setDiffuseColor:&dcolor];
+
+ aiColor4D scolor = aiColor4D(0.0f, 0.0f, 0.0f, 1.0f);
+ if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &scolor))
+ [meshHelper setSpecularColor:&scolor];
+
+ aiColor4D acolor = aiColor4D(0.2f, 0.2f, 0.2f, 1.0f);
+ if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &acolor))
+ [meshHelper setAmbientColor:&acolor];
+
+ aiColor4D ecolor = aiColor4D(0.0f, 0.0f, 0.0f, 1.0f);
+ if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &ecolor))
+ [meshHelper setEmissiveColor:&ecolor];
+
+ // Culling
+ unsigned int max = 1;
+ int two_sided;
+ if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided)
+ [meshHelper setTwoSided:YES];
+ else
+ [meshHelper setTwoSided:NO];
+
+ // Create a VBO for our vertices
+
+ GLuint vhandle;
+ glGenBuffers(1, &vhandle);
+
+ glBindBuffer(GL_ARRAY_BUFFER, vhandle);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * mesh->mNumVertices, NULL, GL_STATIC_DRAW);
+
+ // populate vertices
+ Vertex* verts = (Vertex*)glMapBuffer(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+
+ for (unsigned int x = 0; x < mesh->mNumVertices; ++x)
+ {
+ verts->vPosition = mesh->mVertices[x];
+
+ if (NULL == mesh->mNormals)
+ verts->vNormal = aiVector3D(0.0f,0.0f,0.0f);
+ else
+ verts->vNormal = mesh->mNormals[x];
+
+ if (NULL == mesh->mTangents)
+ {
+ verts->vTangent = aiVector3D(0.0f,0.0f,0.0f);
+ verts->vBitangent = aiVector3D(0.0f,0.0f,0.0f);
+ }
+ else
+ {
+ verts->vTangent = mesh->mTangents[x];
+ verts->vBitangent = mesh->mBitangents[x];
+ }
+
+ if (mesh->HasVertexColors(0))
+ {
+ verts->dColorDiffuse = mesh->mColors[0][x];
+ }
+ else
+ verts->dColorDiffuse = aiColor4D(1.0, 1.0, 1.0, 1.0);
+
+ // This varies slightly form Assimp View, we support the 3rd texture component.
+ if (mesh->HasTextureCoords(0))
+ verts->vTextureUV = mesh->mTextureCoords[0][x];
+ else
+ verts->vTextureUV = aiVector3D(0.5f,0.5f, 0.0f);
+
+ if (mesh->HasTextureCoords(1))
+ verts->vTextureUV2 = mesh->mTextureCoords[1][x];
+ else
+ verts->vTextureUV2 = aiVector3D(0.5f,0.5f, 0.0f);
+
+ // TODO: handle Bone indices and weights
+ /* if( mesh->HasBones())
+ {
+ unsigned char boneIndices[4] = { 0, 0, 0, 0 };
+ unsigned char boneWeights[4] = { 0, 0, 0, 0 };
+ ai_assert( weightsPerVertex[x].size() <= 4);
+
+ for( unsigned int a = 0; a < weightsPerVertex[x].size(); a++)
+ {
+ boneIndices[a] = weightsPerVertex[x][a].mVertexId;
+ boneWeights[a] = (unsigned char) (weightsPerVertex[x][a].mWeight * 255.0f);
+ }
+
+ memcpy( verts->mBoneIndices, boneIndices, sizeof( boneIndices));
+ memcpy( verts->mBoneWeights, boneWeights, sizeof( boneWeights));
+ }
+ else
+ */
+ {
+ memset( verts->mBoneIndices, 0, sizeof( verts->mBoneIndices));
+ memset( verts->mBoneWeights, 0, sizeof( verts->mBoneWeights));
+ }
+
+ ++verts;
+ }
+
+ glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); //invalidates verts
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ // set the mesh vertex buffer handle to our new vertex buffer.
+ meshHelper.vertexBuffer = vhandle;
+
+ // Create Index Buffer
+
+ // populate the index buffer.
+ NSUInteger nidx;
+ switch (mesh->mPrimitiveTypes)
+ {
+ case aiPrimitiveType_POINT:
+ nidx = 1;break;
+ case aiPrimitiveType_LINE:
+ nidx = 2;break;
+ case aiPrimitiveType_TRIANGLE:
+ nidx = 3;break;
+ default: assert(false);
+ }
+
+ // create the index buffer
+ GLuint ihandle;
+ glGenBuffers(1, &ihandle);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ihandle);
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * mesh->mNumFaces * nidx, NULL, GL_STATIC_DRAW);
+
+ unsigned int* indices = (unsigned int*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
+
+ // now fill the index buffer
+ for (unsigned int x = 0; x < mesh->mNumFaces; ++x)
+ {
+ for (unsigned int a = 0; a < nidx; ++a)
+ {
+ // if(mesh->mFaces[x].mNumIndices != 3)
+ // NSLog(@"whoa don't have 3 indices...");
+
+ *indices++ = mesh->mFaces[x].mIndices[a];
+ }
+ }
+
+ glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+ // set the mesh index buffer handle to our new index buffer.
+ meshHelper.indexBuffer = ihandle;
+ meshHelper.numIndices = mesh->mNumFaces * nidx;
+
+ // create the normal buffer. Assimp View creates a second normal buffer. Unsure why. Using only the interleaved normals for now.
+ // This is here for reference.
+
+ /* GLuint nhandle;
+ glGenBuffers(1, &nhandle);
+ glBindBuffer(GL_ARRAY_BUFFER, nhandle);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(aiVector3D)* mesh->mNumVertices, NULL, GL_STATIC_DRAW);
+
+ // populate normals
+ aiVector3D* normals = (aiVector3D*)glMapBuffer(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+
+ for (unsigned int x = 0; x < mesh->mNumVertices; ++x)
+ {
+ aiVector3D vNormal = mesh->mNormals[x];
+ *normals = vNormal;
+ ++normals;
+ }
+
+ glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); //invalidates verts
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ meshHelper.normalBuffer = nhandle;
+ */
+
+ // Create VAO and populate it
+
+ GLuint vaoHandle;
+ glGenVertexArraysAPPLE(1, &vaoHandle);
+
+ glBindVertexArrayAPPLE(vaoHandle);
+
+
+ glBindBuffer(GL_ARRAY_BUFFER, meshHelper.vertexBuffer);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(12));
+
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(4, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(24));
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(64));
+ //TODO: handle second texture
+
+ // VertexPointer ought to come last, apparently this is some optimization, since if its set once, first, it gets fiddled with every time something else is update.
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(Vertex), 0);
+
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshHelper.indexBuffer);
+
+ glBindVertexArrayAPPLE(0);
+
+ // save the VAO handle into our mesh helper
+ meshHelper.vao = vaoHandle;
+
+ // Create the display list
+
+ GLuint list = glGenLists(1);
+
+ glNewList(list, GL_COMPILE);
+
+ float dc[4];
+ float sc[4];
+ float ac[4];
+ float emc[4];
+
+ // Material colors and properties
+ color4_to_float4([meshHelper diffuseColor], dc);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, dc);
+
+ color4_to_float4([meshHelper specularColor], sc);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, sc);
+
+ color4_to_float4([meshHelper ambientColor], ac);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ac);
+
+ color4_to_float4(meshHelper.emissiveColor, emc);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emc);
+
+ glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
+
+ // Culling
+ if(meshHelper.twoSided)
+ glEnable(GL_CULL_FACE);
+ else
+ glDisable(GL_CULL_FACE);
+
+
+ // Texture Binding
+ glBindTexture(GL_TEXTURE_2D, meshHelper.textureID);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ // This binds the whole VAO, inheriting all the buffer and client state. Weeee
+ glBindVertexArrayAPPLE(meshHelper.vao);
+ glDrawElements(GL_TRIANGLES, meshHelper.numIndices, GL_UNSIGNED_INT, 0);
+
+ glEndList();
+
+ meshHelper.displayList = list;
+
+ // Whew, done. Save all of this shit.
+ [modelMeshes addObject:meshHelper];
+
+ [meshHelper release];
+ }
+}
+
+- (void) deleteGLResourcesInContext:(CGLContextObj)cgl_ctx
+{
+ for(MeshHelper* helper in modelMeshes)
+ {
+ const GLuint indexBuffer = helper.indexBuffer;
+ const GLuint vertexBuffer = helper.vertexBuffer;
+ const GLuint normalBuffer = helper.normalBuffer;
+ const GLuint vaoHandle = helper.vao;
+ const GLuint dlist = helper.displayList;
+
+ glDeleteBuffers(1, &vertexBuffer);
+ glDeleteBuffers(1, &indexBuffer);
+ glDeleteBuffers(1, &normalBuffer);
+ glDeleteVertexArraysAPPLE(1, &vaoHandle);
+
+ glDeleteLists(1, dlist);
+
+ helper.indexBuffer = 0;
+ helper.vertexBuffer = 0;
+ helper.normalBuffer = 0;
+ helper.vao = 0;
+ helper.displayList = 0;
+ }
+
+ [modelMeshes release];
+ modelMeshes = nil;
+}
+
+- (void) drawMeshesInContext:(CGLContextObj)cgl_ctx
+{
+ for(MeshHelper* helper in modelMeshes)
+ {
+ // Set up material state.
+ glCallList(helper.displayList);
+ }
+}
+
+
+- (void) loadTexturesInContext:(CGLContextObj)cgl_ctx withModelPath:(NSString*) modelPath
+{
+ if (_scene->HasTextures())
+ {
+ NSLog(@"Support for meshes with embedded textures is not implemented");
+ return;
+ }
+
+ /* getTexture Filenames and Numb of Textures */
+ for (unsigned int m = 0; m < _scene->mNumMaterials; m++)
+ {
+ int texIndex = 0;
+ aiReturn texFound = AI_SUCCESS;
+
+ aiString path; // filename
+
+ // TODO: handle other aiTextureTypes
+ while (texFound == AI_SUCCESS)
+ {
+ texFound = _scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path);
+
+ NSString* texturePath = [NSString stringWithCString:path.data encoding:[NSString defaultCStringEncoding]];
+
+ // add our path to the texture and the index to our texture dictionary.
+ [textureDictionary setValue:[NSNumber numberWithUnsignedInt:texIndex] forKey:texturePath];
+
+ texIndex++;
+ }
+ }
+
+ textureIds = (GLuint*) malloc(sizeof(GLuint) * [textureDictionary count]); //new GLuint[ [textureDictionary count] ];
+ glGenTextures([textureDictionary count], textureIds);
+
+ NSLog(@"textureDictionary: %@", textureDictionary);
+
+ // create our textures, populate them, and alter our textureID value for the specific textureID we create.
+
+ // so we can modify while we enumerate...
+ NSDictionary *textureCopy = [textureDictionary copy];
+
+ // GCD attempt.
+ //dispatch_sync(_queue, ^{
+
+ int i = 0;
+
+ for(NSString* texturePath in textureCopy)
+ {
+ NSString* fullTexturePath = [[[modelPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:[texturePath stringByStandardizingPath]] stringByStandardizingPath];
+ NSLog(@"texturePath: %@", fullTexturePath);
+
+ NSImage* textureImage = [[NSImage alloc] initWithContentsOfFile:fullTexturePath];
+
+ if(textureImage)
+ {
+ //NSLog(@"Have Texture Image");
+ NSBitmapImageRep* bitmap = [NSBitmapImageRep alloc];
+
+ [textureImage lockFocus];
+ [bitmap initWithFocusedViewRect:NSMakeRect(0, 0, textureImage.size.width, textureImage.size.height)];
+ [textureImage unlockFocus];
+
+ glActiveTexture(GL_TEXTURE0);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, textureIds[i]);
+ //glPixelStorei(GL_UNPACK_ROW_LENGTH, [bitmap pixelsWide]);
+ //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ // generate mip maps
+ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ // draw into our bitmap
+ int samplesPerPixel = [bitmap samplesPerPixel];
+
+ if(![bitmap isPlanar] && (samplesPerPixel == 3 || samplesPerPixel == 4))
+ {
+ glTexImage2D(GL_TEXTURE_2D,
+ 0,
+ //samplesPerPixel == 4 ? GL_COMPRESSED_RGBA_S3TC_DXT3_EXT : GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+ samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8,
+ [bitmap pixelsWide],
+ [bitmap pixelsHigh],
+ 0,
+ samplesPerPixel == 4 ? GL_RGBA : GL_RGB,
+ GL_UNSIGNED_BYTE,
+ [bitmap bitmapData]);
+
+ }
+
+
+ // update our dictionary to contain the proper textureID value (from out array of generated IDs)
+ [textureDictionary setValue:[NSNumber numberWithUnsignedInt:textureIds[i]] forKey:texturePath];
+
+ [bitmap release];
+ }
+ else
+ {
+ [textureDictionary removeObjectForKey:texturePath];
+ NSLog(@"Could not Load Texture: %@, removing reference to it.", fullTexturePath);
+ }
+
+ [textureImage release];
+ i++;
+ }
+ //});
+
+ [textureCopy release];
+
+}
+
+- (void) getBoundingBoxWithMinVector:(aiVector3D*) min maxVectr:(aiVector3D*) max
+{
+ aiMatrix4x4 trafo;
+ aiIdentityMatrix4(&trafo);
+
+ min->x = min->y = min->z = 1e10f;
+ max->x = max->y = max->z = -1e10f;
+
+ [self getBoundingBoxForNode:_scene->mRootNode minVector:min maxVector:max matrix:&trafo];
+}
+
+- (void) getBoundingBoxForNode:(const aiNode*)nd minVector:(aiVector3D*) min maxVector:(aiVector3D*) max matrix:(aiMatrix4x4*) trafo
+{
+ aiMatrix4x4 prev;
+ unsigned int n = 0, t;
+
+ prev = *trafo;
+ aiMultiplyMatrix4(trafo,&nd->mTransformation);
+
+ for (; n < nd->mNumMeshes; ++n)
+ {
+ const aiMesh* mesh = _scene->mMeshes[nd->mMeshes[n]];
+ for (t = 0; t < mesh->mNumVertices; ++t)
+ {
+ aiVector3D tmp = mesh->mVertices[t];
+ aiTransformVecByMatrix4(&tmp,trafo);
+
+ min->x = aisgl_min(min->x,tmp.x);
+ min->y = aisgl_min(min->y,tmp.y);
+ min->z = aisgl_min(min->z,tmp.z);
+
+ max->x = aisgl_max(max->x,tmp.x);
+ max->y = aisgl_max(max->y,tmp.y);
+ max->z = aisgl_max(max->z,tmp.z);
+ }
+ }
+
+ for (n = 0; n < nd->mNumChildren; ++n)
+ {
+ [self getBoundingBoxForNode:nd->mChildren[n] minVector:min maxVector:max matrix:trafo];
+ }
+
+ *trafo = prev;
+}
+
+
+@end