MyDocument.mm 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. //
  2. // MyDocument.m
  3. // DisplayLinkAsyncMoviePlayer
  4. //
  5. // Created by vade on 10/26/10.
  6. // Copyright __MyCompanyName__ 2010 . All rights reserved.
  7. //
  8. #import "aiConfig.h"
  9. #import "MyDocument.h"
  10. #import <OpenGL/CGLMacro.h>
  11. #pragma mark -
  12. #pragma mark Helper Functions
  13. #define aisgl_min(x,y) (x<y?x:y)
  14. #define aisgl_max(x,y) (y>x?y:x)
  15. static void color4_to_float4(const struct aiColor4D *c, float f[4])
  16. {
  17. f[0] = c->r;
  18. f[1] = c->g;
  19. f[2] = c->b;
  20. f[3] = c->a;
  21. }
  22. static void set_float4(float f[4], float a, float b, float c, float d)
  23. {
  24. f[0] = a;
  25. f[1] = b;
  26. f[2] = c;
  27. f[3] = d;
  28. }
  29. #pragma mark -
  30. #pragma mark CVDisplayLink Callback
  31. static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeStamp *inNow,const CVTimeStamp *inOutputTime,CVOptionFlags flagsIn,CVOptionFlags *flagsOut,void *displayLinkContext)
  32. {
  33. CVReturn error = [(MyDocument*) displayLinkContext displayLinkRenderCallback:inOutputTime];
  34. return error;
  35. }
  36. #pragma mark -
  37. @implementation MyDocument
  38. @synthesize _view;
  39. - (id)init
  40. {
  41. self = [super init];
  42. if (self != nil)
  43. {
  44. // initialization code
  45. }
  46. return self;
  47. }
  48. - (NSString *)windowNibName
  49. {
  50. return @"MyDocument";
  51. }
  52. - (void)windowControllerDidLoadNib:(NSWindowController *)windowController
  53. {
  54. [super windowControllerDidLoadNib:windowController];
  55. NSOpenGLPixelFormatAttribute attributes[] =
  56. {
  57. NSOpenGLPFADoubleBuffer,
  58. NSOpenGLPFAAccelerated,
  59. NSOpenGLPFADepthSize, 24,
  60. NSOpenGLPFAMultisample,
  61. NSOpenGLPFASampleBuffers, 2,
  62. (NSOpenGLPixelFormatAttribute) 0
  63. };
  64. _glPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
  65. if(!_glPixelFormat)
  66. NSLog(@"Error creating PF");
  67. _glContext = [[NSOpenGLContext alloc] initWithFormat:_glPixelFormat shareContext:nil];
  68. const GLint one = 1;
  69. [_glContext setValues:&one forParameter:NSOpenGLCPSwapInterval];
  70. [_glContext setView:_view];
  71. // Set up initial GL state.
  72. CGLContextObj cgl_ctx = (CGLContextObj)[_glContext CGLContextObj];
  73. glEnable(GL_MULTISAMPLE);
  74. glClearColor(0.3, 0.3, 0.3, 0.3);
  75. // enable color tracking
  76. //glEnable(GL_COLOR_MATERIAL);
  77. glEnable(GL_BLEND);
  78. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  79. glEnable(GL_DEPTH_TEST);
  80. glDepthFunc(GL_LEQUAL);
  81. glDepthMask(GL_TRUE);
  82. glEnable(GL_NORMALIZE);
  83. glEnable(GL_TEXTURE_2D);
  84. glShadeModel(GL_SMOOTH);
  85. glEnable(GL_LIGHTING);
  86. GLfloat global_ambient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
  87. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
  88. GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
  89. glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
  90. GLfloat diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
  91. glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
  92. GLfloat ambient[] = {0.2, 0.2f, 0.2f, 0.2f};
  93. glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
  94. GLfloat position[] = { 1.0f, 1.0f, 1.0f, 1.0f};
  95. glLightfv(GL_LIGHT0, GL_POSITION, position);
  96. glEnable(GL_LIGHT0);
  97. // This is the only client state that always has to be set.
  98. glEnableClientState(GL_VERTEX_ARRAY);
  99. // end GL State setup.
  100. // Display Link setup.
  101. CVReturn error = kCVReturnSuccess;
  102. error = CVDisplayLinkCreateWithActiveCGDisplays(&_displayLink);
  103. if(error == kCVReturnError)
  104. NSLog(@"Error Creating DisplayLink");
  105. error = CVDisplayLinkSetOutputCallback(_displayLink,MyDisplayLinkCallback, self);
  106. if(error == kCVReturnError)
  107. NSLog(@"Error Setting DisplayLink Callback");
  108. error = CVDisplayLinkStart(_displayLink);
  109. if(error == kCVReturnError)
  110. NSLog(@"Error Starting DisplayLink");
  111. NSOpenPanel* openPanel = [NSOpenPanel openPanel];
  112. [openPanel beginSheetModalForWindow:[_view window] completionHandler:^(NSInteger result)
  113. {
  114. if (result == NSOKButton)
  115. {
  116. [openPanel orderOut:self]; // close panel before we might present an error
  117. if([[NSFileManager defaultManager] fileExistsAtPath:[openPanel filename]])
  118. {
  119. // Load our new path.
  120. // only ever give us triangles.
  121. aiSetImportPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT );
  122. NSUInteger aiPostProccesFlags;
  123. switch (2)
  124. {
  125. case 0:
  126. aiPostProccesFlags = aiProcessPreset_TargetRealtime_Fast;
  127. break;
  128. case 1:
  129. aiPostProccesFlags = aiProcessPreset_TargetRealtime_Quality;
  130. break;
  131. case 2:
  132. aiPostProccesFlags = aiProcessPreset_TargetRealtime_MaxQuality;
  133. break;
  134. default:
  135. aiPostProccesFlags = aiProcessPreset_TargetRealtime_MaxQuality;
  136. break;
  137. }
  138. // aiProcess_FlipUVs is needed for VAO / VBOs, not sure why.
  139. _scene = (aiScene*) aiImportFile([[openPanel filename] cStringUsingEncoding:[NSString defaultCStringEncoding]], aiPostProccesFlags | aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_PreTransformVertices | 0 );
  140. if (_scene)
  141. {
  142. textureDictionary = [[NSMutableDictionary alloc] initWithCapacity:5];
  143. // Why do I need to cast this !?
  144. CGLContextObj cgl_ctx = (CGLContextObj)[_glContext CGLContextObj];
  145. CGLLockContext(cgl_ctx);
  146. [self loadTexturesInContext:cgl_ctx withModelPath:[[openPanel filename] stringByStandardizingPath]];
  147. //NSDictionary* userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithPointer:cgl_ctx], @"context", [self.inputModelPath stringByStandardizingPath], @"path", nil ];
  148. //[self performSelectorInBackground:@selector(loadTexturesInBackground:) withObject:userInfo];
  149. [self getBoundingBoxWithMinVector:&scene_min maxVectr:&scene_max];
  150. scene_center.x = (scene_min.x + scene_max.x) / 2.0f;
  151. scene_center.y = (scene_min.y + scene_max.y) / 2.0f;
  152. scene_center.z = (scene_min.z + scene_max.z) / 2.0f;
  153. // optional normalized scaling
  154. normalizedScale = scene_max.x-scene_min.x;
  155. normalizedScale = aisgl_max(scene_max.y - scene_min.y,normalizedScale);
  156. normalizedScale = aisgl_max(scene_max.z - scene_min.z,normalizedScale);
  157. normalizedScale = 1.f / normalizedScale;
  158. if(_scene->HasAnimations())
  159. NSLog(@"scene has animations");
  160. [self createGLResourcesInContext:cgl_ctx];
  161. CGLUnlockContext(cgl_ctx);
  162. }
  163. }
  164. }
  165. }]; // end block handler
  166. }
  167. - (void) close
  168. {
  169. CVDisplayLinkStop(_displayLink);
  170. CVDisplayLinkRelease(_displayLink);
  171. if(_scene)
  172. {
  173. aiReleaseImport(_scene);
  174. _scene = NULL;
  175. CGLContextObj cgl_ctx = (CGLContextObj)[_glContext CGLContextObj];
  176. glDeleteTextures([textureDictionary count], textureIds);
  177. [textureDictionary release];
  178. textureDictionary = nil;
  179. free(textureIds);
  180. textureIds = NULL;
  181. [self deleteGLResourcesInContext:cgl_ctx];
  182. }
  183. [_glContext release];
  184. _glContext = nil;
  185. [_glPixelFormat release];
  186. _glPixelFormat = nil;
  187. [super close];
  188. }
  189. - (CVReturn)displayLinkRenderCallback:(const CVTimeStamp *)timeStamp
  190. {
  191. CVReturn rv = kCVReturnError;
  192. NSAutoreleasePool *pool;
  193. pool = [[NSAutoreleasePool alloc] init];
  194. {
  195. [self render];
  196. rv = kCVReturnSuccess;
  197. }
  198. [pool release];
  199. return rv;
  200. }
  201. - (void) render
  202. {
  203. CGLContextObj cgl_ctx = (CGLContextObj)[_glContext CGLContextObj];
  204. CGLLockContext(cgl_ctx);
  205. [_glContext update];
  206. glMatrixMode(GL_PROJECTION);
  207. glLoadIdentity();
  208. glViewport(0, 0, _view.frame.size.width, _view.frame.size.height);
  209. GLfloat aspect = _view.frame.size.height/_view.frame.size.width;
  210. glOrtho(-1, 1, - (aspect), aspect, -10, 10);
  211. glMatrixMode(GL_MODELVIEW);
  212. glLoadIdentity();
  213. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  214. glTranslated(0.0, 0.0, 1.0);
  215. // Draw our GL model.
  216. if(_scene)
  217. {
  218. glScaled(normalizedScale , normalizedScale, normalizedScale);
  219. // center the model
  220. glTranslated( -scene_center.x, -scene_center.y, -scene_center.z);
  221. glScaled(2.0, 2.0, 2.0);
  222. static float i = 0;
  223. i+=0.5;
  224. glRotated(i, 0, 1, 0);
  225. [self drawMeshesInContext:cgl_ctx];
  226. }
  227. CGLUnlockContext(cgl_ctx);
  228. CGLFlushDrawable(cgl_ctx);
  229. }
  230. #pragma mark -
  231. #pragma mark Loading
  232. // Inspired by LoadAsset() & CreateAssetData() from AssimpView D3D project
  233. - (void) createGLResourcesInContext:(CGLContextObj)cgl_ctx
  234. {
  235. // create new mesh helpers for each mesh, will populate their data later.
  236. modelMeshes = [[NSMutableArray alloc] initWithCapacity:_scene->mNumMeshes];
  237. // create OpenGL buffers and populate them based on each meshes pertinant info.
  238. for (unsigned int i = 0; i < _scene->mNumMeshes; ++i)
  239. {
  240. NSLog(@"%u", i);
  241. // current mesh we are introspecting
  242. const aiMesh* mesh = _scene->mMeshes[i];
  243. // the current meshHelper we will be populating data into.
  244. MeshHelper* meshHelper = [[MeshHelper alloc] init];
  245. // Handle material info
  246. aiMaterial* mtl = _scene->mMaterials[mesh->mMaterialIndex];
  247. // Textures
  248. int texIndex = 0;
  249. aiString texPath;
  250. if(AI_SUCCESS == mtl->GetTexture(aiTextureType_DIFFUSE, texIndex, &texPath))
  251. {
  252. NSString* textureKey = [NSString stringWithCString:texPath.data encoding:[NSString defaultCStringEncoding]];
  253. //bind texture
  254. NSNumber* textureNumber = (NSNumber*)[textureDictionary valueForKey:textureKey];
  255. //NSLog(@"applyMaterialInContext: have texture %i", [textureNumber unsignedIntValue]);
  256. meshHelper.textureID = [textureNumber unsignedIntValue];
  257. }
  258. else
  259. meshHelper.textureID = 0;
  260. // Colors
  261. aiColor4D dcolor = aiColor4D(0.8f, 0.8f, 0.8f, 1.0f);
  262. if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_DIFFUSE, &dcolor))
  263. [meshHelper setDiffuseColor:&dcolor];
  264. aiColor4D scolor = aiColor4D(0.0f, 0.0f, 0.0f, 1.0f);
  265. if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_SPECULAR, &scolor))
  266. [meshHelper setSpecularColor:&scolor];
  267. aiColor4D acolor = aiColor4D(0.2f, 0.2f, 0.2f, 1.0f);
  268. if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_AMBIENT, &acolor))
  269. [meshHelper setAmbientColor:&acolor];
  270. aiColor4D ecolor = aiColor4D(0.0f, 0.0f, 0.0f, 1.0f);
  271. if(AI_SUCCESS == aiGetMaterialColor(mtl, AI_MATKEY_COLOR_EMISSIVE, &ecolor))
  272. [meshHelper setEmissiveColor:&ecolor];
  273. // Culling
  274. unsigned int max = 1;
  275. int two_sided;
  276. if((AI_SUCCESS == aiGetMaterialIntegerArray(mtl, AI_MATKEY_TWOSIDED, &two_sided, &max)) && two_sided)
  277. [meshHelper setTwoSided:YES];
  278. else
  279. [meshHelper setTwoSided:NO];
  280. // Create a VBO for our vertices
  281. GLuint vhandle;
  282. glGenBuffers(1, &vhandle);
  283. glBindBuffer(GL_ARRAY_BUFFER, vhandle);
  284. glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * mesh->mNumVertices, NULL, GL_STATIC_DRAW);
  285. // populate vertices
  286. Vertex* verts = (Vertex*)glMapBuffer(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
  287. for (unsigned int x = 0; x < mesh->mNumVertices; ++x)
  288. {
  289. verts->vPosition = mesh->mVertices[x];
  290. if (NULL == mesh->mNormals)
  291. verts->vNormal = aiVector3D(0.0f,0.0f,0.0f);
  292. else
  293. verts->vNormal = mesh->mNormals[x];
  294. if (NULL == mesh->mTangents)
  295. {
  296. verts->vTangent = aiVector3D(0.0f,0.0f,0.0f);
  297. verts->vBitangent = aiVector3D(0.0f,0.0f,0.0f);
  298. }
  299. else
  300. {
  301. verts->vTangent = mesh->mTangents[x];
  302. verts->vBitangent = mesh->mBitangents[x];
  303. }
  304. if (mesh->HasVertexColors(0))
  305. {
  306. verts->dColorDiffuse = mesh->mColors[0][x];
  307. }
  308. else
  309. verts->dColorDiffuse = aiColor4D(1.0, 1.0, 1.0, 1.0);
  310. // This varies slightly form Assimp View, we support the 3rd texture component.
  311. if (mesh->HasTextureCoords(0))
  312. verts->vTextureUV = mesh->mTextureCoords[0][x];
  313. else
  314. verts->vTextureUV = aiVector3D(0.5f,0.5f, 0.0f);
  315. if (mesh->HasTextureCoords(1))
  316. verts->vTextureUV2 = mesh->mTextureCoords[1][x];
  317. else
  318. verts->vTextureUV2 = aiVector3D(0.5f,0.5f, 0.0f);
  319. // TODO: handle Bone indices and weights
  320. /* if( mesh->HasBones())
  321. {
  322. unsigned char boneIndices[4] = { 0, 0, 0, 0 };
  323. unsigned char boneWeights[4] = { 0, 0, 0, 0 };
  324. ai_assert( weightsPerVertex[x].size() <= 4);
  325. for( unsigned int a = 0; a < weightsPerVertex[x].size(); a++)
  326. {
  327. boneIndices[a] = weightsPerVertex[x][a].mVertexId;
  328. boneWeights[a] = (unsigned char) (weightsPerVertex[x][a].mWeight * 255.0f);
  329. }
  330. memcpy( verts->mBoneIndices, boneIndices, sizeof( boneIndices));
  331. memcpy( verts->mBoneWeights, boneWeights, sizeof( boneWeights));
  332. }
  333. else
  334. */
  335. {
  336. memset( verts->mBoneIndices, 0, sizeof( verts->mBoneIndices));
  337. memset( verts->mBoneWeights, 0, sizeof( verts->mBoneWeights));
  338. }
  339. ++verts;
  340. }
  341. glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); //invalidates verts
  342. glBindBuffer(GL_ARRAY_BUFFER, 0);
  343. // set the mesh vertex buffer handle to our new vertex buffer.
  344. meshHelper.vertexBuffer = vhandle;
  345. // Create Index Buffer
  346. // populate the index buffer.
  347. NSUInteger nidx;
  348. switch (mesh->mPrimitiveTypes)
  349. {
  350. case aiPrimitiveType_POINT:
  351. nidx = 1;break;
  352. case aiPrimitiveType_LINE:
  353. nidx = 2;break;
  354. case aiPrimitiveType_TRIANGLE:
  355. nidx = 3;break;
  356. default: assert(false);
  357. }
  358. // create the index buffer
  359. GLuint ihandle;
  360. glGenBuffers(1, &ihandle);
  361. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ihandle);
  362. glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * mesh->mNumFaces * nidx, NULL, GL_STATIC_DRAW);
  363. unsigned int* indices = (unsigned int*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_ARB);
  364. // now fill the index buffer
  365. for (unsigned int x = 0; x < mesh->mNumFaces; ++x)
  366. {
  367. for (unsigned int a = 0; a < nidx; ++a)
  368. {
  369. // if(mesh->mFaces[x].mNumIndices != 3)
  370. // NSLog(@"whoa dont have 3 indices...");
  371. *indices++ = mesh->mFaces[x].mIndices[a];
  372. }
  373. }
  374. glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
  375. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  376. // set the mesh index buffer handle to our new index buffer.
  377. meshHelper.indexBuffer = ihandle;
  378. meshHelper.numIndices = mesh->mNumFaces * nidx;
  379. // create the normal buffer. Assimp View creates a second normal buffer. Unsure why. Using only the interleaved normals for now.
  380. // This is here for reference.
  381. /* GLuint nhandle;
  382. glGenBuffers(1, &nhandle);
  383. glBindBuffer(GL_ARRAY_BUFFER, nhandle);
  384. glBufferData(GL_ARRAY_BUFFER, sizeof(aiVector3D)* mesh->mNumVertices, NULL, GL_STATIC_DRAW);
  385. // populate normals
  386. aiVector3D* normals = (aiVector3D*)glMapBuffer(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
  387. for (unsigned int x = 0; x < mesh->mNumVertices; ++x)
  388. {
  389. aiVector3D vNormal = mesh->mNormals[x];
  390. *normals = vNormal;
  391. ++normals;
  392. }
  393. glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); //invalidates verts
  394. glBindBuffer(GL_ARRAY_BUFFER, 0);
  395. meshHelper.normalBuffer = nhandle;
  396. */
  397. // Create VAO and populate it
  398. GLuint vaoHandle;
  399. glGenVertexArraysAPPLE(1, &vaoHandle);
  400. glBindVertexArrayAPPLE(vaoHandle);
  401. glBindBuffer(GL_ARRAY_BUFFER, meshHelper.vertexBuffer);
  402. glEnableClientState(GL_NORMAL_ARRAY);
  403. glNormalPointer(GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(12));
  404. glEnableClientState(GL_COLOR_ARRAY);
  405. glColorPointer(4, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(24));
  406. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  407. glTexCoordPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(64));
  408. //TODO: handle second texture
  409. // 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.
  410. glEnableClientState(GL_VERTEX_ARRAY);
  411. glVertexPointer(3, GL_FLOAT, sizeof(Vertex), 0);
  412. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshHelper.indexBuffer);
  413. glBindVertexArrayAPPLE(0);
  414. // save the VAO handle into our mesh helper
  415. meshHelper.vao = vaoHandle;
  416. // Create the display list
  417. GLuint list = glGenLists(1);
  418. glNewList(list, GL_COMPILE);
  419. float dc[4];
  420. float sc[4];
  421. float ac[4];
  422. float emc[4];
  423. // Material colors and properties
  424. color4_to_float4([meshHelper diffuseColor], dc);
  425. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, dc);
  426. color4_to_float4([meshHelper specularColor], sc);
  427. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, sc);
  428. color4_to_float4([meshHelper ambientColor], ac);
  429. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ac);
  430. color4_to_float4(meshHelper.emissiveColor, emc);
  431. glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emc);
  432. glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  433. // Culling
  434. if(meshHelper.twoSided)
  435. glEnable(GL_CULL_FACE);
  436. else
  437. glDisable(GL_CULL_FACE);
  438. // Texture Binding
  439. glBindTexture(GL_TEXTURE_2D, meshHelper.textureID);
  440. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
  441. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  442. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  443. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  444. // This binds the whole VAO, inheriting all the buffer and client state. Weeee
  445. glBindVertexArrayAPPLE(meshHelper.vao);
  446. glDrawElements(GL_TRIANGLES, meshHelper.numIndices, GL_UNSIGNED_INT, 0);
  447. glEndList();
  448. meshHelper.displayList = list;
  449. // Whew, done. Save all of this shit.
  450. [modelMeshes addObject:meshHelper];
  451. [meshHelper release];
  452. }
  453. }
  454. - (void) deleteGLResourcesInContext:(CGLContextObj)cgl_ctx
  455. {
  456. for(MeshHelper* helper in modelMeshes)
  457. {
  458. const GLuint indexBuffer = helper.indexBuffer;
  459. const GLuint vertexBuffer = helper.vertexBuffer;
  460. const GLuint normalBuffer = helper.normalBuffer;
  461. const GLuint vaoHandle = helper.vao;
  462. const GLuint dlist = helper.displayList;
  463. glDeleteBuffers(1, &vertexBuffer);
  464. glDeleteBuffers(1, &indexBuffer);
  465. glDeleteBuffers(1, &normalBuffer);
  466. glDeleteVertexArraysAPPLE(1, &vaoHandle);
  467. glDeleteLists(1, dlist);
  468. helper.indexBuffer = 0;
  469. helper.vertexBuffer = 0;
  470. helper.normalBuffer = 0;
  471. helper.vao = 0;
  472. helper.displayList = 0;
  473. }
  474. [modelMeshes release];
  475. modelMeshes = nil;
  476. }
  477. - (void) drawMeshesInContext:(CGLContextObj)cgl_ctx
  478. {
  479. for(MeshHelper* helper in modelMeshes)
  480. {
  481. // Set up meterial state.
  482. glCallList(helper.displayList);
  483. }
  484. }
  485. - (void) loadTexturesInContext:(CGLContextObj)cgl_ctx withModelPath:(NSString*) modelPath
  486. {
  487. if (_scene->HasTextures())
  488. {
  489. NSLog(@"Support for meshes with embedded textures is not implemented");
  490. return;
  491. }
  492. /* getTexture Filenames and Numb of Textures */
  493. for (unsigned int m = 0; m < _scene->mNumMaterials; m++)
  494. {
  495. int texIndex = 0;
  496. aiReturn texFound = AI_SUCCESS;
  497. aiString path; // filename
  498. // TODO: handle other aiTextureTypes
  499. while (texFound == AI_SUCCESS)
  500. {
  501. texFound = _scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path);
  502. NSString* texturePath = [NSString stringWithCString:path.data encoding:[NSString defaultCStringEncoding]];
  503. // add our path to the texture and the index to our texture dictionary.
  504. [textureDictionary setValue:[NSNumber numberWithUnsignedInt:texIndex] forKey:texturePath];
  505. texIndex++;
  506. }
  507. }
  508. textureIds = (GLuint*) malloc(sizeof(GLuint) * [textureDictionary count]); //new GLuint[ [textureDictionary count] ];
  509. glGenTextures([textureDictionary count], textureIds);
  510. NSLog(@"textureDictionary: %@", textureDictionary);
  511. // create our textures, populate them, and alter our textureID value for the specific textureID we create.
  512. // so we can modify while we enumerate...
  513. NSDictionary *textureCopy = [textureDictionary copy];
  514. // GCD attempt.
  515. //dispatch_sync(_queue, ^{
  516. int i = 0;
  517. for(NSString* texturePath in textureCopy)
  518. {
  519. NSString* fullTexturePath = [[[modelPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:[texturePath stringByStandardizingPath]] stringByStandardizingPath];
  520. NSLog(@"texturePath: %@", fullTexturePath);
  521. NSImage* textureImage = [[NSImage alloc] initWithContentsOfFile:fullTexturePath];
  522. if(textureImage)
  523. {
  524. //NSLog(@"Have Texture Image");
  525. NSBitmapImageRep* bitmap = [NSBitmapImageRep alloc];
  526. [textureImage lockFocus];
  527. [bitmap initWithFocusedViewRect:NSMakeRect(0, 0, textureImage.size.width, textureImage.size.height)];
  528. [textureImage unlockFocus];
  529. glActiveTexture(GL_TEXTURE0);
  530. glEnable(GL_TEXTURE_2D);
  531. glBindTexture(GL_TEXTURE_2D, textureIds[i]);
  532. //glPixelStorei(GL_UNPACK_ROW_LENGTH, [bitmap pixelsWide]);
  533. //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  534. // generate mip maps
  535. glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
  536. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
  537. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  538. // draw into our bitmap
  539. int samplesPerPixel = [bitmap samplesPerPixel];
  540. if(![bitmap isPlanar] && (samplesPerPixel == 3 || samplesPerPixel == 4))
  541. {
  542. glTexImage2D(GL_TEXTURE_2D,
  543. 0,
  544. //samplesPerPixel == 4 ? GL_COMPRESSED_RGBA_S3TC_DXT3_EXT : GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
  545. samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8,
  546. [bitmap pixelsWide],
  547. [bitmap pixelsHigh],
  548. 0,
  549. samplesPerPixel == 4 ? GL_RGBA : GL_RGB,
  550. GL_UNSIGNED_BYTE,
  551. [bitmap bitmapData]);
  552. }
  553. // update our dictionary to contain the proper textureID value (from out array of generated IDs)
  554. [textureDictionary setValue:[NSNumber numberWithUnsignedInt:textureIds[i]] forKey:texturePath];
  555. [bitmap release];
  556. }
  557. else
  558. {
  559. [textureDictionary removeObjectForKey:texturePath];
  560. NSLog(@"Could not Load Texture: %@, removing reference to it.", fullTexturePath);
  561. }
  562. [textureImage release];
  563. i++;
  564. }
  565. //});
  566. [textureCopy release];
  567. }
  568. - (void) getBoundingBoxWithMinVector:(struct aiVector3D*) min maxVectr:(struct aiVector3D*) max
  569. {
  570. struct aiMatrix4x4 trafo;
  571. aiIdentityMatrix4(&trafo);
  572. min->x = min->y = min->z = 1e10f;
  573. max->x = max->y = max->z = -1e10f;
  574. [self getBoundingBoxForNode:_scene->mRootNode minVector:min maxVector:max matrix:&trafo];
  575. }
  576. - (void) getBoundingBoxForNode:(const struct aiNode*)nd minVector:(struct aiVector3D*) min maxVector:(struct aiVector3D*) max matrix:(struct aiMatrix4x4*) trafo
  577. {
  578. struct aiMatrix4x4 prev;
  579. unsigned int n = 0, t;
  580. prev = *trafo;
  581. aiMultiplyMatrix4(trafo,&nd->mTransformation);
  582. for (; n < nd->mNumMeshes; ++n)
  583. {
  584. const struct aiMesh* mesh = _scene->mMeshes[nd->mMeshes[n]];
  585. for (t = 0; t < mesh->mNumVertices; ++t)
  586. {
  587. struct aiVector3D tmp = mesh->mVertices[t];
  588. aiTransformVecByMatrix4(&tmp,trafo);
  589. min->x = aisgl_min(min->x,tmp.x);
  590. min->y = aisgl_min(min->y,tmp.y);
  591. min->z = aisgl_min(min->z,tmp.z);
  592. max->x = aisgl_max(max->x,tmp.x);
  593. max->y = aisgl_max(max->y,tmp.y);
  594. max->z = aisgl_max(max->z,tmp.z);
  595. }
  596. }
  597. for (n = 0; n < nd->mNumChildren; ++n)
  598. {
  599. [self getBoundingBoxForNode:nd->mChildren[n] minVector:min maxVector:max matrix:trafo];
  600. }
  601. *trafo = prev;
  602. }
  603. @end