1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "MatrixStack.hpp" 16 17 #include "Common/Math.hpp" 18 19 namespace sw 20 { MatrixStack(int size)21 MatrixStack::MatrixStack(int size) 22 { 23 stack = new Matrix[size]; 24 stack[0] = 1; 25 26 top = 0; 27 this->size = size; 28 } 29 ~MatrixStack()30 MatrixStack::~MatrixStack() 31 { 32 delete[] stack; 33 stack = 0; 34 } 35 identity()36 void MatrixStack::identity() 37 { 38 stack[top] = 1; 39 } 40 load(const Matrix & M)41 void MatrixStack::load(const Matrix &M) 42 { 43 stack[top] = M; 44 } 45 load(const float * M)46 void MatrixStack::load(const float *M) 47 { 48 stack[top] = Matrix(M[0], M[4], M[8], M[12], 49 M[1], M[5], M[9], M[13], 50 M[2], M[6], M[10], M[14], 51 M[3], M[7], M[11], M[15]); 52 } 53 load(const double * M)54 void MatrixStack::load(const double *M) 55 { 56 stack[top] = Matrix((float)M[0], (float)M[4], (float)M[8], (float)M[12], 57 (float)M[1], (float)M[5], (float)M[9], (float)M[13], 58 (float)M[2], (float)M[6], (float)M[10], (float)M[14], 59 (float)M[3], (float)M[7], (float)M[11], (float)M[15]); 60 } 61 translate(float x,float y,float z)62 void MatrixStack::translate(float x, float y, float z) 63 { 64 stack[top] *= Matrix::translate(x, y, z); 65 } 66 translate(double x,double y,double z)67 void MatrixStack::translate(double x, double y, double z) 68 { 69 translate((float)x, (float)y, (float)z); 70 } 71 rotate(float angle,float x,float y,float z)72 void MatrixStack::rotate(float angle, float x, float y, float z) 73 { 74 float n = 1.0f / sqrt(x*x + y*y + z*z); 75 76 x *= n; 77 y *= n; 78 z *= n; 79 80 float theta = angle * 0.0174532925f; // In radians 81 float c = cos(theta); 82 float _c = 1 - c; 83 float s = sin(theta); 84 85 // Rodrigues' rotation formula 86 sw::Matrix rotate(c+x*x*_c, x*y*_c-z*s, x*z*_c+y*s, 87 x*y*_c+z*s, c+y*y*_c, y*z*_c-x*s, 88 x*z*_c-y*s, y*z*_c+x*s, c+z*z*_c); 89 90 stack[top] *= rotate; 91 } 92 rotate(double angle,double x,double y,double z)93 void MatrixStack::rotate(double angle, double x, double y, double z) 94 { 95 rotate((float)angle, (float)x, (float)y, (float)z); 96 } 97 scale(float x,float y,float z)98 void MatrixStack::scale(float x, float y, float z) 99 { 100 stack[top] *= Matrix::scale(x, y, z); 101 } 102 scale(double x,double y,double z)103 void MatrixStack::scale(double x, double y, double z) 104 { 105 scale((float)x, (float)y, (float)z); 106 } 107 multiply(const float * M)108 void MatrixStack::multiply(const float *M) 109 { 110 stack[top] *= Matrix(M[0], M[4], M[8], M[12], 111 M[1], M[5], M[9], M[13], 112 M[2], M[6], M[10], M[14], 113 M[3], M[7], M[11], M[15]); 114 } 115 multiply(const double * M)116 void MatrixStack::multiply(const double *M) 117 { 118 stack[top] *= Matrix((float)M[0], (float)M[4], (float)M[8], (float)M[12], 119 (float)M[1], (float)M[5], (float)M[9], (float)M[13], 120 (float)M[2], (float)M[6], (float)M[10], (float)M[14], 121 (float)M[3], (float)M[7], (float)M[11], (float)M[15]); 122 } 123 frustum(float left,float right,float bottom,float top,float zNear,float zFar)124 void MatrixStack::frustum(float left, float right, float bottom, float top, float zNear, float zFar) 125 { 126 float l = (float)left; 127 float r = (float)right; 128 float b = (float)bottom; 129 float t = (float)top; 130 float n = (float)zNear; 131 float f = (float)zFar; 132 133 float A = (r + l) / (r - l); 134 float B = (t + b) / (t - b); 135 float C = -(f + n) / (f - n); 136 float D = -2 * f * n / (f - n); 137 138 Matrix frustum(2 * n / (r - l), 0, A, 0, 139 0, 2 * n / (t - b), B, 0, 140 0, 0, C, D, 141 0, 0, -1, 0); 142 143 stack[this->top] *= frustum; 144 } 145 ortho(double left,double right,double bottom,double top,double zNear,double zFar)146 void MatrixStack::ortho(double left, double right, double bottom, double top, double zNear, double zFar) 147 { 148 float l = (float)left; 149 float r = (float)right; 150 float b = (float)bottom; 151 float t = (float)top; 152 float n = (float)zNear; 153 float f = (float)zFar; 154 155 float tx = -(r + l) / (r - l); 156 float ty = -(t + b) / (t - b); 157 float tz = -(f + n) / (f - n); 158 159 Matrix ortho(2 / (r - l), 0, 0, tx, 160 0, 2 / (t - b), 0, ty, 161 0, 0, -2 / (f - n), tz, 162 0, 0, 0, 1); 163 164 stack[this->top] *= ortho; 165 } 166 push()167 bool MatrixStack::push() 168 { 169 if(top >= size - 1) return false; 170 171 stack[top + 1] = stack[top]; 172 top++; 173 174 return true; 175 } 176 pop()177 bool MatrixStack::pop() 178 { 179 if(top <= 0) return false; 180 181 top--; 182 183 return true; 184 } 185 current()186 const Matrix &MatrixStack::current() 187 { 188 return stack[top]; 189 } 190 isIdentity() const191 bool MatrixStack::isIdentity() const 192 { 193 const Matrix &m = stack[top]; 194 195 if(m.m[0][0] != 1.0f) return false; 196 if(m.m[0][1] != 0.0f) return false; 197 if(m.m[0][2] != 0.0f) return false; 198 if(m.m[0][3] != 0.0f) return false; 199 200 if(m.m[1][0] != 0.0f) return false; 201 if(m.m[1][1] != 1.0f) return false; 202 if(m.m[1][2] != 0.0f) return false; 203 if(m.m[1][3] != 0.0f) return false; 204 205 if(m.m[2][0] != 0.0f) return false; 206 if(m.m[2][1] != 0.0f) return false; 207 if(m.m[2][2] != 1.0f) return false; 208 if(m.m[2][3] != 0.0f) return false; 209 210 if(m.m[3][0] != 0.0f) return false; 211 if(m.m[3][1] != 0.0f) return false; 212 if(m.m[3][2] != 0.0f) return false; 213 if(m.m[3][3] != 1.0f) return false; 214 215 return true; 216 } 217 } 218