# with this edition we retire ch.py nee MH and start fixing it
# edited by GF and later by Matt Hoffman with rearrangements
# whose philosophy is reposition 4vertex as being drawn,
# while we usually reassociate and apply rotation after being drawn.
# pyNewTorus.py by Stan Blank, Wayne City, IL
# Credit to George K. Francis for the excellent original program
# continued by GF 18nov12

# om (for angle omega) represents time in the homotopy
global om; om = 0
global dom; dom = .05
global xmult; xmult=1 # rotation angle multiplier
global ymult; ymult=1
global zmult; zmult=2

global dangle; dangle = 15
#compare with dangle=90
global dgap; dgap = dangle

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from math import *
import sys, numpy

svn = sqrt(2)/2.
deg = pi/180
def C(u): return cos(u*deg)
def S(u): return sin(u*deg)

global wd
global ht
global mouseX
global mouseY
global aff
global nrange
nrange = 3.0

aff = [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0] def drawvert(th,ta, xmat, ymat, zmat): #parametric sphere equations #n0= svn*C(th+ta) #n1= svn*S(th+ta) #n2= svn* C(th-ta) #n3= svn*S(th-ta) n0= .5*(C(th) + S(th)) n1= .5*(C(th) - S(th)) n2= .5*(C(ta) + S(ta)) n3= .5*(C(ta) - S(ta)) vert=numpy.array([n0,n1,n2,n3]) # this is the numpy way of applyig matrix multiplation vert=numpy.dot(xmat,vert) vert=numpy.dot(ymat,vert) vert=numpy.dot(zmat,vert) #glColor3f(S(th),C(ta),S(th*ta)) glColor3f(1.,1.,1.) # clifford torus denominator = 1-vert[3] glVertex3f(vert[0]/denominator, vert[1]/denominator, vert[2]/denominator) def drawsurf(): global om #needed because it is changed in the function global dom matc=C(xmult*om); mats=S(xmult*om) xmat=numpy.array([[matc,0,0,-mats],[0,1,0,0],[0,0,1,0],[mats,0,0,matc]]) matc=C(ymult*om); mats=S(ymult*om) ymat=numpy.array([[1,0,0,0],[0,matc,0,-mats],[0,0,1,0],[0,mats,0,matc]]) matc=C(zmult*om); mats=S(zmult*om) zmat=numpy.array([[1,0,0,0],[0,1,0,0],[0,0,matc,-mats],[0,0,mats,matc]]) om += dom glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) for th in range(0 ,360+dangle,dangle): glBegin(GL_QUAD_STRIP) for ta in range (0,360+dangle, dangle): drawvert(th,ta, xmat, ymat, zmat) drawvert(th+dgap,ta, xmat, ymat, zmat) glEnd() #assign initial window and mouse settings wd = 800 ht = 800 mouseX = wd/2 mouseY = ht/2 brake = 500. def display(): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glMatrixMode(GL_MODELVIEW) glLoadIdentity() glMultMatrixf(aff) drawsurf() glutSwapBuffers() #typical keyboard callback def keyboard(key, x, y): if key == chr(27) or key == 'q': sys.exit(0) glutPostRedisplay() #adjust to resizing of the window def reshape(width, height): global wd global ht glClearColor(0.0, 0.0, 0.0, 0.0) if height == 0: height = 1 wd = width ht = height glViewport(0,0,wd,ht) glMatrixMode(GL_PROJECTION) glLoadIdentity() if wd<=ht: glOrtho(-nrange,nrange,-nrange*ht/wd,nrange*ht/wd,-nrange,nrange) else: glOrtho(-nrange*wd/ht,nrange*wd/ht,-nrange,nrange,-nrange,nrange) glMatrixMode(GL_MODELVIEW) glLoadIdentity() #Note that we must declare the globals again def chaptrack(): global mouseX global mouseY global wd global ht global aff dx = (mouseX-wd/2)/brake if dx*dx < .1: dx =0 dy = (mouseY-ht/2)/brake; if dy*dy < .1: dy =0 glMatrixMode(GL_TEXTURE) glPushMatrix() glLoadIdentity() glRotatef(dx,0,1.0,0.0) glRotatef(dy,1.0,0.0,0.0) glMultMatrixf(aff) aff = glGetFloatv(GL_TEXTURE_MATRIX) glPopMatrix() #traditional idle def idle(): chaptrack() glutPostRedisplay() #ditto traditional mousemotion def mousemotion(x,y): global mouseX global mouseY mouseX = x mouseY = y def init(): glEnable(GL_DEPTH_TEST) glShadeModel(GL_SMOOTH) #Traditional main subroutine def main() : global wd global ht glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE) glutInitWindowPosition(50, 50) glutInitWindowSize(wd, ht) glutInit([]) glutCreateWindow("illiTorus") glutKeyboardFunc(keyboard) glutDisplayFunc(display) glutIdleFunc(idle) glutReshapeFunc(reshape) glutPassiveMotionFunc(mousemotion) init() glutMainLoop() if __name__=="__main__": main()