LEFT | RIGHT |
(no file at all) | |
1 /* | 1 /* |
2 * ***** BEGIN GPL LICENSE BLOCK ***** | 2 * ***** BEGIN GPL LICENSE BLOCK ***** |
3 * | 3 * |
4 * This program is free software; you can redistribute it and/or | 4 * This program is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU General Public License | 5 * modify it under the terms of the GNU General Public License |
6 * as published by the Free Software Foundation; either version 2 | 6 * as published by the Free Software Foundation; either version 2 |
7 * of the License, or (at your option) any later version. | 7 * of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This program is distributed in the hope that it will be useful, | 9 * This program is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 * 32x32 bit masks for hinterlace stereo mode. | 79 * 32x32 bit masks for hinterlace stereo mode. |
80 * Left eye = &hinterlace_mask[0] | 80 * Left eye = &hinterlace_mask[0] |
81 * Right eye = &hinterlace_mask[1] | 81 * Right eye = &hinterlace_mask[1] |
82 */ | 82 */ |
83 static GLuint hinterlace_mask[33]; | 83 static GLuint hinterlace_mask[33]; |
84 | 84 |
85 RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, int storage) | 85 RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, int storage) |
86 :RAS_IRasterizer(canvas), | 86 :RAS_IRasterizer(canvas), |
87 m_2DCanvas(canvas), | 87 m_2DCanvas(canvas), |
88 m_fogenabled(false), | 88 m_fogenabled(false), |
89 m_time(0.0), | |
90 m_campos(0.0f, 0.0f, 0.0f), | |
91 m_camortho(false), | |
92 m_stereomode(RAS_STEREO_NOSTEREO), | |
93 m_curreye(RAS_STEREO_LEFTEYE), | |
94 m_eyeseparation(0.0), | |
95 m_focallength(0.0), | |
96 m_setfocallength(false), | |
97 m_noOfScanlines(32), | |
98 m_motionblur(0), | |
99 m_motionblurvalue(-1.0), | 89 m_motionblurvalue(-1.0), |
100 m_usingoverrideshader(false), | |
101 m_clientobject(NULL), | |
102 m_auxilaryClientInfo(NULL), | |
103 m_texco_num(0), | 90 m_texco_num(0), |
104 m_attrib_num(0), | 91 m_attrib_num(0), |
105 » //m_last_alphablend(GPU_BLEND_SOLID), | 92 » //m_last_blendmode(GPU_BLEND_SOLID), |
106 m_last_frontface(true), | 93 m_last_frontface(true), |
107 » m_materialCachingInfo(0), | 94 » m_materialCachingInfo(0) |
108 » m_storage_type(storage) | |
109 { | 95 { |
110 m_viewmatrix.setIdentity(); | |
111 m_viewinvmatrix.setIdentity(); | |
112 ········ | |
113 for (int i = 0; i < 32; i++) | |
114 { | |
115 left_eye_vinterlace_mask[i] = 0x55555555; | |
116 right_eye_vinterlace_mask[i] = 0xAAAAAAAA; | |
117 hinterlace_mask[i] = (i&1)*0xFFFFFFFF; | |
118 } | |
119 hinterlace_mask[32] = 0; | |
120 | |
121 m_prevafvalue = GPU_get_anisotropic(); | |
122 | |
123 if (m_storage_type == RAS_VBO /*|| m_storage_type == RAS_AUTO_STORAGE &&
GLEW_ARB_vertex_buffer_object*/) | |
124 { | |
125 m_storage = new RAS_StorageVBO(&m_texco_num, m_texco, &m_attrib_
num, m_attrib, m_attrib_layer); | |
126 m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m
_attrib_num, m_attrib, m_attrib_layer); | |
127 m_storage_type = RAS_VBO; | |
128 } | |
129 else if ((m_storage_type == RAS_VA) || (m_storage_type == RAS_AUTO_STORA
GE && GLEW_VERSION_1_1)) | |
130 { | |
131 m_storage = new RAS_StorageVA(&m_texco_num, m_texco, &m_attrib_n
um, m_attrib, m_attrib_layer); | |
132 m_failsafe_storage = new RAS_StorageIM(&m_texco_num, m_texco, &m
_attrib_num, m_attrib, m_attrib_layer); | |
133 m_storage_type = RAS_VA; | |
134 } | |
135 else | |
136 { | |
137 m_storage = m_failsafe_storage = new RAS_StorageIM(&m_texco_num,
m_texco, &m_attrib_num, m_attrib, m_attrib_layer); | |
138 m_storage_type = RAS_IMMEDIATE; | |
139 } | |
140 | |
141 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &m_numgllights); | |
142 if (m_numgllights < 8) | |
143 m_numgllights = 8; | |
144 } | |
145 | |
146 | |
147 | |
148 RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer() | |
149 { | |
150 // Restore the previous AF value | |
151 GPU_set_anisotropic(m_prevafvalue); | |
152 if (m_failsafe_storage && m_failsafe_storage != m_storage) | |
153 delete m_failsafe_storage; | |
154 | |
155 if (m_storage) | |
156 delete m_storage; | |
157 } | |
158 | |
159 bool RAS_OpenGLRasterizer::Init() | |
160 { | |
161 bool storage_init; | |
162 GPU_state_init(); | |
163 | |
164 | |
165 m_ambr = 0.0f; | |
166 m_ambg = 0.0f; | |
167 m_ambb = 0.0f; | |
168 | |
169 glDisable(GL_BLEND); | |
170 glDisable(GL_ALPHA_TEST); | |
171 //m_last_alphablend = GPU_BLEND_SOLID; | |
172 GPU_set_material_alpha_blend(GPU_BLEND_SOLID); | |
173 | |
174 glFrontFace(GL_CCW); | |
175 m_last_frontface = true; | |
176 | |
177 m_redback = 0.4375; | |
178 m_greenback = 0.4375; | |
179 m_blueback = 0.4375; | |
180 m_alphaback = 0.0; | |
181 | |
182 glClearColor(m_redback,m_greenback,m_blueback,m_alphaback); | |
183 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
184 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
185 | |
186 | |
187 glShadeModel(GL_SMOOTH); | |
188 | |
189 storage_init = m_storage->Init(); | |
190 | |
191 return true && storage_init; | |
192 } | |
193 | |
194 | |
195 void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue) | |
196 { | |
197 m_ambr = red; | |
198 m_ambg = green; | |
199 m_ambb = blue; | |
200 } | |
201 | |
202 | |
203 void RAS_OpenGLRasterizer::SetAmbient(float factor) | |
204 { | |
205 float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f }; | |
206 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); | |
207 } | |
208 | |
209 | |
210 void RAS_OpenGLRasterizer::SetBackColor(float red, | |
211
float green, | |
212
float blue, | |
213
float alpha) | |
214 { | |
215 m_redback = red; | |
216 m_greenback = green; | |
217 m_blueback = blue; | |
218 m_alphaback = alpha; | |
219 } | |
220 | |
221 | |
222 | |
223 void RAS_OpenGLRasterizer::SetFogColor(float r, | |
224 float
g, | |
225 float
b) | |
226 { | |
227 m_fogr = r; | |
228 m_fogg = g; | |
229 m_fogb = b; | |
230 m_fogenabled = true; | |
231 } | |
232 | |
233 | |
234 | |
235 void RAS_OpenGLRasterizer::SetFogStart(float start) | |
236 { | |
237 m_fogstart = start; | |
238 m_fogenabled = true; | |
239 } | |
240 | |
241 | |
242 | |
243 void RAS_OpenGLRasterizer::SetFogEnd(float fogend) | |
244 { | |
245 m_fogdist = fogend; | |
246 m_fogenabled = true; | |
247 } | |
248 | |
249 | |
250 | |
251 void RAS_OpenGLRasterizer::SetFog(float start, | |
252 float dist, | |
253 float r, | |
254 float g, | |
255 float b) | |
256 { | |
257 m_fogstart = start; | |
258 m_fogdist = dist; | |
259 m_fogr = r; | |
260 m_fogg = g; | |
261 m_fogb = b; | |
262 m_fogenabled = true; | |
263 } | |
264 | |
265 | |
266 | |
267 void RAS_OpenGLRasterizer::DisableFog() | |
268 { | |
269 m_fogenabled = false; | |
270 } | |
271 | |
272 bool RAS_OpenGLRasterizer::IsFogEnabled() | |
273 { | |
274 return m_fogenabled; | |
275 } | |
276 | |
277 | |
278 void RAS_OpenGLRasterizer::DisplayFog() | |
279 { | |
280 if ((m_drawingmode >= KX_SOLID) && m_fogenabled) | |
281 { | |
282 float params[5]; | |
283 glFogi(GL_FOG_MODE, GL_LINEAR); | |
284 glFogf(GL_FOG_DENSITY, 0.1f); | |
285 glFogf(GL_FOG_START, m_fogstart); | |
286 glFogf(GL_FOG_END, m_fogstart + m_fogdist); | |
287 params[0] = m_fogr; | |
288 params[1] = m_fogg; | |
289 params[2] = m_fogb; | |
290 params[3] = 0.0; | |
291 glFogfv(GL_FOG_COLOR, params);· | |
292 glEnable(GL_FOG); | |
293 }· | |
294 else | |
295 { | |
296 glDisable(GL_FOG); | |
297 } | |
298 } | |
299 | |
300 | |
301 | |
302 bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat) | |
303 { | |
304 return mat.Activate(this, m_materialCachingInfo); | |
305 } | |
306 | |
307 | |
308 | |
309 void RAS_OpenGLRasterizer::Exit() | |
310 { | |
311 | |
312 m_storage->Exit(); | |
313 | |
314 glEnable(GL_CULL_FACE); | |
315 glEnable(GL_DEPTH_TEST); | |
316 glClearDepth(1.0);· | |
317 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
318 glClearColor(m_redback, m_greenback, m_blueback, m_alphaback); | |
319 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
320 glDepthMask (GL_TRUE); | |
321 glDepthFunc(GL_LEQUAL); | |
322 glBlendFunc(GL_ONE, GL_ZERO); | |
323 ········ | |
324 glDisable(GL_POLYGON_STIPPLE); | |
325 ········ | |
326 glDisable(GL_LIGHTING); | |
327 if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) | |
328 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SINGLE_COLOR); | |
329 ········ | |
330 EndFrame(); | |
331 } | |
332 | |
333 bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) | |
334 { | |
335 m_time = time; | |
336 SetDrawingMode(drawingmode); | |
337 | |
338 // Blender camera routine destroys the settings | |
339 if (m_drawingmode < KX_SOLID) | |
340 { | |
341 glDisable(GL_CULL_FACE); | |
342 glDisable(GL_DEPTH_TEST); | |
343 } | |
344 else | |
345 { | |
346 glEnable(GL_DEPTH_TEST); | |
347 glEnable(GL_CULL_FACE); | |
348 } | |
349 | |
350 glDisable(GL_BLEND); | |
351 glDisable(GL_ALPHA_TEST); | |
352 //m_last_alphablend = GPU_BLEND_SOLID; | |
353 GPU_set_material_alpha_blend(GPU_BLEND_SOLID); | |
354 | |
355 glFrontFace(GL_CCW); | |
356 m_last_frontface = true; | |
357 | |
358 glShadeModel(GL_SMOOTH); | |
359 | |
360 glEnable(GL_MULTISAMPLE_ARB); | |
361 | |
362 m_2DCanvas->BeginFrame(); | |
363 | |
364 // Render Tools | |
365 m_clientobject = NULL; | |
366 m_lastlightlayer = -1; | |
367 m_lastauxinfo = NULL; | |
368 m_lastlighting = true; /* force disable in DisableOpenGLLights() */ | |
369 DisableOpenGLLights(); | |
370 ········ | |
371 return true; | |
372 } | |
373 | |
374 | |
375 | |
376 void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode) | |
377 { | |
378 m_drawingmode = drawingmode; | |
379 | |
380 if (m_drawingmode == KX_WIREFRAME) | |
381 glDisable(GL_CULL_FACE); | |
382 | |
383 m_storage->SetDrawingMode(drawingmode); | |
384 if (m_failsafe_storage && m_failsafe_storage != m_storage) { | |
385 m_failsafe_storage->SetDrawingMode(drawingmode); | |
386 } | |
387 } | |
388 | |
389 int RAS_OpenGLRasterizer::GetDrawingMode() | |
390 { | |
391 return m_drawingmode; | |
392 } | |
393 | |
394 | |
395 void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask) | |
396 { | |
397 glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE); | |
398 } | |
399 | |
400 | |
401 void RAS_OpenGLRasterizer::ClearColorBuffer() | |
402 { | |
403 m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback); | |
404 m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); | |
405 } | |
406 | |
407 | |
408 void RAS_OpenGLRasterizer::ClearDepthBuffer() | |
409 { | |
410 m_2DCanvas->ClearBuffer(RAS_ICanvas::DEPTH_BUFFER); | |
411 } | |
412 | |
413 | |
414 void RAS_OpenGLRasterizer::ClearCachingInfo(void) | |
415 { | |
416 m_materialCachingInfo = 0; | |
417 } | |
418 | |
419 void RAS_OpenGLRasterizer::FlushDebugShapes() | |
420 { | |
421 if (m_debugShapes.empty()) | |
422 return; | |
423 | |
424 // DrawDebugLines | |
425 GLboolean light, tex; | |
426 | |
427 light= glIsEnabled(GL_LIGHTING); | |
428 tex= glIsEnabled(GL_TEXTURE_2D); | |
429 | |
430 if (light) glDisable(GL_LIGHTING); | |
431 if (tex) glDisable(GL_TEXTURE_2D); | |
432 | |
433 //draw lines | |
434 glBegin(GL_LINES); | |
435 for (unsigned int i=0;i<m_debugShapes.size();i++) | |
436 { | |
437 if (m_debugShapes[i].m_type != OglDebugShape::LINE) | |
438 continue; | |
439 glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1
],m_debugShapes[i].m_color[2],1.f); | |
440 const MT_Scalar* fromPtr = &m_debugShapes[i].m_pos.x(); | |
441 const MT_Scalar* toPtr= &m_debugShapes[i].m_param.x(); | |
442 glVertex3dv(fromPtr); | |
443 glVertex3dv(toPtr); | |
444 } | |
445 glEnd(); | |
446 | |
447 //draw circles | |
448 for (unsigned int i=0;i<m_debugShapes.size();i++) | |
449 { | |
450 if (m_debugShapes[i].m_type != OglDebugShape::CIRCLE) | |
451 continue; | |
452 glBegin(GL_LINE_LOOP); | |
453 glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1
],m_debugShapes[i].m_color[2],1.f); | |
454 | |
455 static const MT_Vector3 worldUp(0.0, 0.0, 1.0); | |
456 MT_Vector3 norm = m_debugShapes[i].m_param; | |
457 MT_Matrix3x3 tr; | |
458 if (norm.fuzzyZero() || norm == worldUp) | |
459 { | |
460 tr.setIdentity(); | |
461 } | |
462 else | |
463 { | |
464 MT_Vector3 xaxis, yaxis; | |
465 xaxis = MT_cross(norm, worldUp); | |
466 yaxis = MT_cross(xaxis, norm); | |
467 tr.setValue(xaxis.x(), xaxis.y(), xaxis.z(), | |
468 yaxis.x(), yaxis.y(), yaxis.z(), | |
469 norm.x(), norm.y(), norm.z()); | |
470 } | |
471 MT_Scalar rad = m_debugShapes[i].m_param2.x(); | |
472 int n = (int) m_debugShapes[i].m_param2.y(); | |
473 for (int j = 0; j<n; j++) | |
474 { | |
475 MT_Scalar theta = j*M_PI*2/n; | |
476 MT_Vector3 pos(cos(theta) * rad, sin(theta) * rad, 0.0); | |
477 pos = pos*tr; | |
478 pos += m_debugShapes[i].m_pos; | |
479 const MT_Scalar* posPtr = &pos.x(); | |
480 glVertex3dv(posPtr); | |
481 } | |
482 glEnd(); | |
483 } | |
484 | |
485 if (light) glEnable(GL_LIGHTING); | |
486 if (tex) glEnable(GL_TEXTURE_2D); | |
487 | |
488 m_debugShapes.clear(); | |
489 } | |
490 | |
491 void RAS_OpenGLRasterizer::EndFrame() | |
492 { | |
493 FlushDebugShapes(); | |
494 | |
495 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | |
496 | |
497 glDisable(GL_MULTISAMPLE_ARB); | |
498 | |
499 m_2DCanvas->EndFrame(); | |
500 } | |
501 | |
502 void RAS_OpenGLRasterizer::SetRenderArea() | |
503 { | |
504 RAS_Rect area; | |
505 // only above/below stereo method needs viewport adjustment | |
506 switch (m_stereomode) | |
507 { | |
508 case RAS_STEREO_ABOVEBELOW: | |
509 switch (m_curreye) { | |
510 case RAS_STEREO_LEFTEYE: | |
511 // upper half of window | |
512 area.SetLeft(0); | |
513 area.SetBottom(m_2DCanvas->GetHeight() - | |
514 int(m_2DCanvas->GetHeight() - m_
noOfScanlines) / 2); | |
515 ········ | |
516 area.SetRight(int(m_2DCanvas->GetWidth()
)); | |
517 area.SetTop(int(m_2DCanvas->GetHeight())
); | |
518 m_2DCanvas->SetDisplayArea(&area); | |
519 break; | |
520 case RAS_STEREO_RIGHTEYE: | |
521 // lower half of window | |
522 area.SetLeft(0); | |
523 area.SetBottom(0); | |
524 area.SetRight(int(m_2DCanvas->GetWidth()
)); | |
525 area.SetTop(int(m_2DCanvas->GetHeight()
- m_noOfScanlines) / 2); | |
526 m_2DCanvas->SetDisplayArea(&area); | |
527 break; | |
528 } | |
529 break; | |
530 case RAS_STEREO_SIDEBYSIDE: | |
531 switch (m_curreye) | |
532 { | |
533 case RAS_STEREO_LEFTEYE: | |
534 // Left half of window | |
535 area.SetLeft(0); | |
536 area.SetBottom(0); | |
537 area.SetRight(m_2DCanvas->GetWidth()/2); | |
538 area.SetTop(m_2DCanvas->GetHeight()); | |
539 m_2DCanvas->SetDisplayArea(&area); | |
540 break; | |
541 case RAS_STEREO_RIGHTEYE: | |
542 // Right half of window | |
543 area.SetLeft(m_2DCanvas->GetWidth()/2); | |
544 area.SetBottom(0); | |
545 area.SetRight(m_2DCanvas->GetWidth()); | |
546 area.SetTop(m_2DCanvas->GetHeight()); | |
547 m_2DCanvas->SetDisplayArea(&area); | |
548 break; | |
549 } | |
550 break; | |
551 default: | |
552 // every available pixel | |
553 area.SetLeft(0); | |
554 area.SetBottom(0); | |
555 area.SetRight(int(m_2DCanvas->GetWidth())); | |
556 area.SetTop(int(m_2DCanvas->GetHeight())); | |
557 m_2DCanvas->SetDisplayArea(&area); | |
558 break; | |
559 } | |
560 } | |
561 ········ | |
562 void RAS_OpenGLRasterizer::SetStereoMode(const StereoMode stereomode) | |
563 { | |
564 m_stereomode = stereomode; | |
565 } | |
566 | |
567 RAS_IRasterizer::StereoMode RAS_OpenGLRasterizer::GetStereoMode() | |
568 { | |
569 return m_stereomode; | |
570 } | |
571 | |
572 bool RAS_OpenGLRasterizer::Stereo() | |
573 { | |
574 if (m_stereomode > RAS_STEREO_NOSTEREO) // > 0 | |
575 return true; | |
576 else | |
577 return false; | |
578 } | |
579 | |
580 bool RAS_OpenGLRasterizer::InterlacedStereo() | |
581 { | |
582 return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STER
EO_INTERLACED; | |
583 } | |
584 | |
585 void RAS_OpenGLRasterizer::SetEye(const StereoEye eye) | |
586 { | |
587 m_curreye = eye; | |
588 switch (m_stereomode) | |
589 { | |
590 case RAS_STEREO_QUADBUFFERED: | |
591 glDrawBuffer(m_curreye == RAS_STEREO_LEFTEYE ? GL_BACK_L
EFT : GL_BACK_RIGHT); | |
592 break; | |
593 case RAS_STEREO_ANAGLYPH: | |
594 if (m_curreye == RAS_STEREO_LEFTEYE) { | |
595 glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALS
E); | |
596 } | |
597 else { | |
598 //glAccum(GL_LOAD, 1.0); | |
599 glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_FALSE
); | |
600 ClearDepthBuffer(); | |
601 } | |
602 break; | |
603 case RAS_STEREO_VINTERLACE: | |
604 { | |
605 glEnable(GL_POLYGON_STIPPLE); | |
606 glPolygonStipple((const GLubyte*) ((m_curreye == RAS_STE
REO_LEFTEYE) ? left_eye_vinterlace_mask : right_eye_vinterlace_mask)); | |
607 if (m_curreye == RAS_STEREO_RIGHTEYE) | |
608 ClearDepthBuffer(); | |
609 break; | |
610 } | |
611 case RAS_STEREO_INTERLACED: | |
612 { | |
613 glEnable(GL_POLYGON_STIPPLE); | |
614 glPolygonStipple((const GLubyte*) &hinterlace_mask[m_cur
reye == RAS_STEREO_LEFTEYE?0:1]); | |
615 if (m_curreye == RAS_STEREO_RIGHTEYE) | |
616 ClearDepthBuffer(); | |
617 break; | |
618 } | |
619 default: | |
620 break; | |
621 } | |
622 } | |
623 | |
624 RAS_IRasterizer::StereoEye RAS_OpenGLRasterizer::GetEye() | |
625 { | |
626 return m_curreye; | |
627 } | |
628 | |
629 | |
630 void RAS_OpenGLRasterizer::SetEyeSeparation(const float eyeseparation) | |
631 { | |
632 m_eyeseparation = eyeseparation; | |
633 } | |
634 | |
635 float RAS_OpenGLRasterizer::GetEyeSeparation() | |
636 { | |
637 return m_eyeseparation; | |
638 } | |
639 | |
640 void RAS_OpenGLRasterizer::SetFocalLength(const float focallength) | |
641 { | |
642 m_focallength = focallength; | |
643 m_setfocallength = true; | |
644 } | |
645 | |
646 float RAS_OpenGLRasterizer::GetFocalLength() | |
647 { | |
648 return m_focallength; | |
649 } | |
650 | |
651 | |
652 void RAS_OpenGLRasterizer::SwapBuffers() | |
653 { | |
654 m_2DCanvas->SwapBuffers(); | |
655 } | |
656 | |
657 | |
658 | |
659 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const | |
660 { | |
661 return m_viewmatrix; | |
662 } | |
663 | |
664 const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewInvMatrix() const | |
665 { | |
666 return m_viewinvmatrix; | |
667 } | |
668 | |
669 void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms, | |
670 class RA
S_IPolyMaterial* polymat) | |
671 {· | |
672 bool obcolor = ms.m_bObjectColor; | |
673 MT_Vector4& rgba = ms.m_RGBAcolor; | |
674 RAS_MeshSlot::iterator it; | |
675 | |
676 const STR_String& mytext = ((CValue*)m_clientobject)->GetPropertyText("T
ext"); | |
677 | |
678 // handle object color | |
679 if (obcolor) { | |
680 glDisableClientState(GL_COLOR_ARRAY); | |
681 glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); | |
682 } | |
683 else | |
684 glEnableClientState(GL_COLOR_ARRAY); | |
685 | |
686 for (ms.begin(it); !ms.end(it); ms.next(it)) { | |
687 RAS_TexVert *vertex; | |
688 size_t i, j, numvert; | |
689 ················ | |
690 numvert = it.array->m_type; | |
691 | |
692 if (it.array->m_type == RAS_DisplayArray::LINE) { | |
693 // line drawing, no text | |
694 glBegin(GL_LINES); | |
695 | |
696 for (i=0; i<it.totindex; i+=2) | |
697 { | |
698 vertex = &it.vertex[it.index[i]]; | |
699 glVertex3fv(vertex->getXYZ()); | |
700 | |
701 vertex = &it.vertex[it.index[i+1]]; | |
702 glVertex3fv(vertex->getXYZ()); | |
703 } | |
704 | |
705 glEnd(); | |
706 } | |
707 else { | |
708 // triangle and quad text drawing | |
709 for (i=0; i<it.totindex; i+=numvert) | |
710 { | |
711 float v[4][3]; | |
712 int glattrib, unit; | |
713 | |
714 for (j=0; j<numvert; j++) { | |
715 vertex = &it.vertex[it.index[i+j]]; | |
716 | |
717 v[j][0] = vertex->getXYZ()[0]; | |
718 v[j][1] = vertex->getXYZ()[1]; | |
719 v[j][2] = vertex->getXYZ()[2]; | |
720 } | |
721 | |
722 // find the right opengl attribute | |
723 glattrib = -1; | |
724 if (GLEW_ARB_vertex_program) | |
725 for (unit=0; unit<m_attrib_num; unit++) | |
726 if (m_attrib[unit] == RAS_TEXCO_
UV) | |
727 glattrib = unit; | |
728 | |
729 GPU_render_text(polymat->GetMTFace(), polymat->G
etDrawingMode(), mytext, mytext.Length(), polymat->GetMCol(), v[1], v[2], v[3],
v[4], glattrib); | |
730 | |
731 ClearCachingInfo(); | |
732 } | |
733 } | |
734 } | |
735 | |
736 glDisableClientState(GL_COLOR_ARRAY); | |
737 } | |
738 | |
739 void RAS_OpenGLRasterizer::SetTexCoordNum(int num) | |
740 { | |
741 m_texco_num = num; | |
742 if (m_texco_num > RAS_MAX_TEXCO) | |
743 m_texco_num = RAS_MAX_TEXCO; | |
744 } | |
745 | |
746 void RAS_OpenGLRasterizer::SetAttribNum(int num) | |
747 { | |
748 m_attrib_num = num; | |
749 if (m_attrib_num > RAS_MAX_ATTRIB) | |
750 m_attrib_num = RAS_MAX_ATTRIB; | |
751 } | |
752 | |
753 void RAS_OpenGLRasterizer::SetTexCoord(TexCoGen coords, int unit) | |
754 { | |
755 // this changes from material to material | |
756 if (unit < RAS_MAX_TEXCO) | |
757 m_texco[unit] = coords; | |
758 } | |
759 | |
760 void RAS_OpenGLRasterizer::SetAttrib(TexCoGen coords, int unit, int layer) | |
761 { | |
762 // this changes from material to material | |
763 if (unit < RAS_MAX_ATTRIB) { | |
764 m_attrib[unit] = coords; | |
765 m_attrib_layer[unit] = layer; | |
766 } | |
767 } | |
768 | |
769 void RAS_OpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms) | |
770 { | |
771 if (ms.m_pDerivedMesh) | |
772 m_failsafe_storage->IndexPrimitives(ms); | |
773 else | |
774 m_storage->IndexPrimitives(ms); | |
775 } | |
776 | |
777 void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) | |
778 { | |
779 if (ms.m_pDerivedMesh) | |
780 m_failsafe_storage->IndexPrimitivesMulti(ms); | |
781 else | |
782 m_storage->IndexPrimitivesMulti(ms); | |
783 } | |
784 | |
785 void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat) | |
786 { | |
787 glMatrixMode(GL_PROJECTION); | |
788 double* matrix = &mat(0, 0); | |
789 glLoadMatrixd(matrix); | |
790 | |
791 m_camortho = (mat(3, 3) != 0.0); | |
792 } | |
793 | |
794 void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat) | |
795 { | |
796 glMatrixMode(GL_PROJECTION); | |
797 double matrix[16]; | |
798 /* Get into argument. Looks a bit dodgy, but it's ok. */ | |
799 mat.getValue(matrix); | |
800 /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */ | |
801 glLoadMatrixd(matrix); | |
802 | |
803 m_camortho= (mat[3][3] != 0.0); | |
804 } | |
805 | |
806 MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix( | |
807 float left, | |
808 float right, | |
809 float bottom, | |
810 float top, | |
811 float frustnear, | |
812 float frustfar, | |
813 float focallength, | |
814 bool· | |
815 ) { | |
816 MT_Matrix4x4 result; | |
817 double mat[16]; | |
818 | |
819 // correction for stereo | |
820 if (Stereo()) | |
821 { | |
822 float near_div_focallength; | |
823 float offset; | |
824 | |
825 // if Rasterizer.setFocalLength is not called we use the
camera focallength | |
826 if (!m_setfocallength) | |
827 // if focallength is null we use a value known t
o be reasonable | |
828 m_focallength = (focallength == 0.f) ? m_eyesepa
ration * 30.0f | |
829 : focallength; | |
830 | |
831 near_div_focallength = frustnear / m_focallength; | |
832 offset = 0.5f * m_eyeseparation * near_div_focallength; | |
833 switch (m_curreye) { | |
834 case RAS_STEREO_LEFTEYE: | |
835 left += offset; | |
836 right += offset; | |
837 break; | |
838 case RAS_STEREO_RIGHTEYE: | |
839 left -= offset; | |
840 right -= offset; | |
841 break; | |
842 } | |
843 // leave bottom and top untouched | |
844 } | |
845 ········ | |
846 glMatrixMode(GL_PROJECTION); | |
847 glLoadIdentity(); | |
848 glFrustum(left, right, bottom, top, frustnear, frustfar); | |
849 ················ | |
850 glGetDoublev(GL_PROJECTION_MATRIX, mat); | |
851 result.setValue(mat); | |
852 | |
853 return result; | |
854 } | |
855 | |
856 MT_Matrix4x4 RAS_OpenGLRasterizer::GetOrthoMatrix( | |
857 float left, | |
858 float right, | |
859 float bottom, | |
860 float top, | |
861 float frustnear, | |
862 float frustfar | |
863 ) { | |
864 MT_Matrix4x4 result; | |
865 double mat[16]; | |
866 | |
867 // stereo is meaning less for orthographic, disable it | |
868 glMatrixMode(GL_PROJECTION); | |
869 glLoadIdentity(); | |
870 glOrtho(left, right, bottom, top, frustnear, frustfar); | |
871 ················ | |
872 glGetDoublev(GL_PROJECTION_MATRIX, mat); | |
873 result.setValue(mat); | |
874 | |
875 return result; | |
876 } | |
877 | |
878 | |
879 // next arguments probably contain redundant info, for later... | |
880 void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat,· | |
881
const MT_Matrix3x3 & camOrientMat3x3, | |
882
const MT_Point3 & pos, | |
883
bool perspective) | |
884 { | |
885 m_viewmatrix = mat; | |
886 | |
887 // correction for stereo | |
888 if (Stereo() && perspective) | |
889 { | |
890 MT_Vector3 unitViewDir(0.0, -1.0, 0.0); // minus y direction, B
lender convention | |
891 MT_Vector3 unitViewupVec(0.0, 0.0, 1.0); | |
892 MT_Vector3 viewDir, viewupVec; | |
893 MT_Vector3 eyeline; | |
894 | |
895 // actual viewDir | |
896 viewDir = camOrientMat3x3 * unitViewDir; // this is the moto co
nvention, vector on right hand side | |
897 // actual viewup vec | |
898 viewupVec = camOrientMat3x3 * unitViewupVec; | |
899 | |
900 // vector between eyes | |
901 eyeline = viewDir.cross(viewupVec); | |
902 | |
903 switch (m_curreye) { | |
904 case RAS_STEREO_LEFTEYE: | |
905 { | |
906 // translate to left by half the eye distance | |
907 MT_Transform transform; | |
908 transform.setIdentity(); | |
909 transform.translate(-(eyeline * m_eyeseparation
/ 2.0)); | |
910 m_viewmatrix *= transform; | |
911 } | |
912 break; | |
913 case RAS_STEREO_RIGHTEYE: | |
914 { | |
915 // translate to right by half the eye distance | |
916 MT_Transform transform; | |
917 transform.setIdentity(); | |
918 transform.translate(eyeline * m_eyeseparation /
2.0); | |
919 m_viewmatrix *= transform; | |
920 } | |
921 break; | |
922 } | |
923 } | |
924 | |
925 m_viewinvmatrix = m_viewmatrix; | |
926 m_viewinvmatrix.invert(); | |
927 | |
928 // note: getValue gives back column major as needed by OpenGL | |
929 MT_Scalar glviewmat[16]; | |
930 m_viewmatrix.getValue(glviewmat); | |
931 | |
932 glMatrixMode(GL_MODELVIEW); | |
933 glLoadMatrixd(glviewmat); | |
934 m_campos = pos; | |
935 } | |
936 | |
937 | |
938 const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition() | |
939 { | |
940 return m_campos; | |
941 } | |
942 | |
943 bool RAS_OpenGLRasterizer::GetCameraOrtho() | |
944 { | |
945 return m_camortho; | |
946 } | |
947 | |
948 void RAS_OpenGLRasterizer::SetCullFace(bool enable) | |
949 { | |
950 if (enable) | |
951 glEnable(GL_CULL_FACE); | |
952 else | |
953 glDisable(GL_CULL_FACE); | |
954 } | |
955 | |
956 void RAS_OpenGLRasterizer::SetLines(bool enable) | |
957 { | |
958 if (enable) | |
959 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); | |
960 else | |
961 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | |
962 } | |
963 | |
964 void RAS_OpenGLRasterizer::SetSpecularity(float specX, | |
965
float specY, | |
966
float specZ, | |
967
float specval) | |
968 { | |
969 GLfloat mat_specular[] = {specX, specY, specZ, specval}; | |
970 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); | |
971 } | |
972 | |
973 | |
974 | |
975 void RAS_OpenGLRasterizer::SetShinyness(float shiny) | |
976 { | |
977 GLfloat mat_shininess[] = { shiny }; | |
978 glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); | |
979 } | |
980 | |
981 | |
982 | |
983 void RAS_OpenGLRasterizer::SetDiffuse(float difX,float difY,float difZ,float dif
fuse) | |
984 { | |
985 GLfloat mat_diffuse [] = {difX, difY,difZ, diffuse}; | |
986 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); | |
987 } | |
988 | |
989 void RAS_OpenGLRasterizer::SetEmissive(float eX, float eY, float eZ, float e) | |
990 { | |
991 GLfloat mat_emit [] = {eX,eY,eZ,e}; | |
992 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_emit); | |
993 } | |
994 | |
995 | |
996 double RAS_OpenGLRasterizer::GetTime() | |
997 { | |
998 return m_time; | |
999 } | |
1000 | |
1001 void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add) | |
1002 { | |
1003 glPolygonOffset(mult, add); | |
1004 GLint mode = GL_POLYGON_OFFSET_FILL; | |
1005 if (m_drawingmode < KX_SHADED) | |
1006 mode = GL_POLYGON_OFFSET_LINE; | |
1007 if (mult != 0.0f || add != 0.0f) | |
1008 glEnable(mode); | |
1009 else | |
1010 glDisable(mode); | |
1011 } | |
1012 | |
1013 void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue) | |
1014 { | |
1015 /* don't just set m_motionblur to 1, but check if it is 0 so | |
1016 * we don't reset a motion blur that is already enabled */ | |
1017 if (m_motionblur == 0) | |
1018 m_motionblur = 1; | |
1019 m_motionblurvalue = motionblurvalue; | |
1020 } | |
1021 | |
1022 void RAS_OpenGLRasterizer::DisableMotionBlur() | |
1023 { | |
1024 m_motionblur = 0; | |
1025 m_motionblurvalue = -1.0; | |
1026 } | |
1027 | |
1028 void RAS_OpenGLRasterizer::SetAlphaBlend(int alphablend) | |
1029 { | |
1030 /* Variance shadow maps don't handle alpha well, best to not allow it fo
r now */ | |
1031 if (m_drawingmode == KX_SHADOW && m_usingoverrideshader) | |
1032 GPU_set_material_alpha_blend(GPU_BLEND_SOLID); | |
1033 else | |
1034 GPU_set_material_alpha_blend(alphablend); | |
1035 /* | |
1036 if (alphablend == m_last_alphablend) | |
1037 return; | |
1038 | |
1039 if (alphablend == GPU_BLEND_SOLID) { | |
1040 glDisable(GL_BLEND); | |
1041 glDisable(GL_ALPHA_TEST); | |
1042 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
1043 } | |
1044 else if (alphablend == GPU_BLEND_ADD) { | |
1045 glBlendFunc(GL_ONE, GL_ONE); | |
1046 glEnable(GL_BLEND); | |
1047 glDisable(GL_ALPHA_TEST); | |
1048 } | |
1049 else if (alphablend == GPU_BLEND_ALPHA) { | |
1050 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
1051 glEnable(GL_BLEND); | |
1052 glEnable(GL_ALPHA_TEST); | |
1053 glAlphaFunc(GL_GREATER, 0.0f); | |
1054 } | |
1055 else if (alphablend == GPU_BLEND_CLIP) { | |
1056 glDisable(GL_BLEND);· | |
1057 glEnable(GL_ALPHA_TEST); | |
1058 glAlphaFunc(GL_GREATER, 0.5f); | |
1059 } | |
1060 | |
1061 m_last_alphablend = alphablend; | |
1062 */ | |
1063 } | |
1064 | |
1065 void RAS_OpenGLRasterizer::SetFrontFace(bool ccw) | |
1066 { | |
1067 if (m_last_frontface == ccw) | |
1068 return; | |
1069 | |
1070 if (ccw) | |
1071 glFrontFace(GL_CCW); | |
1072 else | |
1073 glFrontFace(GL_CW); | |
1074 ········ | |
1075 m_last_frontface = ccw; | |
1076 } | |
1077 | |
1078 void RAS_OpenGLRasterizer::SetAnisotropicFiltering(short level) | |
1079 { | |
1080 GPU_set_anisotropic((float)level); | |
1081 } | |
1082 | |
1083 short RAS_OpenGLRasterizer::GetAnisotropicFiltering() | |
1084 { | |
1085 return (short)GPU_get_anisotropic(); | |
1086 } | |
1087 | |
1088 void RAS_OpenGLRasterizer::SetMipmapping(MipmapOption val) | |
1089 { | |
1090 if (val == RAS_IRasterizer::RAS_MIPMAP_LINEAR) | |
1091 { | |
1092 GPU_set_linear_mipmap(1); | |
1093 GPU_set_mipmap(1); | |
1094 } | |
1095 else if (val == RAS_IRasterizer::RAS_MIPMAP_NEAREST) | |
1096 { | |
1097 GPU_set_linear_mipmap(0); | |
1098 GPU_set_mipmap(1); | |
1099 } | |
1100 else | |
1101 { | |
1102 GPU_set_linear_mipmap(0); | |
1103 GPU_set_mipmap(0); | |
1104 } | |
1105 } | |
1106 | |
1107 RAS_IRasterizer::MipmapOption RAS_OpenGLRasterizer::GetMipmapping() | |
1108 { | |
1109 if (GPU_get_linear_mipmap()) | |
1110 return RAS_IRasterizer::RAS_MIPMAP_LINEAR; | |
1111 else if (GPU_get_mipmap()) | |
1112 return RAS_IRasterizer::RAS_MIPMAP_NEAREST; | |
1113 else | |
1114 return RAS_IRasterizer::RAS_MIPMAP_NONE; | |
1115 } | |
1116 | |
1117 void RAS_OpenGLRasterizer::SetUsingOverrideShader(bool val) | |
1118 { | |
1119 m_usingoverrideshader = val; | |
1120 } | |
1121 | |
1122 bool RAS_OpenGLRasterizer::GetUsingOverrideShader() | |
1123 { | |
1124 return m_usingoverrideshader; | |
1125 } | |
1126 | |
1127 /** | |
1128 * Render Tools | |
1129 */ | |
1130 | |
1131 /* ProcessLighting performs lighting on objects. the layer is a bitfield that | |
1132 * contains layer information. There are 20 'official' layers in blender. A | |
1133 * light is applied on an object only when they are in the same layer. OpenGL | |
1134 * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in | |
1135 * a scene. */ | |
1136 | |
1137 void RAS_OpenGLRasterizer::ProcessLighting(bool uselights, const MT_Transform& v
iewmat) | |
1138 { | |
1139 bool enable = false; | |
1140 int layer= -1; | |
1141 | |
1142 /* find the layer */ | |
1143 if (uselights) { | |
1144 if (m_clientobject) | |
1145 layer = static_cast<KX_GameObject*>(m_clientobject)->Get
Layer(); | |
1146 } | |
1147 | |
1148 /* avoid state switching */ | |
1149 if (m_lastlightlayer == layer && m_lastauxinfo == m_auxilaryClientInfo) | |
1150 return; | |
1151 | |
1152 m_lastlightlayer = layer; | |
1153 m_lastauxinfo = m_auxilaryClientInfo; | |
1154 | |
1155 /* enable/disable lights as needed */ | |
1156 if (layer >= 0) { | |
1157 //enable = ApplyLights(layer, viewmat); | |
1158 // taken from blender source, incompatibility between Blender Ob
ject / GameObject | |
1159 KX_Scene* kxscene = (KX_Scene*)m_auxilaryClientInfo; | |
1160 float glviewmat[16]; | |
1161 unsigned int count; | |
1162 std::vector<struct RAS_LightObject*>::iterator lit = m_ligh
ts.begin(); | |
1163 | |
1164 for (count=0; count<m_numgllights; count++) | |
1165 glDisable((GLenum)(GL_LIGHT0+count)); | |
1166 | |
1167 viewmat.getValue(glviewmat); | |
1168 | |
1169 glPushMatrix(); | |
1170 glLoadMatrixf(glviewmat); | |
1171 for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) &
& count < m_numgllights; ++lit) | |
1172 { | |
1173 RAS_LightObject* lightdata = (*lit); | |
1174 KX_LightObject *kxlight = (KX_LightObject*)lightdata->m_
light; | |
1175 | |
1176 if (kxlight->ApplyLight(kxscene, layer, count)) | |
1177 count++; | |
1178 } | |
1179 glPopMatrix(); | |
1180 | |
1181 enable = count > 0; | |
1182 } | |
1183 | |
1184 if (enable) | |
1185 EnableOpenGLLights(); | |
1186 else | |
1187 DisableOpenGLLights(); | |
1188 } | |
1189 | |
1190 void RAS_OpenGLRasterizer::EnableOpenGLLights() | |
1191 { | |
1192 if (m_lastlighting == true) | |
1193 return; | |
1194 | |
1195 glEnable(GL_LIGHTING); | |
1196 glEnable(GL_COLOR_MATERIAL); | |
1197 | |
1198 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); | |
1199 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); | |
1200 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (GetCameraOrtho())? GL_FALSE:
GL_TRUE); | |
1201 if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) | |
1202 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR
_COLOR); | |
1203 | |
1204 m_lastlighting = true; | |
1205 } | |
1206 | |
1207 void RAS_OpenGLRasterizer::DisableOpenGLLights() | |
1208 { | |
1209 if (m_lastlighting == false) | |
1210 return; | |
1211 | |
1212 glDisable(GL_LIGHTING); | |
1213 glDisable(GL_COLOR_MATERIAL); | |
1214 | |
1215 m_lastlighting = false; | |
1216 } | |
1217 | |
1218 void RAS_OpenGLRasterizer::AddLight(struct RAS_LightObject* lightobject) | |
1219 { | |
1220 m_lights.push_back(lightobject); | |
1221 } | |
1222 | |
1223 void RAS_OpenGLRasterizer::RemoveLight(struct RAS_LightObject* lightobject) | |
1224 { | |
1225 std::vector<struct RAS_LightObject*>::iterator lit = | |
1226 std::find(m_lights.begin(),m_lights.end(),lightobject); | |
1227 | |
1228 if (!(lit==m_lights.end())) | |
1229 m_lights.erase(lit); | |
1230 } | |
1231 | |
1232 bool RAS_OpenGLRasterizer::RayHit(class KX_ClientObjectInfo *client, KX_RayCast
*result, void * const data) | |
1233 { | |
1234 double* const oglmatrix = (double* const) data; | |
1235 | |
1236 RAS_Polygon* poly = result->m_hitMesh->GetPolygon(result->m_hitPolygon); | |
1237 if (!poly->IsVisible()) | |
1238 return false; | |
1239 | |
1240 MT_Point3 resultpoint(result->m_hitPoint); | |
1241 MT_Vector3 resultnormal(result->m_hitNormal); | |
1242 MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); | |
1243 MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); | |
1244 left = (dir.cross(resultnormal)).safe_normalized(); | |
1245 // for the up vector, we take the 'resultnormal' returned by the physics | |
1246 | |
1247 double maat[16] = {left[0], left[1], left[2], 0, | |
1248 dir[0], dir[1], dir[2], 0, | |
1249 resultnormal[0], resultnormal[1], resultnormal[2], 0, | |
1250 0, 0, 0, 1}
; | |
1251 | |
1252 glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]); | |
1253 //glMultMatrixd(oglmatrix); | |
1254 glMultMatrixd(maat); | |
1255 return true; | |
1256 } | |
1257 | |
1258 void RAS_OpenGLRasterizer::applyTransform(double* oglmatrix,int objectdrawmode ) | |
1259 { | |
1260 /* FIXME: | |
1261 blender: intern/moto/include/MT_Vector3.inl:42: MT_Vector3 operator/(con
st | |
1262 MT_Vector3&, double): Assertion `!MT_fuzzyZero(s)' failed. | |
1263 | |
1264 Program received signal SIGABRT, Aborted. | |
1265 [Switching to Thread 16384 (LWP 1519)] | |
1266 0x40477571 in kill () from /lib/libc.so.6 | |
1267 (gdb) bt | |
1268 #7 0x08334368 in MT_Vector3::normalized() const () | |
1269 #8 0x0833e6ec in RAS_OpenGLRasterizer::applyTransform(RAS_IRasterizer*,
double*, int) () | |
1270 */ | |
1271 | |
1272 if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED || | |
1273 objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED) | |
1274 { | |
1275 // rotate the billboard/halo | |
1276 //page 360/361 3D Game Engine Design, David Eberly for a discuss
ion | |
1277 // on screen aligned and axis aligned billboards | |
1278 // assumed is that the preprocessor transformed all billboard po
lygons | |
1279 // so that their normal points into the positive x direction (1.
0, 0.0, 0.0) | |
1280 // when new parenting for objects is done, this rotation | |
1281 // will be moved into the object | |
1282 | |
1283 MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]); | |
1284 MT_Point3 campos = GetCameraPosition(); | |
1285 MT_Vector3 dir = (campos - objpos).safe_normalized(); | |
1286 MT_Vector3 up(0,0,1.0); | |
1287 | |
1288 KX_GameObject* gameobj = (KX_GameObject*)m_clientobject; | |
1289 // get scaling of halo object | |
1290 MT_Vector3 size = gameobj->GetSGNode()->GetWorldScaling(); | |
1291 | |
1292 bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBO
ARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned | |
1293 if (screenaligned) | |
1294 { | |
1295 up = (up - up.dot(dir) * dir).safe_normalized(); | |
1296 } else | |
1297 { | |
1298 dir = (dir - up.dot(dir)*up).safe_normalized(); | |
1299 } | |
1300 | |
1301 MT_Vector3 left = dir.normalized(); | |
1302 dir = (up.cross(left)).normalized(); | |
1303 | |
1304 // we have calculated the row vectors, now we keep | |
1305 // local scaling into account: | |
1306 | |
1307 left *= size[0]; | |
1308 dir *= size[1]; | |
1309 up *= size[2]; | |
1310 | |
1311 double maat[16] = {left[0], left[1], left[2], 0, | |
1312 dir[0], dir[1], dir[2], 0, | |
1313 up[0], up[1], up[2], 0, | |
1314 0, 0, 0, 1}; | |
1315 | |
1316 glTranslated(objpos[0],objpos[1],objpos[2]); | |
1317 glMultMatrixd(maat); | |
1318 | |
1319 } | |
1320 else { | |
1321 if (objectdrawmode & RAS_IPolyMaterial::SHADOW) | |
1322 { | |
1323 // shadow must be cast to the ground, physics system nee
ded here! | |
1324 MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatri
x[14]); | |
1325 KX_GameObject *gameobj = (KX_GameObject*)m_clientobject; | |
1326 MT_Vector3 direction = MT_Vector3(0,0,-1); | |
1327 | |
1328 direction.normalize(); | |
1329 direction *= 100000; | |
1330 | |
1331 MT_Point3 topoint = frompoint + direction; | |
1332 | |
1333 KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo; | |
1334 PHY_IPhysicsEnvironment* physics_environment = kxscene->
GetPhysicsEnvironment(); | |
1335 PHY_IPhysicsController* physics_controller = gameobj->Ge
tPhysicsController(); | |
1336 | |
1337 KX_GameObject *parent = gameobj->GetParent(); | |
1338 if (!physics_controller && parent) | |
1339 physics_controller = parent->GetPhysicsControlle
r(); | |
1340 if (parent) | |
1341 parent->Release(); | |
1342 | |
1343 KX_RayCast::Callback<RAS_OpenGLRasterizer> callback(this
, physics_controller, oglmatrix); | |
1344 if (!KX_RayCast::RayTest(physics_environment, frompoint,
topoint, callback)) | |
1345 { | |
1346 // couldn't find something to cast the shadow on
... | |
1347 glMultMatrixd(oglmatrix); | |
1348 } | |
1349 else | |
1350 { // we found the "ground", but the cast matrix doesn't
take | |
1351 // scaling in consideration, so we must apply the obje
ct scale | |
1352 MT_Vector3 size = gameobj->GetSGNode()->GetLoca
lScale(); | |
1353 glScalef(size[0], size[1], size[2]); | |
1354 } | |
1355 } else | |
1356 { | |
1357 | |
1358 // 'normal' object | |
1359 glMultMatrixd(oglmatrix); | |
1360 } | |
1361 } | |
1362 } | |
1363 | |
1364 static void DisableForText() | |
1365 { | |
1366 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); /* needed for texture fonts o
therwise they render as wireframe */ | |
1367 | |
1368 glDisable(GL_BLEND); | |
1369 glDisable(GL_ALPHA_TEST); | |
1370 | |
1371 glDisable(GL_LIGHTING); | |
1372 glDisable(GL_COLOR_MATERIAL); | |
1373 | |
1374 if (GLEW_ARB_multitexture) { | |
1375 for (int i=0; i<RAS_MAX_TEXCO; i++) { | |
1376 glActiveTextureARB(GL_TEXTURE0_ARB+i); | |
1377 | |
1378 if (GLEW_ARB_texture_cube_map) | |
1379 glDisable(GL_TEXTURE_CUBE_MAP_ARB); | |
1380 | |
1381 glDisable(GL_TEXTURE_2D); | |
1382 } | |
1383 | |
1384 glActiveTextureARB(GL_TEXTURE0_ARB); | |
1385 } | |
1386 else { | |
1387 if (GLEW_ARB_texture_cube_map) | |
1388 glDisable(GL_TEXTURE_CUBE_MAP_ARB); | |
1389 | |
1390 glDisable(GL_TEXTURE_2D); | |
1391 } | |
1392 } | |
1393 | |
1394 void RAS_OpenGLRasterizer::RenderBox2D(int xco, | |
1395 int yco, | |
1396 int width, | |
1397 int height, | |
1398 float percentage) | |
1399 { | |
1400 /* This is a rather important line :( The gl-mode hasn't been left | |
1401 * behind quite as neatly as we'd have wanted to. I don't know | |
1402 * what cause it, though :/ .*/ | |
1403 glDisable(GL_DEPTH_TEST); | |
1404 | |
1405 glMatrixMode(GL_PROJECTION); | |
1406 glPushMatrix(); | |
1407 glLoadIdentity(); | |
1408 | |
1409 glOrtho(0, width, 0, height, -100, 100); | |
1410 | |
1411 glMatrixMode(GL_MODELVIEW); | |
1412 glPushMatrix(); | |
1413 glLoadIdentity(); | |
1414 | |
1415 yco = height - yco; | |
1416 int barsize = 50; | |
1417 | |
1418 /* draw in black first*/ | |
1419 glColor3ub(0, 0, 0); | |
1420 glBegin(GL_QUADS); | |
1421 glVertex2f(xco + 1 + 1 + barsize * percentage, yco - 1 + 10); | |
1422 glVertex2f(xco + 1, yco - 1 + 10); | |
1423 glVertex2f(xco + 1, yco - 1); | |
1424 glVertex2f(xco + 1 + 1 + barsize * percentage, yco - 1); | |
1425 glEnd(); | |
1426 | |
1427 glColor3ub(255, 255, 255); | |
1428 glBegin(GL_QUADS); | |
1429 glVertex2f(xco + 1 + barsize * percentage, yco + 10); | |
1430 glVertex2f(xco, yco + 10); | |
1431 glVertex2f(xco, yco); | |
1432 glVertex2f(xco + 1 + barsize * percentage, yco); | |
1433 glEnd(); | |
1434 | |
1435 glMatrixMode(GL_PROJECTION); | |
1436 glPopMatrix(); | |
1437 glMatrixMode(GL_MODELVIEW); | |
1438 glPopMatrix(); | |
1439 glEnable(GL_DEPTH_TEST); | |
1440 } | |
1441 | |
1442 void RAS_OpenGLRasterizer::RenderText3D(int fontid, | |
1443
const char* text, | |
1444
int size, | |
1445
int dpi, | |
1446
float* color, | |
1447
double* mat, | |
1448
float aspect) | |
1449 { | |
1450 /* gl prepping */ | |
1451 DisableForText(); | |
1452 | |
1453 /* the actual drawing */ | |
1454 glColor4fv(color); | |
1455 | |
1456 /* multiply the text matrix by the object matrix */ | |
1457 BLF_enable(fontid, BLF_MATRIX|BLF_ASPECT); | |
1458 BLF_matrix(fontid, mat); | |
1459 | |
1460 /* aspect is the inverse scale that allows you to increase */ | |
1461 /* your resolution without sizing the final text size */ | |
1462 /* the bigger the size, the smaller the aspect */ | |
1463 BLF_aspect(fontid, aspect, aspect, aspect); | |
1464 | |
1465 BLF_size(fontid, size, dpi); | |
1466 BLF_position(fontid, 0, 0, 0); | |
1467 BLF_draw(fontid, (char *)text, 65535); | |
1468 | |
1469 BLF_disable(fontid, BLF_MATRIX|BLF_ASPECT); | |
1470 } | |
1471 | |
1472 void RAS_OpenGLRasterizer::RenderText2D(RAS_TEXT_RENDER_MODE mode, | |
1473
const char* text, | |
1474
int xco, | |
1475
int yco, | |
1476
int width, | |
1477
int height) | |
1478 { | |
1479 /* This is a rather important line :( The gl-mode hasn't been left | |
1480 * behind quite as neatly as we'd have wanted to. I don't know | |
1481 * what cause it, though :/ .*/ | |
1482 DisableForText(); | |
1483 glDisable(GL_DEPTH_TEST); | |
1484 | |
1485 glMatrixMode(GL_PROJECTION); | |
1486 glPushMatrix(); | |
1487 glLoadIdentity(); | |
1488 | |
1489 glOrtho(0, width, 0, height, -100, 100); | |
1490 | |
1491 glMatrixMode(GL_MODELVIEW); | |
1492 glPushMatrix(); | |
1493 glLoadIdentity(); | |
1494 | |
1495 if (mode == RAS_TEXT_PADDED) { | |
1496 /* draw in black first*/ | |
1497 glColor3ub(0, 0, 0); | |
1498 BLF_size(blf_mono_font, 11, 72); | |
1499 BLF_position(blf_mono_font, (float)xco+1, (float)(height-yco-1),
0.0f); | |
1500 BLF_draw(blf_mono_font, (char *)text, 65535);/* XXX, use real le
n */ | |
1501 } | |
1502 | |
1503 /* the actual drawing */ | |
1504 glColor3ub(255, 255, 255); | |
1505 BLF_size(blf_mono_font, 11, 72); | |
1506 BLF_position(blf_mono_font, (float)xco, (float)(height-yco), 0.0f); | |
1507 BLF_draw(blf_mono_font, (char *)text, 65535); /* XXX, use real len */ | |
1508 | |
1509 glMatrixMode(GL_PROJECTION); | |
1510 glPopMatrix(); | |
1511 glMatrixMode(GL_MODELVIEW); | |
1512 glPopMatrix(); | |
1513 glEnable(GL_DEPTH_TEST); | |
1514 } | |
1515 | |
1516 void RAS_OpenGLRasterizer::PushMatrix() | |
1517 { | |
1518 glPushMatrix(); | |
1519 } | |
1520 | |
1521 void RAS_OpenGLRasterizer::PopMatrix() | |
1522 { | |
1523 glPopMatrix(); | |
1524 } | |
1525 | |
1526 void RAS_OpenGLRasterizer::MotionBlur() | |
1527 { | |
1528 int state = GetMotionBlurState(); | |
1529 float motionblurvalue; | |
1530 if (state) | |
1531 { | |
1532 motionblurvalue = GetMotionBlurValue(); | |
1533 if (state==1) | |
1534 { | |
1535 //bugfix:load color buffer into accum buffer for the fir
st time(state=1) | |
1536 glAccum(GL_LOAD, 1.0); | |
1537 SetMotionBlurState(2); | |
1538 } | |
1539 else if (motionblurvalue >= 0.0f && motionblurvalue <= 1.0f) { | |
1540 glAccum(GL_MULT, motionblurvalue); | |
1541 glAccum(GL_ACCUM, 1-motionblurvalue); | |
1542 glAccum(GL_RETURN, 1.0); | |
1543 glFlush(); | |
1544 } | |
1545 } | |
1546 } | |
1547 | |
1548 void RAS_OpenGLRasterizer::SetClientObject(void* obj) | |
1549 { | |
1550 if (m_clientobject != obj) | |
1551 { | |
1552 bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeSca
ling()); | |
1553 SetFrontFace(ccw); | |
1554 | |
1555 m_clientobject = obj; | |
1556 } | |
1557 } | |
1558 | |
1559 void RAS_OpenGLRasterizer::SetAuxilaryClientInfo(void* inf) | |
1560 { | |
1561 m_auxilaryClientInfo = inf; | |
1562 } | |
1563 | |
LEFT | RIGHT |