25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MyDocument.mm 27 KiB

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