Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

glmdraw.c 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /* */
  2. #define GL_GLEXT_PROTOTYPES
  3. #include <assert.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <GL/gl.h>
  7. #include <GL/glu.h>
  8. #include "glm.h"
  9. #include "readtex.h"
  10. #include "shaderutil.h"
  11. /* defines */
  12. #define T(x) model->triangles[(x)]
  13. /* glmDraw: Renders the model to the current OpenGL context using the
  14. * mode specified.
  15. *
  16. * model - initialized GLMmodel structure
  17. * mode - a bitwise OR of values describing what is to be rendered.
  18. * GLM_NONE - render with only vertices
  19. * GLM_FLAT - render with facet normals
  20. * GLM_SMOOTH - render with vertex normals
  21. * GLM_TEXTURE - render with texture coords
  22. * GLM_COLOR - render with colors (color material)
  23. * GLM_MATERIAL - render with materials
  24. * GLM_COLOR and GLM_MATERIAL should not both be specified.
  25. * GLM_FLAT and GLM_SMOOTH should not both be specified.
  26. */
  27. GLvoid
  28. glmDraw(GLMmodel* model, GLuint mode)
  29. {
  30. GLuint i;
  31. GLMgroup* group;
  32. assert(model);
  33. assert(model->vertices);
  34. /* do a bit of warning */
  35. if (mode & GLM_FLAT && !model->facetnorms) {
  36. printf("glmDraw() warning: flat render mode requested "
  37. "with no facet normals defined.\n");
  38. mode &= ~GLM_FLAT;
  39. }
  40. if (mode & GLM_SMOOTH && !model->normals) {
  41. printf("glmDraw() warning: smooth render mode requested "
  42. "with no normals defined.\n");
  43. mode &= ~GLM_SMOOTH;
  44. }
  45. if (mode & GLM_TEXTURE && !model->texcoords) {
  46. printf("glmDraw() warning: texture render mode requested "
  47. "with no texture coordinates defined.\n");
  48. mode &= ~GLM_TEXTURE;
  49. }
  50. if (mode & GLM_FLAT && mode & GLM_SMOOTH) {
  51. printf("glmDraw() warning: flat render mode requested "
  52. "and smooth render mode requested (using smooth).\n");
  53. mode &= ~GLM_FLAT;
  54. }
  55. if (mode & GLM_COLOR && !model->materials) {
  56. printf("glmDraw() warning: color render mode requested "
  57. "with no materials defined.\n");
  58. mode &= ~GLM_COLOR;
  59. }
  60. if (mode & GLM_MATERIAL && !model->materials) {
  61. printf("glmDraw() warning: material render mode requested "
  62. "with no materials defined.\n");
  63. mode &= ~GLM_MATERIAL;
  64. }
  65. if (mode & GLM_COLOR && mode & GLM_MATERIAL) {
  66. printf("glmDraw() warning: color and material render mode requested "
  67. "using only material mode\n");
  68. mode &= ~GLM_COLOR;
  69. }
  70. if (mode & GLM_COLOR)
  71. glEnable(GL_COLOR_MATERIAL);
  72. if (mode & GLM_MATERIAL)
  73. glDisable(GL_COLOR_MATERIAL);
  74. glPushMatrix();
  75. glTranslatef(model->position[0], model->position[1], model->position[2]);
  76. glBegin(GL_TRIANGLES);
  77. group = model->groups;
  78. while (group) {
  79. if (mode & GLM_MATERIAL) {
  80. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,
  81. model->materials[group->material].ambient);
  82. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,
  83. model->materials[group->material].diffuse);
  84. glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,
  85. model->materials[group->material].specular);
  86. glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS,
  87. model->materials[group->material].shininess);
  88. }
  89. if (mode & GLM_COLOR) {
  90. glColor3fv(model->materials[group->material].diffuse);
  91. }
  92. for (i = 0; i < group->numtriangles; i++) {
  93. if (mode & GLM_FLAT)
  94. glNormal3fv(&model->facetnorms[3 * T(group->triangles[i]).findex]);
  95. if (mode & GLM_SMOOTH)
  96. glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[0]]);
  97. if (mode & GLM_TEXTURE)
  98. glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[0]]);
  99. glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[0]]);
  100. #if 0
  101. printf("%f %f %f\n",
  102. model->vertices[3 * T(group->triangles[i]).vindices[0] + X],
  103. model->vertices[3 * T(group->triangles[i]).vindices[0] + Y],
  104. model->vertices[3 * T(group->triangles[i]).vindices[0] + Z]);
  105. #endif
  106. if (mode & GLM_SMOOTH)
  107. glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[1]]);
  108. if (mode & GLM_TEXTURE)
  109. glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[1]]);
  110. glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[1]]);
  111. #if 0
  112. printf("%f %f %f\n",
  113. model->vertices[3 * T(group->triangles[i]).vindices[1] + X],
  114. model->vertices[3 * T(group->triangles[i]).vindices[1] + Y],
  115. model->vertices[3 * T(group->triangles[i]).vindices[1] + Z]);
  116. #endif
  117. if (mode & GLM_SMOOTH)
  118. glNormal3fv(&model->normals[3 * T(group->triangles[i]).nindices[2]]);
  119. if (mode & GLM_TEXTURE)
  120. glTexCoord2fv(&model->texcoords[2*T(group->triangles[i]).tindices[2]]);
  121. glVertex3fv(&model->vertices[3 * T(group->triangles[i]).vindices[2]]);
  122. #if 0
  123. printf("%f %f %f\n",
  124. model->vertices[3 * T(group->triangles[i]).vindices[2] + X],
  125. model->vertices[3 * T(group->triangles[i]).vindices[2] + Y],
  126. model->vertices[3 * T(group->triangles[i]).vindices[2] + Z]);
  127. #endif
  128. }
  129. group = group->next;
  130. }
  131. glEnd();
  132. glPopMatrix();
  133. }
  134. void
  135. glmMakeVBOs(GLMmodel *model)
  136. {
  137. uint bytes, vertexFloats, i;
  138. float *buffer;
  139. vertexFloats = 3;
  140. model->posOffset = 0;
  141. if (model->numnormals > 0) {
  142. assert(model->numnormals == model->numvertices);
  143. model->normOffset = vertexFloats * sizeof(GLfloat);
  144. vertexFloats += 3;
  145. }
  146. if (model->numtexcoords > 0) {
  147. assert(model->numtexcoords == model->numvertices);
  148. model->texOffset = vertexFloats * sizeof(GLfloat);
  149. vertexFloats += 2;
  150. }
  151. model->vertexSize = vertexFloats;
  152. bytes = (model->numvertices + 1) * vertexFloats * sizeof(float);
  153. buffer = (float *) malloc(bytes);
  154. for (i = 0; i < model->numvertices; i++) {
  155. /* copy vertex pos */
  156. uint j = 0;
  157. buffer[i * vertexFloats + j++] = model->vertices[i * 3 + 0];
  158. buffer[i * vertexFloats + j++] = model->vertices[i * 3 + 1];
  159. buffer[i * vertexFloats + j++] = model->vertices[i * 3 + 2];
  160. if (model->numnormals > 0) {
  161. buffer[i * vertexFloats + j++] = model->normals[i * 3 + 0];
  162. buffer[i * vertexFloats + j++] = model->normals[i * 3 + 1];
  163. buffer[i * vertexFloats + j++] = model->normals[i * 3 + 2];
  164. }
  165. if (model->numtexcoords > 0) {
  166. buffer[i * vertexFloats + j++] = model->texcoords[i * 2 + 0];
  167. buffer[i * vertexFloats + j++] = model->texcoords[i * 2 + 1];
  168. }
  169. }
  170. glGenBuffersARB(1, &model->vbo);
  171. glBindBufferARB(GL_ARRAY_BUFFER_ARB, model->vbo);
  172. glBufferDataARB(GL_ARRAY_BUFFER_ARB, bytes, buffer, GL_STATIC_DRAW_ARB);
  173. glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
  174. free(buffer);
  175. }
  176. static void
  177. _glmLoadTexture(GLMmaterial *mat)
  178. {
  179. if (mat->map_kd) {
  180. GLint imgWidth, imgHeight;
  181. GLenum imgFormat;
  182. GLubyte *image = NULL;
  183. glGenTextures(1, &mat->texture_kd);
  184. image = LoadRGBImage( mat->map_kd, &imgWidth, &imgHeight, &imgFormat );
  185. if (!image) {
  186. /*fprintf(stderr, "Couldn't open texture %s\n", mat->map_kd);*/
  187. free(mat->map_kd);
  188. mat->map_kd = NULL;
  189. mat->texture_kd = 0;
  190. return;
  191. }
  192. if (0)
  193. printf("load texture %s %d x %d\n", mat->map_kd, imgWidth, imgHeight);
  194. glBindTexture(GL_TEXTURE_2D, mat->texture_kd);
  195. gluBuild2DMipmaps(GL_TEXTURE_2D, 3, imgWidth, imgHeight,
  196. imgFormat, GL_UNSIGNED_BYTE, image);
  197. free(image);
  198. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
  199. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
  200. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
  201. glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  202. }
  203. }
  204. void
  205. glmLoadTextures(GLMmodel *model)
  206. {
  207. uint i;
  208. for (i = 0; i < model->nummaterials; i++) {
  209. GLMmaterial *mat = &model->materials[i];
  210. _glmLoadTexture(mat);
  211. }
  212. }
  213. void
  214. glmDrawVBO(GLMmodel *model)
  215. {
  216. GLMgroup* group;
  217. assert(model->vbo);
  218. glBindBufferARB(GL_ARRAY_BUFFER_ARB, model->vbo);
  219. glVertexPointer(3, GL_FLOAT, model->vertexSize * sizeof(float),
  220. (void *) model->posOffset);
  221. glEnableClientState(GL_VERTEX_ARRAY);
  222. if (model->numnormals > 0) {
  223. glNormalPointer(GL_FLOAT, model->vertexSize * sizeof(float),
  224. (void *) model->normOffset);
  225. glEnableClientState(GL_NORMAL_ARRAY);
  226. }
  227. if (model->numtexcoords > 0) {
  228. glTexCoordPointer(2, GL_FLOAT, model->vertexSize * sizeof(float),
  229. (void *) model->texOffset);
  230. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  231. }
  232. glPushMatrix();
  233. glTranslatef(model->position[0], model->position[1], model->position[2]);
  234. glScalef(model->scale, model->scale, model->scale);
  235. for (group = model->groups; group; group = group->next) {
  236. if (group->numtriangles > 0) {
  237. glmShaderMaterial(&model->materials[group->material]);
  238. glDrawRangeElements(GL_TRIANGLES,
  239. group->minIndex, group->maxIndex,
  240. 3 * group->numtriangles,
  241. GL_UNSIGNED_INT, group->triIndexes);
  242. }
  243. }
  244. glPopMatrix();
  245. glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
  246. glDisableClientState(GL_VERTEX_ARRAY);
  247. glDisableClientState(GL_NORMAL_ARRAY);
  248. glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  249. }
  250. /* glmList: Generates and returns a display list for the model using
  251. * the mode specified.
  252. *
  253. * model - initialized GLMmodel structure
  254. * mode - a bitwise OR of values describing what is to be rendered.
  255. * GLM_NONE - render with only vertices
  256. * GLM_FLAT - render with facet normals
  257. * GLM_SMOOTH - render with vertex normals
  258. * GLM_TEXTURE - render with texture coords
  259. * GLM_COLOR - render with colors (color material)
  260. * GLM_MATERIAL - render with materials
  261. * GLM_COLOR and GLM_MATERIAL should not both be specified.
  262. * GLM_FLAT and GLM_SMOOTH should not both be specified.
  263. */
  264. GLuint
  265. glmList(GLMmodel* model, GLuint mode)
  266. {
  267. GLuint list;
  268. list = glGenLists(1);
  269. glNewList(list, GL_COMPILE);
  270. glmDraw(model, mode);
  271. glEndList();
  272. return list;
  273. }
  274. static const char *VertexShader =
  275. "varying vec3 normal; \n"
  276. "void main() { \n"
  277. " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n"
  278. " normal = gl_NormalMatrix * gl_Normal; \n"
  279. " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
  280. "} \n";
  281. /**
  282. * Two %s substitutions:
  283. * diffuse texture? true/false
  284. * specular texture? true/false
  285. */
  286. static const char *TexFragmentShader =
  287. "uniform vec4 ambient, diffuse, specular; \n"
  288. "uniform vec4 ambientLight, diffuseLight, specularLight; \n"
  289. "uniform float shininess; \n"
  290. "uniform sampler2D diffTex; \n"
  291. "uniform samplerCube specTex; \n"
  292. "varying vec3 normal; \n"
  293. "\n"
  294. "void main() \n"
  295. "{ \n"
  296. " vec4 diffTerm, specTerm; \n"
  297. " float dotProd = max(dot(gl_LightSource[0].position.xyz, \n"
  298. " normalize(normal)), 0.0);\n"
  299. " float dotProd2 = max(dot(-gl_LightSource[0].position.xyz, \n"
  300. " normalize(normal)), 0.0);\n"
  301. " dotProd += dotProd2; \n"
  302. " \n"
  303. " diffTerm = diffuse * diffuseLight * dotProd; \n"
  304. " if (%s) \n"
  305. " diffTerm *= texture2D(diffTex, gl_TexCoord[0].st); \n"
  306. " \n"
  307. " specTerm = specular * specularLight * pow(dotProd, shininess); \n"
  308. " if (%s) \n"
  309. " specTerm *= textureCube(specTex, normal); \n"
  310. " \n"
  311. " gl_FragColor = ambient * ambientLight + diffTerm + specTerm; \n"
  312. "} \n";
  313. void
  314. glmShaderMaterial(GLMmaterial *mat)
  315. {
  316. static const float ambientLight[4] = { 0.1, 0.1, 0.1, 0.0 };
  317. static const float diffuseLight[4] = { 0.75, 0.75, 0.75, 1.0 };
  318. static const float specularLight[4] = { 1.0, 1.0, 1.0, 0.0 };
  319. if (!mat->prog) {
  320. /* make shader now */
  321. char newShader[10000];
  322. GLuint vs, fs;
  323. const char *diffuseTex = mat->texture_kd ? "true" : "false";
  324. const char *specularTex = mat->texture_ks ? "true" : "false";
  325. GLint uAmbientLight, uDiffuseLight, uSpecularLight;
  326. /* replace %d with 0 or 1 */
  327. sprintf(newShader, TexFragmentShader, diffuseTex, specularTex);
  328. if (0)
  329. printf("===== new shader =====\n%s\n============\n", newShader);
  330. vs = CompileShaderText(GL_VERTEX_SHADER, VertexShader);
  331. fs = CompileShaderText(GL_FRAGMENT_SHADER, newShader);
  332. mat->prog = LinkShaders(vs, fs);
  333. assert(mat->prog);
  334. glUseProgram(mat->prog);
  335. mat->uAmbient = glGetUniformLocation(mat->prog, "ambient");
  336. mat->uDiffuse = glGetUniformLocation(mat->prog, "diffuse");
  337. mat->uSpecular = glGetUniformLocation(mat->prog, "specular");
  338. mat->uShininess = glGetUniformLocation(mat->prog, "shininess");
  339. mat->uDiffTex = glGetUniformLocation(mat->prog, "diffTex");
  340. mat->uSpecTex = glGetUniformLocation(mat->prog, "specTex");
  341. uAmbientLight = glGetUniformLocation(mat->prog, "ambientLight");
  342. uDiffuseLight = glGetUniformLocation(mat->prog, "diffuseLight");
  343. uSpecularLight = glGetUniformLocation(mat->prog, "specularLight");
  344. glUniform4fv(mat->uAmbient, 1, mat->ambient);
  345. glUniform4fv(mat->uDiffuse, 1, mat->diffuse);
  346. glUniform4fv(mat->uSpecular, 1, mat->specular);
  347. glUniform1f(mat->uShininess, mat->shininess);
  348. glUniform1i(mat->uDiffTex, 0);
  349. glUniform1i(mat->uSpecTex, 1);
  350. glUniform4fv(uAmbientLight, 1, ambientLight);
  351. glUniform4fv(uDiffuseLight, 1, diffuseLight);
  352. glUniform4fv(uSpecularLight, 1, specularLight);
  353. }
  354. glActiveTexture(GL_TEXTURE1);
  355. if (mat->texture_ks)
  356. glBindTexture(GL_TEXTURE_CUBE_MAP, mat->texture_ks);
  357. else
  358. glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
  359. glActiveTexture(GL_TEXTURE0);
  360. if (mat->texture_kd)
  361. glBindTexture(GL_TEXTURE_2D, mat->texture_kd);
  362. else
  363. glBindTexture(GL_TEXTURE_2D, 0);
  364. if (mat->diffuse[3] < 1.0) {
  365. glEnable(GL_BLEND);
  366. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  367. }
  368. else {
  369. glDisable(GL_BLEND);
  370. }
  371. glUseProgram(mat->prog);
  372. }
  373. void
  374. glmSpecularTexture(GLMmodel *model, uint cubeTex)
  375. {
  376. uint i;
  377. for (i = 0; i < model->nummaterials; i++) {
  378. model->materials[i].texture_ks = cubeTex;
  379. }
  380. }