Home | History | Annotate | Download | only in common
      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 {
     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 
     30 	MatrixStack::~MatrixStack()
     31 	{
     32 		delete[] stack;
     33 		stack = 0;
     34 	}
     35 
     36 	void MatrixStack::identity()
     37 	{
     38 		stack[top] = 1;
     39 	}
     40 
     41 	void MatrixStack::load(const Matrix &M)
     42 	{
     43 		stack[top] = M;
     44 	}
     45 
     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 
     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 
     62 	void MatrixStack::translate(float x, float y, float z)
     63 	{
     64 		stack[top] *= Matrix::translate(x, y, z);
     65 	}
     66 
     67 	void MatrixStack::translate(double x, double y, double z)
     68 	{
     69 		translate((float)x, (float)y, (float)z);
     70 	}
     71 
     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 
     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 
     98 	void MatrixStack::scale(float x, float y, float z)
     99 	{
    100 		stack[top] *= Matrix::scale(x, y, z);
    101 	}
    102 
    103 	void MatrixStack::scale(double x, double y, double z)
    104 	{
    105 		scale((float)x, (float)y, (float)z);
    106 	}
    107 
    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 
    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 
    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 
    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 
    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 
    177 	bool MatrixStack::pop()
    178 	{
    179 		if(top <= 0) return false;
    180 
    181 		top--;
    182 
    183 		return true;
    184 	}
    185 
    186 	const Matrix &MatrixStack::current()
    187 	{
    188 		return stack[top];
    189 	}
    190 
    191 	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