framework2
462 строки · 11.9 Кб
1/*
2* ofMatrixStack.cpp
3*
4* Created on: Apr 3, 2013
5* Author: arturo
6*/
7
8#include "ofMatrixStack.h"
9#include "ofAppBaseWindow.h"
10#include "ofGraphicsBaseTypes.h"
11#include "ofLog.h"
12
13#define GLM_FORCE_CTOR_INIT
14#include "glm/mat4x4.hpp"
15#include "glm/gtx/transform.hpp"
16
17using std::swap;
18using std::make_pair;
19using std::pair;
20
21ofMatrixStack::ofMatrixStack(const ofAppBaseWindow * window)
22:vFlipped(true)
23,orientation(OF_ORIENTATION_DEFAULT)
24,handedness(OF_LEFT_HANDED)
25,currentRenderSurface(nullptr)
26,currentWindow(const_cast<ofAppBaseWindow*>(window))
27,currentMatrixMode(OF_MATRIX_MODELVIEW)
28,currentMatrix(&modelViewMatrix)
29,flipRenderSurfaceMatrix(true)
30,modelMatrix(1)
31,viewMatrix(1)
32,viewInverse(1)
33,modelViewMatrix(1)
34,projectionMatrix(1)
35,textureMatrix(1)
36,modelViewProjectionMatrix(1)
37,orientedProjectionMatrix(1)
38,orientationMatrix(1)
39,orientationMatrixInverse(1)
40{
41
42}
43
44void ofMatrixStack::setRenderSurface(const ofBaseDraws & renderSurface_){
45currentRenderSurface = const_cast<ofBaseDraws*>(&renderSurface_);
46flipRenderSurfaceMatrix = true;
47setOrientation(orientation,vFlipped);
48}
49
50void ofMatrixStack::setRenderSurfaceNoMatrixFlip(const ofBaseDraws & renderSurface_) {
51currentRenderSurface = const_cast<ofBaseDraws*>(&renderSurface_);
52flipRenderSurfaceMatrix = false;
53setOrientation(orientation, vFlipped);
54}
55
56void ofMatrixStack::setRenderSurface(const ofAppBaseWindow & window){
57currentWindow = const_cast<ofAppBaseWindow*>(&window);
58currentRenderSurface = nullptr;
59setOrientation(orientation,vFlipped);
60}
61
62void ofMatrixStack::setOrientation(ofOrientation _orientation, bool vFlip){
63vFlipped = vFlip;
64orientation = _orientation;
65
66if(vFlip){
67handedness = OF_LEFT_HANDED;
68}else{
69handedness = OF_RIGHT_HANDED;
70}
71
72orientationMatrix = glm::mat4(1.0);
73
74bool vFlipMatrix = customMatrixNeedsFlip();
75
76if(vFlipMatrix)
77orientationMatrix = glm::scale(orientationMatrix, glm::vec3(1.f,-1.f,1.f));
78
79if(!doesHWOrientation()){
80switch(orientation) {
81case OF_ORIENTATION_180:
82orientationMatrix = glm::rotate(orientationMatrix, glm::pi<float>(), glm::vec3{0.f, 0.f, 1.f});
83break;
84
85case OF_ORIENTATION_90_RIGHT:
86orientationMatrix = glm::rotate(orientationMatrix, glm::half_pi<float>(), glm::vec3{0.f, 0.f, 1.f});
87break;
88
89case OF_ORIENTATION_90_LEFT:
90orientationMatrix = glm::rotate(orientationMatrix, -glm::half_pi<float>(), glm::vec3{0.f, 0.f, 1.f});
91break;
92
93case OF_ORIENTATION_DEFAULT:
94default:
95break;
96}
97}
98
99orientationMatrixInverse = glm::inverse(orientationMatrix);
100orientedProjectionMatrix = orientationMatrix * projectionMatrix;
101modelViewProjectionMatrix = orientedProjectionMatrix * modelViewMatrix;
102}
103
104ofOrientation ofMatrixStack::getOrientation() const{
105return orientation;
106}
107
108bool ofMatrixStack::isVFlipped() const{
109return vFlipped;
110}
111
112bool ofMatrixStack::customMatrixNeedsFlip() const{
113return vFlipped != (bool(currentRenderSurface) && flipRenderSurfaceMatrix);
114}
115
116int ofMatrixStack::getRenderSurfaceWidth() const{
117if(currentRenderSurface){
118return currentRenderSurface->getWidth();
119}else if(currentWindow){
120return currentWindow->getWindowSize().x;
121}else{
122return 0;
123}
124}
125
126int ofMatrixStack::getRenderSurfaceHeight() const{
127if(currentRenderSurface){
128return currentRenderSurface->getHeight();
129}else if(currentWindow){
130return currentWindow->getWindowSize().y;
131}else{
132return 0;
133}
134}
135
136ofMatrixMode ofMatrixStack::getCurrentMatrixMode() const{
137return currentMatrixMode;
138}
139
140ofHandednessType ofMatrixStack::getHandedness() const{
141return handedness;
142}
143
144
145bool ofMatrixStack::doesHWOrientation() const{
146return currentRenderSurface || (currentWindow && currentWindow->doesHWOrientation());
147}
148
149void ofMatrixStack::viewport(float x, float y, float width, float height, bool vflip){
150if(!doesHWOrientation() && (orientation==OF_ORIENTATION_90_LEFT || orientation==OF_ORIENTATION_90_RIGHT)){
151swap(width,height);
152swap(x,y);
153}
154
155if(width < 0 || height < 0){
156width = getRenderSurfaceWidth();
157height = getRenderSurfaceHeight();
158vflip = isVFlipped();
159}
160
161if (vflip){
162y = getRenderSurfaceHeight() - (y + height);
163}
164
165currentViewport.set(x,y,width,height);
166}
167
168ofRectangle ofMatrixStack::getCurrentViewport() const{
169ofRectangle tmpCurrentViewport = currentViewport;
170if (isVFlipped()){
171tmpCurrentViewport.y = getRenderSurfaceHeight() - (tmpCurrentViewport.y + tmpCurrentViewport.height);
172}
173
174if(!doesHWOrientation() && (orientation==OF_ORIENTATION_90_LEFT || orientation==OF_ORIENTATION_90_RIGHT)){
175swap(tmpCurrentViewport.width,tmpCurrentViewport.height);
176swap(tmpCurrentViewport.x,tmpCurrentViewport.y);
177}
178return tmpCurrentViewport;
179}
180
181ofRectangle ofMatrixStack::getNativeViewport() const{
182return currentViewport;
183}
184
185ofRectangle ofMatrixStack::getFullSurfaceViewport() const{
186if(currentRenderSurface){
187return ofRectangle(0,0,currentRenderSurface->getWidth(),currentRenderSurface->getHeight());
188}else if(currentWindow){
189return ofRectangle(0,0,currentWindow->getWidth(),currentWindow->getHeight());
190}else{
191return ofRectangle();
192}
193}
194
195void ofMatrixStack::nativeViewport(ofRectangle viewport){
196currentViewport=viewport;
197}
198
199const glm::mat4 & ofMatrixStack::getModelMatrix() const{
200return modelMatrix;
201}
202
203const glm::mat4 & ofMatrixStack::getViewMatrix() const{
204return viewMatrix;
205}
206
207const glm::mat4 & ofMatrixStack::getViewInverse() const{
208return viewInverse;
209}
210
211const glm::mat4 & ofMatrixStack::getProjectionMatrix() const{
212return orientedProjectionMatrix;
213}
214
215const glm::mat4 & ofMatrixStack::getModelViewMatrix() const{
216return modelViewMatrix;
217}
218
219const glm::mat4 & ofMatrixStack::getModelViewProjectionMatrix() const{
220return modelViewProjectionMatrix;
221}
222
223const glm::mat4 & ofMatrixStack::getTextureMatrix() const{
224return textureMatrix;
225}
226
227const glm::mat4 & ofMatrixStack::getCurrentMatrix() const{
228return *currentMatrix;
229}
230
231const glm::mat4 & ofMatrixStack::getProjectionMatrixNoOrientation() const{
232return projectionMatrix;
233}
234
235const glm::mat4 & ofMatrixStack::getOrientationMatrix() const{
236return orientationMatrix;
237}
238
239const glm::mat4 & ofMatrixStack::getOrientationMatrixInverse() const{
240return orientationMatrixInverse;
241}
242
243void ofMatrixStack::pushView(){
244viewportHistory.push(currentViewport);
245
246ofMatrixMode currentMode = currentMatrixMode;
247
248matrixMode(OF_MATRIX_PROJECTION);
249pushMatrix();
250
251matrixMode(OF_MATRIX_MODELVIEW);
252pushMatrix();
253
254matrixMode(currentMode);
255
256viewMatrixStack.push(viewMatrix);
257
258orientationStack.push(make_pair(orientation,vFlipped));
259}
260
261void ofMatrixStack::popView(){
262if(!viewMatrixStack.empty()){
263viewMatrix = viewMatrixStack.top();
264viewInverse = glm::inverse(viewMatrix);
265viewMatrixStack.pop();
266}
267
268if(!orientationStack.empty()){
269pair<ofOrientation,bool> orientationFlip = orientationStack.top();
270setOrientation(orientationFlip.first,orientationFlip.second);
271orientationStack.pop();
272}
273
274if( viewportHistory.size() ){
275currentViewport = viewportHistory.top();
276viewportHistory.pop();
277}
278
279ofMatrixMode currentMode = currentMatrixMode;
280
281matrixMode(OF_MATRIX_PROJECTION);
282popMatrix();
283
284matrixMode(OF_MATRIX_MODELVIEW);
285popMatrix();
286
287matrixMode(currentMode);
288}
289
290void ofMatrixStack::pushMatrix(){
291switch(currentMatrixMode){
292case OF_MATRIX_MODELVIEW:
293modelViewMatrixStack.push(modelViewMatrix);
294break;
295case OF_MATRIX_PROJECTION:
296projectionMatrixStack.push(projectionMatrix);
297break;
298case OF_MATRIX_TEXTURE:
299textureMatrixStack.push(textureMatrix);
300break;
301}
302}
303
304void ofMatrixStack::popMatrix(){
305if (currentMatrixMode == OF_MATRIX_MODELVIEW && !modelViewMatrixStack.empty()){
306modelViewMatrix = modelViewMatrixStack.top();
307modelViewMatrixStack.pop();
308modelMatrix = viewInverse * modelViewMatrix;
309} else if (currentMatrixMode == OF_MATRIX_PROJECTION && !projectionMatrixStack.empty()){
310projectionMatrix = projectionMatrixStack.top();
311projectionMatrixStack.pop();
312} else if (currentMatrixMode == OF_MATRIX_TEXTURE && !textureMatrixStack.empty()){
313textureMatrix = textureMatrixStack.top();
314textureMatrixStack.pop();
315} else {
316ofLogWarning("ofMatrixStack") << "popMatrix(): empty matrix stack, cannot pop any further";
317}
318updatedRelatedMatrices();
319}
320
321void ofMatrixStack::clearStacks(){
322int tmpCounter = 0;
323while (!modelViewMatrixStack.empty()){
324modelViewMatrixStack.pop();
325tmpCounter++;
326}
327if (tmpCounter > 0 ){
328ofLogWarning("ofMatrixStack") << "clearStacks(): found " << tmpCounter << " extra modelview matrices on the stack, did you forget to pop somewhere?";
329}
330
331tmpCounter = 0;
332while (!projectionMatrixStack.empty()){
333projectionMatrixStack.pop();
334tmpCounter++;
335}
336if (tmpCounter > 0 ){
337ofLogWarning("ofMatrixStack") << "clearStacks(): found " << tmpCounter << " extra projection matrices on the stack, did you forget to pop somewhere?";
338}
339
340tmpCounter = 0;
341while (!textureMatrixStack.empty()){
342textureMatrixStack.pop();
343tmpCounter++;
344}
345if (tmpCounter > 0 ){
346ofLogWarning("ofMatrixStack") << "clearStacks(): found " << tmpCounter << " extra texture matrices on the stack, did you forget to pop somewhere?";
347}
348
349tmpCounter = 0;
350while (!viewportHistory.empty()){
351viewportHistory.pop();
352tmpCounter++;
353}
354if (tmpCounter > 0 ){
355ofLogWarning("ofMatrixStack") << "clearStacks(): found " << tmpCounter << " extra viewports on the stack, did you forget to popView() somewhere?";
356}
357
358tmpCounter = 0;
359while (!orientationStack.empty()){
360orientationStack.pop();
361tmpCounter++;
362}
363if (tmpCounter > 0 ){
364ofLogWarning("ofMatrixStack") << "clearStacks(): found " << tmpCounter << " extra orientations on the stack, did you forget to popView() somewhere?";
365}
366
367tmpCounter = 0;
368while (!viewMatrixStack.empty()){
369viewMatrixStack.pop();
370tmpCounter++;
371}
372if (tmpCounter > 0 ){
373ofLogWarning("ofMatrixStack") << "clearStacks(): found " << tmpCounter << " extra view matrices on the stack, did you forget to popView() somewhere?";
374}
375}
376
377void ofMatrixStack::translate(float x, float y, float z){
378*currentMatrix = glm::translate(*currentMatrix, glm::vec3(x, y, z));
379updatedRelatedMatrices();
380}
381
382void ofMatrixStack::scale(float xAmnt, float yAmnt, float zAmnt){
383*currentMatrix = glm::scale(*currentMatrix, glm::vec3(xAmnt, yAmnt, zAmnt));
384updatedRelatedMatrices();
385}
386
387void ofMatrixStack::rotateRad(float radians, float vecX, float vecY, float vecZ){
388*currentMatrix = glm::rotate(*currentMatrix, radians, glm::vec3(vecX, vecY, vecZ));
389updatedRelatedMatrices();
390}
391
392void ofMatrixStack::matrixMode(ofMatrixMode mode){
393currentMatrixMode = mode;
394switch(currentMatrixMode){
395case OF_MATRIX_MODELVIEW:
396currentMatrix = &modelViewMatrix;
397break;
398case OF_MATRIX_PROJECTION:
399currentMatrix = &projectionMatrix;
400break;
401case OF_MATRIX_TEXTURE:
402currentMatrix = &textureMatrix;
403break;
404}
405}
406
407void ofMatrixStack::loadIdentityMatrix (void){
408*currentMatrix = glm::mat4(1.0);
409updatedRelatedMatrices();
410}
411
412void ofMatrixStack::loadMatrix (const glm::mat4 & m){
413*currentMatrix = glm::mat4(m);
414updatedRelatedMatrices();
415}
416
417void ofMatrixStack::multMatrix (const glm::mat4 & m){
418*currentMatrix = *currentMatrix * m;
419updatedRelatedMatrices();
420}
421
422void ofMatrixStack::loadViewMatrix(const glm::mat4 & matrix){
423auto lastMatrixMode = currentMatrixMode;
424currentMatrixMode = OF_MATRIX_MODELVIEW;
425viewMatrix = matrix;
426viewInverse = glm::inverse(viewMatrix);
427loadMatrix(matrix);
428currentMatrixMode = lastMatrixMode;
429}
430
431void ofMatrixStack::multViewMatrix(const glm::mat4 & matrix){
432ofMatrixMode lastMatrixMode = currentMatrixMode;
433currentMatrixMode = OF_MATRIX_MODELVIEW;
434viewMatrix = viewMatrix * matrix;
435viewInverse = glm::inverse(viewMatrix);
436multMatrix(matrix);
437currentMatrixMode = lastMatrixMode;
438}
439
440
441void ofMatrixStack::updatedRelatedMatrices(){
442switch(currentMatrixMode){
443case OF_MATRIX_MODELVIEW:
444modelViewProjectionMatrix = orientedProjectionMatrix * modelViewMatrix;
445modelMatrix = viewInverse * modelViewMatrix;
446break;
447case OF_MATRIX_PROJECTION:
448orientedProjectionMatrix = orientationMatrix * projectionMatrix;
449modelViewProjectionMatrix = orientedProjectionMatrix * modelViewMatrix;
450break;
451default:
452break;
453}
454}
455
456bool ofMatrixStack::doesHardwareOrientation() const{
457if(currentRenderSurface){
458return true;
459}else{
460return currentWindow->doesHWOrientation();
461}
462}
463