• Home
  • Textbooks
  • Mathematics for Game Programming and Computer Graphics: Explore the essential mathematics for creating, rendering, and manipulating 3D virtual environments
  • Working with Coordinate Spaces

Mathematics for Game Programming and Computer Graphics: Explore the essential mathematics for creating, rendering, and manipulating 3D virtual environments

Penny de Byl

Chapter 14

Working with Coordinate Spaces - all with Video Answers

Educators


Section 1

Understanding OpenGL’s Matrix Stack

Problem 1

Create a new Python folder called Chapter_14 and copy the contents from Chapter_13 into it.

Check back soon!

Problem 2

We are going to rewrite the entire contents of the Trans form. py class to work with matrices. Delete all the lines of code in your Transform. py class and add the following code:
import pygame
import math
import numpy as np
class Transform:
def__init_(self) :
self.MVM $=$ np.identity $(4)$
def get_MVM(self) :
return self.MVM
To begin, the initialization method has had the original variables removed and self .MVM has been added to store the modelview matrix. It is initially set to an empty identity matrix. When we zero a matrix in computer graphics, it's not set to all values of zero; otherwise, any other matrix multiplied with it will result in another matrix full of zeros.
Following this, a new method for returning the modelview matrix has been added.

Check back soon!

Problem 3

The next method that you add here will update the position of the object. It does this through a multiplication operation of the existing modelview matrix with a translation matrix:
def update position(self, position):
$[0,1,0,0]$,
$[0,0,1,0]$,
[position.x, position.y,
position.z, 1]])
The update_scale () method is similar to the update_position () method in that it performs a matrix calculation. But notice the format of the matrix is different to cater to scaling operations:
def update_scale(self, amount: pygame.Vector3):
self.MVM $=$ self.MVM @ $\mathrm{np} \cdot \operatorname{matrix}([$
[amount.x, $0,0,0]$,
$[0$, amount. $y, 0,0]$,
$[0,0$, amount. $z, 0]$,
$[0,0,0,1]$
])

Check back soon!
05:28

Problem 4

The final three methods you will add are all for rotation. They allow you to rotate around any axis:
def rotate_x(self, amount) :
amount $=$ math.radians (amount)
self.MVM $=$ self.MVM@np.matrix([
$[1,0,0,0]$,
[0, math.cos (amount),
math.sin (amount), 0],
[0, -math. $\sin$ (amount),
math.cos (amount), 0],
$[0,0,0,1]])$
def rotate_y(self, amount) :
amount $=$ math.radians (amount)
self.MVM = self.MVM@np.matrix([
[math.cos (amount), 0 ,
-math.sin(amount), 0],
$[0,1,0,0]$,
[math.sin(amount), 0 ,
math.cos (amount), 0],
$[0,0,0,1]\})$
def rotate_z(self, amount) :
amount $=$ math $\cdot$ radians (amount)
self.MVM $=$ self.MVM @ np.matrix([
[math.cos(amount), math.sin(amount),
$0,0]$,
[-math.sin(amount), math.cos(amount),
$0,0]$,
$[0,0,1,0]$,
$[0,0,0,1]])$

Take note of how the three rotation matrices have been formatted for the different axes.

Anthony Ramos
Anthony Ramos
Numerade Educator

Problem 5

To use the modelview matrix to set the transformation of the object, the code in object. py needs to be updated thus:
.
def update (self, events $=$ None):
glPushMatrix ()
for $c$ in self.components:
if isinstance(c, Transform):
glLoadMatrixf(c.get_MVM())
mv $=$ glGetDoublev (GL_MODELVIEW_MATRIX)
print ("MV: ")
print (mv)
elif isinstance (c, Mesh3D) :
glColor(1, 1, 1)
Take note here of how the OpenGL transformations have been removed and replaced with a glLoadMatrixf () call instead. This method loads in the matrix calculated by the Transform class. The printing of the modelview matrix has been left to show you the contents of the matrix after we have calculated it manually. The idea is that if you perform the exact same transformations as we did in Chapter 13, Understanding the Importance of Matrices, the modelview matrix will be the same.

Check back soon!

Problem 6

To use these modifications, open up TransformationMatrices . py and modify how the cube is being drawn thus:
.
objects_3d $=[]$
objects_2d = []
cube = Object(“Cube”)
cube.add_component(Transform())
cube.add_component(Cube(GL_POLYGON, “images/wall.tif”))
trans: Transform = cube.get_component(Transform)
trans.update_position(pygame.Vector3(0, 0, -3))
trans.rotate_x(45)
trans.update_scale(pygame.Vector3(0.5, 2, 1))
objects_3d.append(cube)
clock = pygame.time.Clock()
..

Check back soon!