summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell D. Fish <fish@cs.utah.edu>2008-05-21 16:22:55 +0000
committerRussell D. Fish <fish@cs.utah.edu>2008-05-21 16:22:55 +0000
commit7ecf4fb89f6a169544f0126d3b8a49f7862f8477 (patch)
treeee3c3c550ea8cb054f4e9c37d476fb04aaf725b4
parentd2068d6297662cdea172df08d99830bfa9030c29 (diff)
downloadnanoengineer-theirix-7ecf4fb89f6a169544f0126d3b8a49f7862f8477.tar.gz
nanoengineer-theirix-7ecf4fb89f6a169544f0126d3b8a49f7862f8477.zip
Break up drawer.py
The globals tying together drawer.py have already been factored into a separate drawing_globals.py module. The remainder of drawer.py is now in 10 smaller modules: glprefs.py setup_draw.py shape_vertices.py ColorSorter.py CS_workers.py CS_ShapeList.py CS_draw_primitives.py drawers.py gl_lighting.py gl_buffers.py (Continuity of SVN history with drawer.py has been retained.) There is a large imports section cloned from drawer.py at the front of each of them. (I will remove the unused imports as a separate phase.) All imports from graphics.drawing.drawer have been pointed to the new modules.
-rwxr-xr-xcad/src/analysis/ESP/ESPImage.py10
-rwxr-xr-xcad/src/analysis/GAMESS/jig_Gamess.py2
-rwxr-xr-xcad/src/command_support/GraphicsMode.py10
-rwxr-xr-xcad/src/commands/BuildAtoms/BuildAtoms_GraphicsMode.py2
-rwxr-xr-xcad/src/commands/BuildCrystal/CookieShape.py14
-rwxr-xr-xcad/src/commands/BuildCrystal/cookieMode.py12
-rwxr-xr-xcad/src/commands/Extrude/extrudeMode.py2
-rwxr-xr-xcad/src/commands/Fuse/FuseChunks_GraphicsMode.py2
-rw-r--r--cad/src/dna/commands/MultipleDnaSegmentResize/MultipleDnaSegmentResize_GraphicsMode.py63
-rw-r--r--cad/src/dna/model/DnaMarker.py2
-rw-r--r--cad/src/dna/updater/dna_updater_debug.py2
-rw-r--r--cad/src/exprs/Arrow.py5
-rwxr-xr-xcad/src/exprs/Rect.py4
-rwxr-xr-xcad/src/exprs/dna_ribbon_view.py6
-rwxr-xr-xcad/src/exprs/scratch/dna_ribbon_view_scraps.py1
-rw-r--r--cad/src/exprs/scratch/test_animation_mode.py7
-rwxr-xr-xcad/src/exprs/test.py2
-rw-r--r--cad/src/geometry/BoundingBox.py2
-rwxr-xr-xcad/src/graphics/behaviors/shape.py4
-rwxr-xr-xcad/src/graphics/display_styles/CylinderChunks.py4
-rw-r--r--cad/src/graphics/display_styles/DnaCylinderChunks.py12
-rwxr-xr-xcad/src/graphics/display_styles/SurfaceChunks.py6
-rw-r--r--cad/src/graphics/drawables/DirectionArrow.py2
-rw-r--r--cad/src/graphics/drawables/ResizeHandle.py3
-rwxr-xr-xcad/src/graphics/drawables/handles.py2
-rwxr-xr-xcad/src/graphics/drawing/CS_ShapeList.py472
-rwxr-xr-xcad/src/graphics/drawing/CS_draw_primitives.py417
-rwxr-xr-xcad/src/graphics/drawing/CS_workers.py431
-rwxr-xr-xcad/src/graphics/drawing/ColorSorter.py879
-rwxr-xr-xcad/src/graphics/drawing/Font3D.py2
-rwxr-xr-xcad/src/graphics/drawing/bond_drawer.py10
-rwxr-xr-xcad/src/graphics/drawing/dimensions.py2
-rwxr-xr-xcad/src/graphics/drawing/drawDnaLadder.py6
-rwxr-xr-xcad/src/graphics/drawing/drawDnaRibbons.py10
-rw-r--r--cad/src/graphics/drawing/drawNanotubeLadder.py6
-rwxr-xr-xcad/src/graphics/drawing/draw_bond_vanes.py2
-rw-r--r--cad/src/graphics/drawing/draw_grid_lines.py2
-rwxr-xr-xcad/src/graphics/drawing/drawer.py3975
-rwxr-xr-xcad/src/graphics/drawing/drawers.py1158
-rw-r--r--cad/src/graphics/drawing/drawing_globals.py30
-rwxr-xr-xcad/src/graphics/drawing/gl_buffers.py267
-rwxr-xr-xcad/src/graphics/drawing/gl_lighting.py451
-rwxr-xr-xcad/src/graphics/drawing/glprefs.py294
-rwxr-xr-xcad/src/graphics/drawing/setup_draw.py544
-rwxr-xr-xcad/src/graphics/drawing/shape_vertices.py648
-rwxr-xr-xcad/src/graphics/widgets/GLPane.py24
-rw-r--r--cad/src/graphics/widgets/GLPane_minimal.py2
-rwxr-xr-xcad/src/graphics/widgets/ThumbView.py8
-rwxr-xr-xcad/src/model/Line.py2
-rwxr-xr-xcad/src/model/Plane.py3
-rwxr-xr-xcad/src/model/chem.py10
-rwxr-xr-xcad/src/model/chunk.py6
-rwxr-xr-xcad/src/model/jigs.py2
-rwxr-xr-xcad/src/model/jigs_measurements.py2
-rwxr-xr-xcad/src/model/jigs_motors.py8
-rwxr-xr-xcad/src/model/jigs_planes.py2
-rw-r--r--cad/src/model/virtual_site_indicators.py3
-rwxr-xr-xcad/src/ne1_ui/MWsemantics.py2
-rw-r--r--cad/src/prototype/example_expr_command.py2
-rw-r--r--cad/src/prototype/test_connectWithState.py4
-rw-r--r--cad/src/temporary_commands/LineMode.py3
-rwxr-xr-xcad/src/temporary_commands/ZoomToAreaMode.py2
62 files changed, 5744 insertions, 4128 deletions
diff --git a/cad/src/analysis/ESP/ESPImage.py b/cad/src/analysis/ESP/ESPImage.py
index a392810be..ec19c168f 100755
--- a/cad/src/analysis/ESP/ESPImage.py
+++ b/cad/src/analysis/ESP/ESPImage.py
@@ -66,9 +66,9 @@ from foundation.state_utils import DataMixin
from model.chunk import Chunk
from model.chem import Atom
-from graphics.drawing.drawer import drawPlane
-from graphics.drawing.drawer import drawwirecube
-from graphics.drawing.drawer import drawLineLoop
+from graphics.drawing.drawers import drawPlane
+from graphics.drawing.drawers import drawwirecube
+from graphics.drawing.drawers import drawLineLoop
from geometry.VQT import V, Q, A
from graphics.rendering.povray.povheader import povpoint
@@ -391,7 +391,7 @@ class ESPImage(RectGadget):
# This is for debugging purposes. This draws a green normal vector using
# local space coords. Mark 050930
if 0:
- from graphics.drawing.drawer import drawline
+ from graphics.drawing.CS_draw_primitives import drawline
drawline(green, V(0.0, 0.0, 0.0), V(0.0, 0.0, 1.0), 0, 3)
glPopMatrix()
@@ -399,7 +399,7 @@ class ESPImage(RectGadget):
# This is for debugging purposes. This draws a yellow normal vector using
# model space coords. Mark 050930
if 0:
- from graphics.drawing.drawer import drawline
+ from graphics.drawing.CS_draw_primitives import drawline
from utilities.constants import yellow
drawline(yellow, self.center, self.center + self.planeNorm, 0, 3)
diff --git a/cad/src/analysis/GAMESS/jig_Gamess.py b/cad/src/analysis/GAMESS/jig_Gamess.py
index f3b973b9a..ed64bcc70 100755
--- a/cad/src/analysis/GAMESS/jig_Gamess.py
+++ b/cad/src/analysis/GAMESS/jig_Gamess.py
@@ -10,7 +10,7 @@ jig_Gamess.py
import sys
from model.jigs import Jig
-from graphics.drawing.drawer import drawwirecube
+from graphics.drawing.drawers import drawwirecube
from graphics.rendering.povray.povheader import povpoint # Fix for bug 692 Mark 050628
from analysis.GAMESS.files_gms import get_energy_from_gms_outfile, get_atompos_from_gms_outfile
from utilities.Log import redmsg, greenmsg
diff --git a/cad/src/command_support/GraphicsMode.py b/cad/src/command_support/GraphicsMode.py
index aa39e3ec6..1dbf290a4 100755
--- a/cad/src/command_support/GraphicsMode.py
+++ b/cad/src/command_support/GraphicsMode.py
@@ -29,11 +29,11 @@ from PyQt4.Qt import Qt
from PyQt4.Qt import QMenu
from geometry.VQT import V, Q, vlen, norm, planeXline, ptonline, cross
-from graphics.drawing.drawer import drawline
-from graphics.drawing.drawer import drawOriginAsSmallAxis
-from graphics.drawing.drawer import drawTag
-from graphics.drawing.drawer import drawaxes
-from graphics.drawing.drawer import drawrectangle
+from graphics.drawing.CS_draw_primitives import drawline
+from graphics.drawing.CS_draw_primitives import drawTag
+from graphics.drawing.drawers import drawOriginAsSmallAxis
+from graphics.drawing.drawers import drawaxes
+from graphics.drawing.drawers import drawrectangle
from utilities.debug import print_compact_traceback
diff --git a/cad/src/commands/BuildAtoms/BuildAtoms_GraphicsMode.py b/cad/src/commands/BuildAtoms/BuildAtoms_GraphicsMode.py
index 69f7e4d49..a279c6ab2 100755
--- a/cad/src/commands/BuildAtoms/BuildAtoms_GraphicsMode.py
+++ b/cad/src/commands/BuildAtoms/BuildAtoms_GraphicsMode.py
@@ -67,7 +67,7 @@ from model.chem import oneUnbonded
from model.elements import Singlet
from geometry.VQT import Q, A, norm, twistor
-from graphics.drawing.drawer import drawline
+from graphics.drawing.CS_draw_primitives import drawline
from foundation.Group import Group
from foundation.Utility import Node
diff --git a/cad/src/commands/BuildCrystal/CookieShape.py b/cad/src/commands/BuildCrystal/CookieShape.py
index 3f32bf6c3..fd55b086e 100755
--- a/cad/src/commands/BuildCrystal/CookieShape.py
+++ b/cad/src/commands/BuildCrystal/CookieShape.py
@@ -26,13 +26,13 @@ from geometry.VQT import vlen, V
from OpenGL.GL import glNewList, glEndList, glCallList
from OpenGL.GL import GL_COMPILE_AND_EXECUTE
-from graphics.drawing.drawer import drawCircle
-from graphics.drawing.drawer import genDiam
-from graphics.drawing.drawer import drawcylinder
-from graphics.drawing.drawer import drawsphere
-from graphics.drawing.drawer import drawline
-from graphics.drawing.drawer import ColorSorter
-from graphics.drawing.drawer import ColorSortedDisplayList
+from graphics.drawing.drawers import drawCircle
+from graphics.drawing.drawers import genDiam
+from graphics.drawing.CS_draw_primitives import drawcylinder
+from graphics.drawing.CS_draw_primitives import drawsphere
+from graphics.drawing.CS_draw_primitives import drawline
+from graphics.drawing.ColorSorter import ColorSorter
+from graphics.drawing.ColorSorter import ColorSortedDisplayList
from utilities.constants import SUBTRACT_FROM_SELECTION
from utilities.constants import OUTSIDE_SUBTRACT_FROM_SELECTION
diff --git a/cad/src/commands/BuildCrystal/cookieMode.py b/cad/src/commands/BuildCrystal/cookieMode.py
index ba5ea181c..66fa335fd 100755
--- a/cad/src/commands/BuildCrystal/cookieMode.py
+++ b/cad/src/commands/BuildCrystal/cookieMode.py
@@ -43,12 +43,12 @@ from geometry.Slab import Slab
from commands.BuildCrystal.CookieShape import CookieShape
import graphics.drawing.drawing_globals as drawing_globals
-from graphics.drawing.drawer import drawline
-from graphics.drawing.drawer import drawCircle
-from graphics.drawing.drawer import drawGrid
-from graphics.drawing.drawer import drawLineLoop
-from graphics.drawing.drawer import drawrectangle
-from graphics.drawing.drawer import findCell
+from graphics.drawing.CS_draw_primitives import drawline
+from graphics.drawing.drawers import drawCircle
+from graphics.drawing.drawers import drawGrid
+from graphics.drawing.drawers import drawLineLoop
+from graphics.drawing.drawers import drawrectangle
+from graphics.drawing.drawers import findCell
from model.chunk import Chunk
from model.chem import Atom
diff --git a/cad/src/commands/Extrude/extrudeMode.py b/cad/src/commands/Extrude/extrudeMode.py
index e761a4e15..c0731e85a 100755
--- a/cad/src/commands/Extrude/extrudeMode.py
+++ b/cad/src/commands/Extrude/extrudeMode.py
@@ -62,7 +62,7 @@ from geometry.VQT import V, Q, norm, vlen, cross
from commands.Extrude.ExtrudePropertyManager import ExtrudePropertyManager
-from graphics.drawing.drawer import drawline
+from graphics.drawing.CS_draw_primitives import drawline
from model.chunk import Chunk
from graphics.behaviors.shape import get_selCurve_color
diff --git a/cad/src/commands/Fuse/FuseChunks_GraphicsMode.py b/cad/src/commands/Fuse/FuseChunks_GraphicsMode.py
index 2a9a51c33..70ebc31f1 100755
--- a/cad/src/commands/Fuse/FuseChunks_GraphicsMode.py
+++ b/cad/src/commands/Fuse/FuseChunks_GraphicsMode.py
@@ -12,7 +12,7 @@ Ninad 2008-01-25: Split Command and GraphicsMode classes
out of class fuseChunksMode. The command class can be
found in FuseChunks_Command.py
"""
-from graphics.drawing.drawer import drawline
+from graphics.drawing.CS_draw_primitives import drawline
from graphics.behaviors.shape import get_selCurve_color
from utilities.constants import green
diff --git a/cad/src/dna/commands/MultipleDnaSegmentResize/MultipleDnaSegmentResize_GraphicsMode.py b/cad/src/dna/commands/MultipleDnaSegmentResize/MultipleDnaSegmentResize_GraphicsMode.py
index 80b80ec25..5e170311e 100644
--- a/cad/src/dna/commands/MultipleDnaSegmentResize/MultipleDnaSegmentResize_GraphicsMode.py
+++ b/cad/src/dna/commands/MultipleDnaSegmentResize/MultipleDnaSegmentResize_GraphicsMode.py
@@ -17,7 +17,8 @@ from dna.commands.DnaSegment.DnaSegment_GraphicsMode import DnaSegment_GraphicsM
from PyQt4.Qt import Qt
from graphics.drawing.drawDnaRibbons import drawDnaRibbons
from utilities.constants import black, banana, silver, lighterblue, darkred, darkgreen
-from graphics.drawing import drawer
+from graphics.drawing.CS_draw_primitives import drawcylinder
+from graphics.drawing.CS_draw_primitives import drawsphere
SPHERE_RADIUS = 6.0
SPHERE_DRAWLEVEL = 2
@@ -129,12 +130,13 @@ class MultipleDnaSegmentResize_GraphicsMode(DnaSegment_GraphicsMode):
for segment in segmentList:
end1, end2 = segment.getAxisEndPoints()
if end1 is not None and end2 is not None:
- drawer.drawcylinder(banana,
- end1,
- end2,
- CYL_RADIUS,
- capped = True,
- opacity = CYL_OPACITY )
+ drawcylinder(banana,
+ end1,
+ end2,
+ CYL_RADIUS,
+ capped = True,
+ opacity = CYL_OPACITY )
+
def _drawTags(self):
"""
Overrides _superClass._drawTags()
@@ -149,12 +151,11 @@ class MultipleDnaSegmentResize_GraphicsMode(DnaSegment_GraphicsMode):
if self._tagPositions:
for point in self._tagPositions:
- drawer.drawsphere(silver,
- point,
- SPHERE_RADIUS,
- SPHERE_DRAWLEVEL,
- opacity = SPHERE_OPACITY)
-
+ drawsphere(silver,
+ point,
+ SPHERE_RADIUS,
+ SPHERE_DRAWLEVEL,
+ opacity = SPHERE_OPACITY)
def _DEBUG_Flag_EndPoint1_ofDnaSegments(self):
"""
@@ -172,11 +173,11 @@ class MultipleDnaSegmentResize_GraphicsMode(DnaSegment_GraphicsMode):
if e1 is not None:
endPoints_1.append(e1)
for end1 in endPoints_1:
- drawer.drawsphere(lighterblue,
- end1,
- SPHERE_RADIUS,
- SPHERE_DRAWLEVEL,
- opacity = 1.0)
+ drawsphere(lighterblue,
+ end1,
+ SPHERE_RADIUS,
+ SPHERE_DRAWLEVEL,
+ opacity = 1.0)
def _drawDnaRubberbandLine(self):
"""
@@ -242,11 +243,11 @@ class MultipleDnaSegmentResize_GraphicsMode(DnaSegment_GraphicsMode):
#Draw a sphere that indicates the current position of
#the resize end of each segment .
- drawer.drawsphere(darkgreen,
- end2,
- SPHERE_RADIUS_2,
- SPHERE_DRAWLEVEL,
- opacity = SPHERE_OPACITY)
+ drawsphere(darkgreen,
+ end2,
+ SPHERE_RADIUS_2,
+ SPHERE_DRAWLEVEL,
+ opacity = SPHERE_OPACITY)
numberOfBasePairsString = "+" + str(numberOfBasePairs)
self.glpane.renderTextAtPosition( end2,
@@ -256,23 +257,17 @@ class MultipleDnaSegmentResize_GraphicsMode(DnaSegment_GraphicsMode):
numberOfBasePairs , end2 = params_when_removing_bases
#Draw a sphere that indicates the current position of
#the resize end of each segment.
- drawer.drawsphere(darkred,
- end2,
- SPHERE_RADIUS_2,
- SPHERE_DRAWLEVEL,
- opacity = SPHERE_OPACITY)
+ drawsphere(darkred,
+ end2,
+ SPHERE_RADIUS_2,
+ SPHERE_DRAWLEVEL,
+ opacity = SPHERE_OPACITY)
numberOfBasePairsString = str(numberOfBasePairs)
self.glpane.renderTextAtPosition( end2,
textString = numberOfBasePairsString,
)
-
-
-
#Draw the text next to the cursor that gives info about
#number of base pairs etc
self._drawCursorText()
-
-
-
diff --git a/cad/src/dna/model/DnaMarker.py b/cad/src/dna/model/DnaMarker.py
index 3d17f9727..e3a5ae924 100644
--- a/cad/src/dna/model/DnaMarker.py
+++ b/cad/src/dna/model/DnaMarker.py
@@ -27,7 +27,7 @@ from dna.updater.dna_updater_prefs import pref_draw_internal_markers
from utilities import debug_flags
-from graphics.drawing.drawer import drawwirecube
+from graphics.drawing.drawers import drawwirecube
from utilities.constants import orange
diff --git a/cad/src/dna/updater/dna_updater_debug.py b/cad/src/dna/updater/dna_updater_debug.py
index f86f79a13..5e5be1ceb 100644
--- a/cad/src/dna/updater/dna_updater_debug.py
+++ b/cad/src/dna/updater/dna_updater_debug.py
@@ -9,7 +9,7 @@ dna_updater_debug.py -- debug code for dna_updater
from utilities import debug_flags
-from graphics.drawing.drawer import drawline
+from graphics.drawing.CS_draw_primitives import drawline
from model.jigs import Jig
diff --git a/cad/src/exprs/Arrow.py b/cad/src/exprs/Arrow.py
index eb298ad1e..c57dfe777 100644
--- a/cad/src/exprs/Arrow.py
+++ b/cad/src/exprs/Arrow.py
@@ -14,8 +14,7 @@ from exprs.ExprsConstants import Color, Position, ORIGIN, DX
from utilities.constants import gray
-from graphics.drawing.drawer import drawDirectionArrow
-
+from graphics.drawing.CS_draw_primitives import drawDirectionArrow
class Arrow(Widget2D):
"""
@@ -40,4 +39,4 @@ class Arrow(Widget2D):
numberOfSides = 6
)
- \ No newline at end of file
+
diff --git a/cad/src/exprs/Rect.py b/cad/src/exprs/Rect.py
index 26cfca1d4..e4c9206f3 100755
--- a/cad/src/exprs/Rect.py
+++ b/cad/src/exprs/Rect.py
@@ -34,8 +34,8 @@ from exprs.__Symbols__ import _self
from exprs.py_utils import printnim, printfyi
-from graphics.drawing.drawer import drawsphere # drawsphere(color, pos, radius, detailLevel)
-from graphics.drawing.drawer import drawline
+from graphics.drawing.CS_draw_primitives import drawsphere
+from graphics.drawing.CS_draw_primitives import drawline
# ==
diff --git a/cad/src/exprs/dna_ribbon_view.py b/cad/src/exprs/dna_ribbon_view.py
index 7f69d9ff1..1858ec5c9 100755
--- a/cad/src/exprs/dna_ribbon_view.py
+++ b/cad/src/exprs/dna_ribbon_view.py
@@ -101,9 +101,9 @@ from OpenGL.GL import GL_FALSE
from exprs.Overlay import Overlay
-from graphics.drawing.drawer import drawcylinder
-from graphics.drawing.drawer import drawsphere # drawsphere(color, pos, radius, detailLevel)
-from graphics.drawing.drawer import drawline
+from graphics.drawing.CS_draw_primitives import drawcylinder
+from graphics.drawing.CS_draw_primitives import drawsphere
+from graphics.drawing.CS_draw_primitives import drawline
from exprs.world import World
diff --git a/cad/src/exprs/scratch/dna_ribbon_view_scraps.py b/cad/src/exprs/scratch/dna_ribbon_view_scraps.py
index 929fabe16..b62d2e2f0 100755
--- a/cad/src/exprs/scratch/dna_ribbon_view_scraps.py
+++ b/cad/src/exprs/scratch/dna_ribbon_view_scraps.py
@@ -21,7 +21,6 @@ from Overlay import Overlay
from TextRect import TextRect
from OpenGL.GL import * #e move what needs this into draw_utils
-import graphics.drawing.drawer as drawer
from dna_ribbon_view import * ###e reloadable -- needed at least for IorE, probably more
from utilities import debug_flags
diff --git a/cad/src/exprs/scratch/test_animation_mode.py b/cad/src/exprs/scratch/test_animation_mode.py
index c2eceb71a..bb031e31b 100644
--- a/cad/src/exprs/scratch/test_animation_mode.py
+++ b/cad/src/exprs/scratch/test_animation_mode.py
@@ -68,7 +68,10 @@ from foundation.state_utils import copy_val
from utilities.constants import green, red, white, pink, black, brown, gray # other colors below
from math import pi
-from graphics.drawing.drawer import drawline, drawbrick, drawsphere, drawcylinder
+from graphics.drawing.CS_draw_primitives import drawline
+from graphics.drawing.drawers import drawbrick
+from graphics.drawing.CS_draw_primitives import drawsphere
+from graphics.drawing.CS_draw_primitives import drawcylinder
from OpenGL.GL import GL_LIGHTING, glDisable, glEnable
from geometry.VQT import cross, proj2sphere, V, norm, Q, vlen
@@ -967,7 +970,7 @@ annoyers = [##'editToolbar', 'fileToolbar', 'helpToolbar', 'modifyToolbar',
# code copied from test_commands.py:
# these imports are not needed in a minimal example like ExampleCommand2;
# to make that clear, we put them down here instead of at the top of the file
-from graphics.drawing.drawer import drawline
+from graphics.drawing.CS_draw_primitives import drawline
from utilities.constants import red, green
##from exprs.ExprsConstants import PIXELS
from exprs.images import Image
diff --git a/cad/src/exprs/test.py b/cad/src/exprs/test.py
index 55e213265..5bd08c0b0 100755
--- a/cad/src/exprs/test.py
+++ b/cad/src/exprs/test.py
@@ -144,7 +144,7 @@ from utilities.constants import ave_colors, noop
from utilities.prefs_constants import displayOriginAxis_prefs_key
from graphics.drawing.texture_fonts import courierfile
-from graphics.drawing.drawer import drawline
+from graphics.drawing.CS_draw_primitives import drawline
from exprs.reload import exprs_globals
diff --git a/cad/src/geometry/BoundingBox.py b/cad/src/geometry/BoundingBox.py
index 593fcb6bc..935f5432b 100644
--- a/cad/src/geometry/BoundingBox.py
+++ b/cad/src/geometry/BoundingBox.py
@@ -19,7 +19,7 @@ even though it also includes graphics code, and hardcoded constants
about its use for our model objects (atoms).
"""
-from graphics.drawing.drawer import drawwirebox
+from graphics.drawing.drawers import drawwirebox
from Numeric import add, subtract, sqrt
from Numeric import maximum, minimum, dot
diff --git a/cad/src/graphics/behaviors/shape.py b/cad/src/graphics/behaviors/shape.py
index 4b80a6d68..b84993ddc 100755
--- a/cad/src/graphics/behaviors/shape.py
+++ b/cad/src/graphics/behaviors/shape.py
@@ -32,8 +32,8 @@ from Numeric import array, zeros, maximum, minimum, ceil, dot, floor
from geometry.VQT import A, vlen, V
-from graphics.drawing.drawer import drawrectangle
-from graphics.drawing.drawer import drawline
+from graphics.drawing.drawers import drawrectangle
+from graphics.drawing.CS_draw_primitives import drawline
from utilities.constants import black
from utilities.constants import DELETE_SELECTION
diff --git a/cad/src/graphics/display_styles/CylinderChunks.py b/cad/src/graphics/display_styles/CylinderChunks.py
index 0d1fe2821..c1cf94f6d 100755
--- a/cad/src/graphics/display_styles/CylinderChunks.py
+++ b/cad/src/graphics/display_styles/CylinderChunks.py
@@ -14,8 +14,8 @@ though it might be useful as a fast-rendering display mode too.
from Numeric import dot, argmax, argmin, sqrt
import foundation.env as env
-from graphics.drawing.drawer import drawcylinder
-from graphics.drawing.drawer import drawcylinder_wireframe
+from graphics.drawing.CS_draw_primitives import drawcylinder
+from graphics.drawing.CS_draw_primitives import drawcylinder_wireframe
from geometry.geometryUtilities import matrix_putting_axis_at_z
from geometry.VQT import V, norm
from utilities.debug import print_compact_traceback
diff --git a/cad/src/graphics/display_styles/DnaCylinderChunks.py b/cad/src/graphics/display_styles/DnaCylinderChunks.py
index d9c22e439..1cc371b2f 100644
--- a/cad/src/graphics/display_styles/DnaCylinderChunks.py
+++ b/cad/src/graphics/display_styles/DnaCylinderChunks.py
@@ -42,12 +42,12 @@ piotr 080520: Further code cleanup..
import sys
import foundation.env as env
-from graphics.drawing.drawer import drawcylinder
-from graphics.drawing.drawer import drawpolycone
-from graphics.drawing.drawer import drawpolycone_multicolor
-from graphics.drawing.drawer import drawsphere
-from graphics.drawing.drawer import drawCircle
-from graphics.drawing.drawer import drawFilledCircle
+from graphics.drawing.CS_draw_primitives import drawcylinder
+from graphics.drawing.CS_draw_primitives import drawpolycone
+from graphics.drawing.CS_draw_primitives import drawpolycone_multicolor
+from graphics.drawing.CS_draw_primitives import drawsphere
+from graphics.drawing.drawers import drawCircle
+from graphics.drawing.drawers import drawFilledCircle
from math import sin, cos, pi
from Numeric import dot, argmax, argmin, sqrt
diff --git a/cad/src/graphics/display_styles/SurfaceChunks.py b/cad/src/graphics/display_styles/SurfaceChunks.py
index 9e4410e85..54a85461e 100755
--- a/cad/src/graphics/display_styles/SurfaceChunks.py
+++ b/cad/src/graphics/display_styles/SurfaceChunks.py
@@ -22,9 +22,9 @@ import types
from PyQt4.Qt import QApplication, Qt, QCursor
import foundation.env as env
-from graphics.drawing.drawer import drawsurface
-from graphics.drawing.drawer import drawsurface_wireframe
-from graphics.drawing.drawer import getSphereTriangles
+from graphics.drawing.CS_draw_primitives import drawsurface
+from graphics.drawing.CS_draw_primitives import drawsurface_wireframe
+from graphics.drawing.shape_vertices import getSphereTriangles
from geometry.VQT import V, cross
from utilities.Log import greenmsg
from graphics.display_styles.displaymodes import ChunkDisplayMode
diff --git a/cad/src/graphics/drawables/DirectionArrow.py b/cad/src/graphics/drawables/DirectionArrow.py
index 787a59367..fa15026f6 100644
--- a/cad/src/graphics/drawables/DirectionArrow.py
+++ b/cad/src/graphics/drawables/DirectionArrow.py
@@ -23,7 +23,7 @@ from OpenGL.GL import glTranslatef
from OpenGL.GL import glRotatef
from OpenGL.GL import glPopMatrix
-from graphics.drawing.drawer import drawDirectionArrow
+from graphics.drawing.CS_draw_primitives import drawDirectionArrow
from geometry.VQT import V, norm, vlen
from math import pi
diff --git a/cad/src/graphics/drawables/ResizeHandle.py b/cad/src/graphics/drawables/ResizeHandle.py
index d42046e89..afc759df3 100644
--- a/cad/src/graphics/drawables/ResizeHandle.py
+++ b/cad/src/graphics/drawables/ResizeHandle.py
@@ -21,7 +21,8 @@ from OpenGL.GL import glPopMatrix
from OpenGL.GL import glTranslatef
from OpenGL.GL import glRotatef
-from graphics.drawing.drawer import drawLineLoop, drawPlane
+from graphics.drawing.drawers import drawLineLoop
+from graphics.drawing.drawers import drawPlane
from utilities.constants import black, orange, darkgreen
from math import pi
diff --git a/cad/src/graphics/drawables/handles.py b/cad/src/graphics/drawables/handles.py
index d2afc26ee..bbf79a1fb 100755
--- a/cad/src/graphics/drawables/handles.py
+++ b/cad/src/graphics/drawables/handles.py
@@ -20,7 +20,7 @@ from geometry.VQT import V
from geometry.VQT import vlen
from geometry.VQT import norm
from geometry.VQT import orthodist
-from graphics.drawing.drawer import drawsphere
+from graphics.drawing.CS_draw_primitives import drawsphere
from utilities.constants import ave_colors
from utilities.constants import magenta
from utilities.constants import blue
diff --git a/cad/src/graphics/drawing/CS_ShapeList.py b/cad/src/graphics/drawing/CS_ShapeList.py
new file mode 100755
index 000000000..a061833cf
--- /dev/null
+++ b/cad/src/graphics/drawing/CS_ShapeList.py
@@ -0,0 +1,472 @@
+# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
+"""
+CS_ShapeList.py - The C++ ColorSorter's arrays of primitives to draw.
+
+Does some memoization as a speedup.
+
+@version: $Id$
+@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
+
+History:
+
+Originated by Josh as drawer.py .
+
+Various developers extended it since then.
+
+Brad G. added ColorSorter features.
+
+At some point Bruce partly cleaned up the use of display lists.
+
+071030 bruce split some functions and globals into draw_grid_lines.py
+and removed some obsolete functions.
+
+080210 russ Split the single display-list into two second-level lists (with and
+without color) and a set of per-color sublists so selection and hover-highlight
+can over-ride Chunk base colors. ColorSortedDisplayList is now a class in the
+parent's displist attr to keep track of all that stuff.
+
+080311 piotr Added a "drawpolycone_multicolor" function for drawing polycone
+tubes with per-vertex colors (necessary for DNA display style)
+
+080313 russ Added triangle-strip icosa-sphere constructor, "getSphereTriStrips".
+
+080420 piotr Solved highlighting and selection problems for multi-colored
+objects (e.g. rainbow colored DNA structures).
+
+080519 russ pulled the globals into a drawing_globals module and broke drawer.py
+into 10 smaller chunks: glprefs.py setup_draw.py shape_vertices.py
+ColorSorter.py CS_workers.py CS_ShapeList.py CS_draw_primitives.py drawers.py
+gl_lighting.py gl_buffers.py
+"""
+
+import os
+import sys
+
+# the imports from math vs. Numeric are as discovered in existing code
+# as of 2007/06/25. It's not clear why acos is coming from math...
+from math import floor, ceil, acos, atan2
+import Numeric
+from Numeric import sin, cos, sqrt, pi
+degreesPerRadian = 180.0 / pi
+
+# russ 080519 No doubt many of the following imports are unused.
+# When the dust settles, the unnecessary ones will be removed.
+from OpenGL.GL import GL_AMBIENT
+from OpenGL.GL import GL_AMBIENT_AND_DIFFUSE
+from OpenGL.GL import glAreTexturesResident
+from OpenGL.GL import GL_ARRAY_BUFFER_ARB
+from OpenGL.GL import GL_BACK
+from OpenGL.GL import glBegin
+from OpenGL.GL import glBindTexture
+from OpenGL.GL import GL_BLEND
+from OpenGL.GL import glBlendFunc
+from OpenGL.GL import glCallList
+from OpenGL.GL import glColor3f
+from OpenGL.GL import glColor3fv
+from OpenGL.GL import glColor4fv
+from OpenGL.GL import GL_COLOR_MATERIAL
+from OpenGL.GL import GL_COMPILE
+from OpenGL.GL import GL_COMPILE_AND_EXECUTE
+from OpenGL.GL import GL_CONSTANT_ATTENUATION
+from OpenGL.GL import GL_CULL_FACE
+from OpenGL.GL import GL_CURRENT_BIT
+from OpenGL.GL import glDeleteLists
+from OpenGL.GL import glDeleteTextures
+from OpenGL.GL import glDepthMask
+from OpenGL.GL import GL_DEPTH_TEST
+from OpenGL.GL import GL_DIFFUSE
+from OpenGL.GL import glDisable
+from OpenGL.GL import glDisableClientState
+from OpenGL.GL import glDrawArrays
+from OpenGL.GL import glDrawElements
+from OpenGL.GL import glDrawElementsub
+from OpenGL.GL import glDrawElementsui
+from OpenGL.GL import glDrawElementsus
+from OpenGL.GL import GL_ELEMENT_ARRAY_BUFFER_ARB
+from OpenGL.GL import glEnable
+from OpenGL.GL import glEnableClientState
+from OpenGL.GL import glEnd
+from OpenGL.GL import glEndList
+from OpenGL.GL import GL_EXTENSIONS
+from OpenGL.GL import GL_FALSE
+from OpenGL.GL import GL_FILL
+from OpenGL.GL import glFinish
+from OpenGL.GL import GL_FLOAT
+from OpenGL.GL import GL_FOG
+from OpenGL.GL import GL_FOG_COLOR
+from OpenGL.GL import GL_FOG_END
+from OpenGL.GL import GL_FOG_MODE
+from OpenGL.GL import GL_FOG_START
+from OpenGL.GL import GL_FRONT
+from OpenGL.GL import GL_FRONT_AND_BACK
+from OpenGL.GL import glGenLists
+from OpenGL.GL import glGenTextures
+from OpenGL.GL import glGetString
+from OpenGL.GL import GL_LIGHT0
+from OpenGL.GL import GL_LIGHT1
+from OpenGL.GL import GL_LIGHT2
+from OpenGL.GL import glLightf
+from OpenGL.GL import glLightfv
+from OpenGL.GL import GL_LIGHTING
+from OpenGL.GL import GL_LINE
+from OpenGL.GL import GL_LINEAR
+from OpenGL.GL import GL_LINE_LOOP
+from OpenGL.GL import GL_LINES
+from OpenGL.GL import GL_LINE_SMOOTH
+from OpenGL.GL import glLineStipple
+from OpenGL.GL import GL_LINE_STIPPLE
+from OpenGL.GL import GL_LINE_STRIP
+from OpenGL.GL import glLineWidth
+from OpenGL.GL import glLoadIdentity
+from OpenGL.GL import glMaterialf
+from OpenGL.GL import glMaterialfv
+from OpenGL.GL import glMatrixMode
+from OpenGL.GL import GL_MODELVIEW
+from OpenGL.GL import glNewList
+from OpenGL.GL import glNormal3fv
+from OpenGL.GL import glNormalPointer
+from OpenGL.GL import glNormalPointerf
+from OpenGL.GL import GL_NORMAL_ARRAY
+from OpenGL.GL import GL_ONE_MINUS_SRC_ALPHA
+from OpenGL.GL import glPointSize
+from OpenGL.GL import GL_POINTS
+from OpenGL.GL import GL_POINT_SMOOTH
+from OpenGL.GL import GL_POLYGON
+from OpenGL.GL import glPolygonMode
+from OpenGL.GL import glPopAttrib
+from OpenGL.GL import glPopMatrix
+from OpenGL.GL import glPopName
+from OpenGL.GL import GL_POSITION
+from OpenGL.GL import glPushAttrib
+from OpenGL.GL import glPushMatrix
+from OpenGL.GL import glPushName
+from OpenGL.GL import GL_QUADS
+from OpenGL.GL import GL_QUAD_STRIP
+from OpenGL.GL import GL_RENDERER
+from OpenGL.GL import GL_RGBA
+from OpenGL.GL import glRotate
+from OpenGL.GL import glRotatef
+from OpenGL.GL import GL_SHININESS
+from OpenGL.GL import GL_SPECULAR
+from OpenGL.GL import GL_SRC_ALPHA
+from OpenGL.GL import GL_STATIC_DRAW
+from OpenGL.GL import glTexCoord2f
+from OpenGL.GL import glTexCoord2fv
+from OpenGL.GL import GL_TEXTURE_2D
+from OpenGL.GL import glTranslate
+from OpenGL.GL import glTranslatef
+from OpenGL.GL import GL_TRIANGLES
+from OpenGL.GL import GL_TRIANGLE_STRIP
+from OpenGL.GL import GL_TRUE
+from OpenGL.GL import GL_UNSIGNED_BYTE
+from OpenGL.GL import GL_UNSIGNED_SHORT
+from OpenGL.GL import GL_VENDOR
+from OpenGL.GL import GL_VERSION
+from OpenGL.GL import glVertex
+from OpenGL.GL import glVertex2f
+from OpenGL.GL import glVertex3f
+from OpenGL.GL import glVertex3fv
+from OpenGL.GL import GL_VERTEX_ARRAY
+from OpenGL.GL import glVertexPointer
+from OpenGL.GL import glVertexPointerf
+
+from OpenGL.GLU import gluBuild2DMipmaps
+
+from geometry.VQT import norm, vlen, V, Q, A
+
+from utilities.constants import white, blue, red
+from utilities.constants import darkgreen, lightblue
+from utilities.constants import DIAMOND_BOND_LENGTH
+from utilities.prefs_constants import material_specular_highlights_prefs_key
+from utilities.prefs_constants import material_specular_shininess_prefs_key
+from utilities.prefs_constants import material_specular_finish_prefs_key
+from utilities.prefs_constants import material_specular_brightness_prefs_key
+
+from utilities.debug_prefs import Choice
+import utilities.debug as debug # for debug.print_compact_traceback
+
+#=
+
+import graphics.drawing.drawing_globals as drawing_globals
+if drawing_globals.quux_module_import_succeeded:
+ import quux
+
+class ShapeList_inplace:
+
+ """
+ Records sphere and cylinder data and invokes it through the native C++
+ rendering system.
+
+ This has the benefit over ShapeList that shapes aren't first stored in
+ lots of Python lists, and then turned into lots of Numeric arrays.
+ Instead, it stores directly in a list of fixed-size Numeric arrays.
+ It shows some speedup, but not a lot. And tons of memory is being
+ used. I'm not sure where. -grantham
+
+ """
+
+ __author__ = "grantham@plunk.org"
+
+ _blocking = 512 # balance between memory zeroing and drawing efficiency
+
+ def __init__(self):
+
+ #
+ # Lists of lists, each list containing a Numeric array and the
+ # number of objects in that array. E.g. Each element in
+ # sphere is [l, n], where l is array((m, 9), 'f'), n is the
+ # number of valid 9 element slices in l that represent
+ # spheres, and m is equal to or more than n+1.
+ #
+ self.spheres = []
+ self.cylinders = []
+
+ # If this is true, disallow future adds.
+ self.petrified = False
+
+
+ def draw(self):
+
+ """
+ Draw all the objects represented in this shape list.
+ """
+
+ for (spheres, count) in self.spheres:
+ quux.shapeRendererDrawSpheresIlvd(count, spheres)
+ for (cylinders, count) in self.cylinders:
+ quux.shapeRendererDrawCylindersIlvd(count, cylinders)
+
+
+ def add_sphere(self, color4, pos, radius, name = 0):
+ """
+ Add a sphere to this shape list.
+
+ "color4" must have 4 elements. "name" is the GL selection name.
+ """
+
+ if self.petrified:
+ raise ValueError, "Tried to add a sphere to a petrified ShapeList_inplace"
+
+ # struct Sphere {
+ # float m_color[4];
+ # float m_nameUInt;
+ # float m_center[3];
+ # float m_radius;
+ # };
+
+ if len(self.spheres) == 0 or self.spheres[-1][1] == ShapeList_inplace._blocking:
+ # size of struct Sphere in floats is 9
+ block = Numeric.zeros((ShapeList_inplace._blocking, 9), 'f')
+ self.spheres.append([block, 0])
+
+ (block, count) = self.spheres[-1]
+
+ block[count] = (\
+ color4[0], color4[1], color4[2], color4[3],
+ float(name),
+ pos[0], pos[1], pos[2],
+ radius)
+
+ self.spheres[-1][1] += 1
+
+
+ def add_cylinder(self, color4, pos1, pos2, radius, name = 0, capped=0):
+ """
+ Add a cylinder to this shape list.
+
+ "color4" must have 4 elements. "name" is the GL selection name.
+ """
+
+ if self.petrified:
+ raise ValueError, "Tried to add a cylinder to a petrified ShapeList_inplace"
+
+ # struct Cylinder {
+ # float m_color[4];
+ # float m_nameUInt;
+ # float m_cappedBool;
+ # float m_pos1[3];
+ # float m_pos2[3];
+ # float m_radius;
+ # };
+
+ if len(self.cylinders) == 0 or self.cylinders[-1][1] == ShapeList_inplace._blocking:
+ # size of struct Cylinder in floats is 13
+ block = Numeric.zeros((ShapeList_inplace._blocking, 13), 'f')
+ self.cylinders.append([block, 0])
+
+ (block, count) = self.cylinders[-1]
+
+ block[count] = (\
+ color4[0], color4[1], color4[2], color4[3],
+ float(name),
+ float(capped),
+ pos1[0], pos1[1], pos1[2],
+ pos2[0], pos2[1], pos2[2],
+ radius)
+
+ self.cylinders[-1][1] += 1
+
+
+ def petrify(self):
+ """
+ Make this object
+
+ Since the last block of shapes might not be full, this
+ function copies them to a new block exactly big enough to hold
+ the shapes in that block. The gc has a chance to release the
+ old block and reduce memory use. After this point, shapes
+ must not be added to this ShapeList.
+ """
+
+ self.petrified = True
+
+ if len(self.spheres) > 0:
+ count = self.spheres[-1][1]
+ if count < ShapeList_inplace._blocking:
+ block = self.spheres[-1][0]
+ newblock = Numeric.array(block[0:count], 'f')
+ self.spheres[-1][0] = newblock
+
+ if len(self.cylinders) > 0:
+ count = self.cylinders[-1][1]
+ if count < ShapeList_inplace._blocking:
+ block = self.cylinders[-1][0]
+ newblock = Numeric.array(block[0:count], 'f')
+ self.cylinders[-1][0] = newblock
+
+
+class ShapeList:
+
+ """
+ Records sphere and cylinder data and invokes it through the native C++
+ rendering system.
+
+ Probably better to use "ShapeList_inplace".
+ """
+
+ __author__ = "grantham@plunk.org"
+
+ def __init__(self):
+
+ self.memoized = False
+
+ self.sphere_colors = []
+ self.sphere_radii = []
+ self.sphere_centers = []
+ self.sphere_names = []
+
+ self.cylinder_colors = []
+ self.cylinder_radii = []
+ self.cylinder_pos1 = []
+ self.cylinder_pos2 = []
+ self.cylinder_cappings = []
+ self.cylinder_names = []
+
+
+ def _memoize(self):
+
+ """
+ Internal function that creates Numeric arrays from the data stored
+ in add_sphere and add-cylinder.
+ """
+
+ self.memoized = True
+
+ # GL Names are uint32. Numeric.array appears to have only
+ # int32. Winging it...
+
+ self.sphere_colors_array = Numeric.array(self.sphere_colors, 'f')
+ self.sphere_radii_array = Numeric.array(self.sphere_radii, 'f')
+ self.sphere_centers_array = Numeric.array(self.sphere_centers, 'f')
+ self.sphere_names_array = Numeric.array(self.sphere_names, 'i')
+
+ self.cylinder_colors_array = Numeric.array(self.cylinder_colors, 'f')
+ self.cylinder_radii_array = Numeric.array(self.cylinder_radii, 'f')
+ self.cylinder_pos1_array = Numeric.array(self.cylinder_pos1, 'f')
+ self.cylinder_pos2_array = Numeric.array(self.cylinder_pos2, 'f')
+ self.cylinder_cappings_array = Numeric.array(self.cylinder_cappings, 'f')
+ self.cylinder_names_array = Numeric.array(self.cylinder_names, 'i')
+
+
+ def draw(self):
+
+ """
+ Draw all the objects represented in this shape list.
+ """
+
+ # ICK - SLOW - Probably no big deal in a display list.
+
+ if len(self.sphere_radii) > 0:
+ if not self.memoized:
+ self._memoize()
+ quux.shapeRendererDrawSpheres(len(self.sphere_radii),
+ self.sphere_centers_array,
+ self.sphere_radii_array,
+ self.sphere_colors_array,
+ self.sphere_names_array)
+
+ if len(self.cylinder_radii) > 0:
+ if not self.memoized:
+ self._memoize()
+ quux.shapeRendererDrawCylinders(len(self.cylinder_radii),
+ self.cylinder_pos1_array,
+ self.cylinder_pos2_array,
+ self.cylinder_radii_array,
+ self.cylinder_cappings_array,
+ self.cylinder_colors_array,
+ self.cylinder_names_array)
+
+
+ def add_sphere(self, color4, pos, radius, name = 0):
+ """
+ Add a sphere to this shape list.
+
+ "color4" must have 4 elements. "name" is the GL selection name.
+ """
+
+ self.sphere_colors.append(color4)
+ self.sphere_centers.append(list(pos))
+ self.sphere_radii.append(radius)
+ self.sphere_names.append(name)
+ self.memoized = False
+
+
+ def add_cylinder(self, color4, pos1, pos2, radius, name = 0, capped=0):
+ """
+ Add a cylinder to this shape list.
+
+ "color4" must have 4 elements. "name" is the GL selection name.
+ """
+
+ self.cylinder_colors.append(color4)
+ self.cylinder_radii.append(radius)
+ self.cylinder_pos1.append(list(pos1))
+ self.cylinder_pos2.append(list(pos2))
+ self.cylinder_cappings.append(capped)
+ self.cylinder_names.append(name)
+ self.memoized = False
+
+
+ def petrify(self):
+ """
+ Delete all but the cached Numeric arrays.
+
+ Call this when you're sure you don't have any more shapes to store
+ in the shape list and you want to release the python lists of data
+ back to the heap. Additional shapes must not be added to this shape
+ list.
+ """
+ if not self.memoized:
+ self._memoize()
+
+ del self.sphere_colors
+ del self.sphere_radii
+ del self.sphere_centers
+ del self.sphere_names
+
+ del self.cylinder_colors
+ del self.cylinder_radii
+ del self.cylinder_pos1
+ del self.cylinder_pos2
+ del self.cylinder_cappings
+ del self.cylinder_names
diff --git a/cad/src/graphics/drawing/CS_draw_primitives.py b/cad/src/graphics/drawing/CS_draw_primitives.py
new file mode 100755
index 000000000..eefba073e
--- /dev/null
+++ b/cad/src/graphics/drawing/CS_draw_primitives.py
@@ -0,0 +1,417 @@
+# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
+"""
+CS_draw_primitives.py - Public entry points for ColorSorter drawing primitives.
+
+These functions all call ColorSorter.schedule_* methods, which record object
+data for sorting, including the object color and an eventual call on the
+appropriate drawing worker function.
+
+@version: $Id$
+@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
+
+History:
+
+Originated by Josh as drawer.py .
+
+Various developers extended it since then.
+
+Brad G. added ColorSorter features.
+
+At some point Bruce partly cleaned up the use of display lists.
+
+071030 bruce split some functions and globals into draw_grid_lines.py
+and removed some obsolete functions.
+
+080210 russ Split the single display-list into two second-level lists (with and
+without color) and a set of per-color sublists so selection and hover-highlight
+can over-ride Chunk base colors. ColorSortedDisplayList is now a class in the
+parent's displist attr to keep track of all that stuff.
+
+080311 piotr Added a "drawpolycone_multicolor" function for drawing polycone
+tubes with per-vertex colors (necessary for DNA display style)
+
+080313 russ Added triangle-strip icosa-sphere constructor, "getSphereTriStrips".
+
+080420 piotr Solved highlighting and selection problems for multi-colored
+objects (e.g. rainbow colored DNA structures).
+
+080519 russ pulled the globals into a drawing_globals module and broke drawer.py
+into 10 smaller chunks: glprefs.py setup_draw.py shape_vertices.py
+ColorSorter.py CS_workers.py CS_ShapeList.py CS_draw_primitives.py drawers.py
+gl_lighting.py gl_buffers.py
+"""
+
+import os
+import sys
+
+# the imports from math vs. Numeric are as discovered in existing code
+# as of 2007/06/25. It's not clear why acos is coming from math...
+from math import floor, ceil, acos, atan2
+import Numeric
+from Numeric import sin, cos, sqrt, pi
+degreesPerRadian = 180.0 / pi
+
+# russ 080519 No doubt many of the following imports are unused.
+# When the dust settles, the unnecessary ones will be removed.
+from OpenGL.GL import GL_AMBIENT
+from OpenGL.GL import GL_AMBIENT_AND_DIFFUSE
+from OpenGL.GL import glAreTexturesResident
+from OpenGL.GL import GL_ARRAY_BUFFER_ARB
+from OpenGL.GL import GL_BACK
+from OpenGL.GL import glBegin
+from OpenGL.GL import glBindTexture
+from OpenGL.GL import GL_BLEND
+from OpenGL.GL import glBlendFunc
+from OpenGL.GL import glCallList
+from OpenGL.GL import glColor3f
+from OpenGL.GL import glColor3fv
+from OpenGL.GL import glColor4fv
+from OpenGL.GL import GL_COLOR_MATERIAL
+from OpenGL.GL import GL_COMPILE
+from OpenGL.GL import GL_COMPILE_AND_EXECUTE
+from OpenGL.GL import GL_CONSTANT_ATTENUATION
+from OpenGL.GL import GL_CULL_FACE
+from OpenGL.GL import GL_CURRENT_BIT
+from OpenGL.GL import glDeleteLists
+from OpenGL.GL import glDeleteTextures
+from OpenGL.GL import glDepthMask
+from OpenGL.GL import GL_DEPTH_TEST
+from OpenGL.GL import GL_DIFFUSE
+from OpenGL.GL import glDisable
+from OpenGL.GL import glDisableClientState
+from OpenGL.GL import glDrawArrays
+from OpenGL.GL import glDrawElements
+from OpenGL.GL import glDrawElementsub
+from OpenGL.GL import glDrawElementsui
+from OpenGL.GL import glDrawElementsus
+from OpenGL.GL import GL_ELEMENT_ARRAY_BUFFER_ARB
+from OpenGL.GL import glEnable
+from OpenGL.GL import glEnableClientState
+from OpenGL.GL import glEnd
+from OpenGL.GL import glEndList
+from OpenGL.GL import GL_EXTENSIONS
+from OpenGL.GL import GL_FALSE
+from OpenGL.GL import GL_FILL
+from OpenGL.GL import glFinish
+from OpenGL.GL import GL_FLOAT
+from OpenGL.GL import GL_FOG
+from OpenGL.GL import GL_FOG_COLOR
+from OpenGL.GL import GL_FOG_END
+from OpenGL.GL import GL_FOG_MODE
+from OpenGL.GL import GL_FOG_START
+from OpenGL.GL import GL_FRONT
+from OpenGL.GL import GL_FRONT_AND_BACK
+from OpenGL.GL import glGenLists
+from OpenGL.GL import glGenTextures
+from OpenGL.GL import glGetString
+from OpenGL.GL import GL_LIGHT0
+from OpenGL.GL import GL_LIGHT1
+from OpenGL.GL import GL_LIGHT2
+from OpenGL.GL import glLightf
+from OpenGL.GL import glLightfv
+from OpenGL.GL import GL_LIGHTING
+from OpenGL.GL import GL_LINE
+from OpenGL.GL import GL_LINEAR
+from OpenGL.GL import GL_LINE_LOOP
+from OpenGL.GL import GL_LINES
+from OpenGL.GL import GL_LINE_SMOOTH
+from OpenGL.GL import glLineStipple
+from OpenGL.GL import GL_LINE_STIPPLE
+from OpenGL.GL import GL_LINE_STRIP
+from OpenGL.GL import glLineWidth
+from OpenGL.GL import glLoadIdentity
+from OpenGL.GL import glMaterialf
+from OpenGL.GL import glMaterialfv
+from OpenGL.GL import glMatrixMode
+from OpenGL.GL import GL_MODELVIEW
+from OpenGL.GL import glNewList
+from OpenGL.GL import glNormal3fv
+from OpenGL.GL import glNormalPointer
+from OpenGL.GL import glNormalPointerf
+from OpenGL.GL import GL_NORMAL_ARRAY
+from OpenGL.GL import GL_ONE_MINUS_SRC_ALPHA
+from OpenGL.GL import glPointSize
+from OpenGL.GL import GL_POINTS
+from OpenGL.GL import GL_POINT_SMOOTH
+from OpenGL.GL import GL_POLYGON
+from OpenGL.GL import glPolygonMode
+from OpenGL.GL import glPopAttrib
+from OpenGL.GL import glPopMatrix
+from OpenGL.GL import glPopName
+from OpenGL.GL import GL_POSITION
+from OpenGL.GL import glPushAttrib
+from OpenGL.GL import glPushMatrix
+from OpenGL.GL import glPushName
+from OpenGL.GL import GL_QUADS
+from OpenGL.GL import GL_QUAD_STRIP
+from OpenGL.GL import GL_RENDERER
+from OpenGL.GL import GL_RGBA
+from OpenGL.GL import glRotate
+from OpenGL.GL import glRotatef
+from OpenGL.GL import GL_SHININESS
+from OpenGL.GL import GL_SPECULAR
+from OpenGL.GL import GL_SRC_ALPHA
+from OpenGL.GL import GL_STATIC_DRAW
+from OpenGL.GL import glTexCoord2f
+from OpenGL.GL import glTexCoord2fv
+from OpenGL.GL import GL_TEXTURE_2D
+from OpenGL.GL import glTranslate
+from OpenGL.GL import glTranslatef
+from OpenGL.GL import GL_TRIANGLES
+from OpenGL.GL import GL_TRIANGLE_STRIP
+from OpenGL.GL import GL_TRUE
+from OpenGL.GL import GL_UNSIGNED_BYTE
+from OpenGL.GL import GL_UNSIGNED_SHORT
+from OpenGL.GL import GL_VENDOR
+from OpenGL.GL import GL_VERSION
+from OpenGL.GL import glVertex
+from OpenGL.GL import glVertex2f
+from OpenGL.GL import glVertex3f
+from OpenGL.GL import glVertex3fv
+from OpenGL.GL import GL_VERTEX_ARRAY
+from OpenGL.GL import glVertexPointer
+from OpenGL.GL import glVertexPointerf
+
+from OpenGL.GLU import gluBuild2DMipmaps
+
+from geometry.VQT import norm, vlen, V, Q, A
+
+from utilities.constants import white, blue, red
+from utilities.constants import darkgreen, lightblue
+from utilities.constants import DIAMOND_BOND_LENGTH
+from utilities.prefs_constants import material_specular_highlights_prefs_key
+from utilities.prefs_constants import material_specular_shininess_prefs_key
+from utilities.prefs_constants import material_specular_finish_prefs_key
+from utilities.prefs_constants import material_specular_brightness_prefs_key
+
+from utilities.debug_prefs import Choice
+import utilities.debug as debug # for debug.print_compact_traceback
+
+#=
+from graphics.drawing.ColorSorter import ColorSorter
+from graphics.drawing.drawers import drawPoint
+
+try:
+ from OpenGL.GLE import gleGetNumSides, gleSetNumSides
+except:
+ print "GLE module can't be imported. Now trying _GLE"
+ from OpenGL._GLE import gleGetNumSides, gleSetNumSides
+
+import foundation.env as env #bruce 051126
+
+def drawsphere(color, pos, radius, detailLevel, opacity = 1.0):
+ """
+ Schedule a sphere for rendering whenever ColorSorter thinks is appropriate.
+ """
+ ColorSorter.schedule_sphere(color,
+ pos,
+ radius,
+ detailLevel,
+ opacity = opacity)
+
+def drawwiresphere(color, pos, radius, detailLevel = 1):
+ """
+ Schedule a wireframe sphere for rendering whenever ColorSorter thinks is appropriate.
+ """
+ ColorSorter.schedule_wiresphere(color, pos, radius, detailLevel = detailLevel)
+
+def drawcylinder(color, pos1, pos2, radius, capped = 0, opacity = 1.0):
+ """Schedule a cylinder for rendering whenever ColorSorter thinks is
+ appropriate."""
+ if 1:
+ #bruce 060304 optimization: don't draw zero-length or almost-zero-length cylinders.
+ # (This happens a lot, apparently for both long-bond indicators and for open bonds.
+ # The callers hitting this should be fixed directly! That might provide a further
+ # optim by making a lot more single bonds draw as single cylinders.)
+ # The reason the threshhold depends on capped is in case someone draws a very thin
+ # cylinder as a way of drawing a disk. But they have to use some positive length
+ # (or the direction would be undefined), so we still won't permit zero-length then.
+ cyllen = vlen(pos1 - pos2)
+ if cyllen < (capped and 0.000000000001 or 0.0001):
+ # uncomment this to find the callers that ought to be optimized
+## if env.debug(): #e optim or remove this test; until then it's commented out
+## print "skipping drawcylinder since length is only %5g" % (cyllen,), \
+## " (color is (%0.2f, %0.2f, %0.2f))" % (color[0], color[1], color[2])
+ return
+ ColorSorter.schedule_cylinder(color, pos1, pos2, radius,
+ capped = capped, opacity = opacity)
+
+def drawcylinder_wireframe(color, end1, end2, radius): #bruce 060608
+ "draw a wireframe cylinder (not too pretty, definitely could look nicer, but it works)"
+ # display polys as their edges (see drawer.py's drawwirecube or Jig.draw for related code)
+ # (probably we should instead create a suitable lines display list,
+ # or even use a wire-frame-like texture so various lengths work well)
+ glPolygonMode(GL_FRONT, GL_LINE)
+ glPolygonMode(GL_BACK, GL_LINE)
+ glDisable(GL_LIGHTING)
+ glDisable(GL_CULL_FACE) # this makes motors look too busy, but without it, they look too weird (which seems worse)
+ try:
+ drawcylinder(color, end1, end2, radius) ##k not sure if this color will end up controlling the edge color; we hope it will
+ except:
+ debug.print_compact_traceback("bug, ignored: ")
+ # the following assumes that we are never called as part of a jig's drawing method,
+ # or it will mess up drawing of the rest of the jig if it's disabled
+ glEnable(GL_CULL_FACE)
+ glEnable(GL_LIGHTING)
+ glPolygonMode(GL_FRONT, GL_FILL)
+ glPolygonMode(GL_BACK, GL_FILL) # could probably use GL_FRONT_AND_BACK
+ return
+
+def drawDirectionArrow(color,
+ tailPoint,
+ arrowBasePoint,
+ tailRadius,
+ scale,
+ flipDirection = False,
+ opacity = 1.0,
+ numberOfSides = 20
+ ):
+ """
+ Draw a directional arrow staring at <tailPoint> with an endpoint decided
+ by the vector between <arrowBasePoint> and <tailPoint>
+ and the glpane scale <scale>
+ @param color : The arrow color
+ @type color: Array
+ @param tailPoint: The point on the arrow tail where the arrow begins.
+ @type tailPoint: V
+ @param arrowBasePoint: A point on the arrow where the arrow head begins(??
+ @type arrowBasePoint: V
+ @param tailRadius: The radius of the arrow tail (cylinder radius
+ representing the arrow tail)
+ @type tailRaius: float
+ @param opacity: The opacity decides the opacity (or transparent display)
+ of the rendered arrow. By default it is rendered as a solid
+ arrow. It varies between 0.0 to 1.0 ... 1.0 represents the
+ solid arrow renderring style
+ @type opacity: float
+ @param numberOfSides: The total number of sides for the arrow head
+ (a glePolycone) The default value if 20 (20 sided
+ polycone)
+ @type numberOfSides: int
+ """
+
+ vec = arrowBasePoint - tailPoint
+ vec = scale*0.07*vec
+ arrowBase = tailRadius*3.0
+ arrowHeight = arrowBase*1.5
+ axis = norm(vec)
+
+ #as of 2008-03-03 scaledBasePoint is not used so commenting out.
+ #(will be removed after more testing)
+ ##scaledBasePoint = tailPoint + vlen(vec)*axis
+ drawcylinder(color, tailPoint, arrowBasePoint, tailRadius, capped = True,
+ opacity = opacity)
+
+ ##pos = scaledBasePoint
+ pos = arrowBasePoint
+ arrowRadius = arrowBase
+ gleSetNumSides(numberOfSides)
+ drawpolycone(color, [[pos[0] - 1 * axis[0],
+ pos[1] - 1 * axis[1],
+ pos[2] - 1 * axis[2]],
+ [pos[0],# - axis[0],
+ pos[1], #- axis[1],
+ pos[2]], #- axis[2]],
+ [pos[0] + arrowHeight * axis[0],
+ pos[1] + arrowHeight * axis[1],
+ pos[2] + arrowHeight * axis[2]],
+ [pos[0] + (arrowHeight + 1) * axis[0],
+ pos[1] + (arrowHeight + 1) * axis[1],
+ pos[2] + (arrowHeight + 1) * axis[2]]], # Point array (the two end
+ # points not drawn)
+ [arrowRadius, arrowRadius, 0, 0], # Radius array
+ opacity = opacity
+ )
+ #reset the gle number of sides to the gle default of '20'
+ gleSetNumSides(20)
+
+def drawpolycone(color, pos_array, rad_array, opacity = 1.0):
+ """Schedule a polycone for rendering whenever ColorSorter thinks is
+ appropriate."""
+ ColorSorter.schedule_polycone(color, pos_array, rad_array, opacity = opacity)
+
+def drawpolycone_multicolor(color, pos_array, color_array, rad_array, opacity = 1.0):
+ """Schedule a polycone for rendering whenever ColorSorter thinks is
+ appropriate. Accepts color_array for per-vertex coloring. """
+ ColorSorter.schedule_polycone_multicolor(color, pos_array, color_array, rad_array, opacity = opacity)
+
+def drawsurface(color, pos, radius, tm, nm):
+ """
+ Schedule a surface for rendering whenever ColorSorter thinks is
+ appropriate.
+ """
+ ColorSorter.schedule_surface(color, pos, radius, tm, nm)
+
+def drawsurface_wireframe(color, pos, radius, tm, nm):
+ glPolygonMode(GL_FRONT, GL_LINE)
+ glPolygonMode(GL_BACK, GL_LINE)
+ glDisable(GL_LIGHTING)
+ glDisable(GL_CULL_FACE)
+ try:
+ drawsurface(color, pos, radius, tm, nm)
+ except:
+ debug.print_compact_traceback("bug, ignored: ")
+ glEnable(GL_CULL_FACE)
+ glEnable(GL_LIGHTING)
+ glPolygonMode(GL_FRONT, GL_FILL)
+ glPolygonMode(GL_BACK, GL_FILL)
+ return
+
+def drawline(color,
+ endpt1,
+ endpt2,
+ dashEnabled = False,
+ stipleFactor = 1,
+ width = 1,
+ isSmooth = False):
+ """
+ Draw a line from endpt1 to endpt2 in the given color. Actually, schedule
+ it for rendering whenever ColorSorter thinks is appropriate.
+
+ @param endpt1: First endpoint.
+ @type endpt1: point
+
+ @param endpt2: Second endpoint.
+ @type endpt2: point
+
+ @param dashEnabled: If dashEnabled is True, it will be dashed.
+ @type dashEnabled: boolean
+
+ @param stipleFactor: The stiple factor.
+ @param stipleFactor: int
+
+ @param width: The line width in pixels. The default is 1.
+ @type width: int or float
+
+ @param isSmooth: Enables GL_LINE_SMOOTH. The default is False.
+ @type isSmooth: boolean
+
+ @note: Whether the line is antialiased is determined by GL state variables
+ which are not set in this function.
+
+ @warning: Some callers pass dashEnabled as a positional argument rather
+ than a named argument.
+ """
+ ColorSorter.schedule_line(color, endpt1, endpt2, dashEnabled,
+ stipleFactor, width, isSmooth)
+
+def drawTag(color, basePoint, endPoint, pointSize = 20.0):
+ """
+ Draw a tag (or a 'flag') as a line ending with a circle (like a balloon
+ with a string). Note: The word 'Flag' is intentionally not used in the
+ method nameto avoid potential confusion with a boolean flag.
+
+ @param color: color of the tag
+ @type color: A
+ @param basePoint: The base point of the tag
+ @type basePoint: V
+ @param endPoint: The end point of the tag
+ @type endPoint: V
+ @param pointSize: The pointSize of the point to be drawin at the <endPoint>
+ @type pointSize: float
+
+ @see: GraphicsMode._drawTags where it is called (an example)
+
+ """
+ drawline(color, basePoint, endPoint)
+ drawPoint(color, endPoint, pointSize = 20.0)
diff --git a/cad/src/graphics/drawing/CS_workers.py b/cad/src/graphics/drawing/CS_workers.py
new file mode 100755
index 000000000..feabb607d
--- /dev/null
+++ b/cad/src/graphics/drawing/CS_workers.py
@@ -0,0 +1,431 @@
+# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
+"""
+CS_workers.py - Drawing functions for primitives drawn by the ColorSorter.
+
+@version: $Id$
+@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
+
+History:
+
+Originated by Josh as drawer.py .
+
+Various developers extended it since then.
+
+Brad G. added ColorSorter features.
+
+At some point Bruce partly cleaned up the use of display lists.
+
+071030 bruce split some functions and globals into draw_grid_lines.py
+and removed some obsolete functions.
+
+080210 russ Split the single display-list into two second-level lists (with and
+without color) and a set of per-color sublists so selection and hover-highlight
+can over-ride Chunk base colors. ColorSortedDisplayList is now a class in the
+parent's displist attr to keep track of all that stuff.
+
+080311 piotr Added a "drawpolycone_multicolor" function for drawing polycone
+tubes with per-vertex colors (necessary for DNA display style)
+
+080313 russ Added triangle-strip icosa-sphere constructor, "getSphereTriStrips".
+
+080420 piotr Solved highlighting and selection problems for multi-colored
+objects (e.g. rainbow colored DNA structures).
+
+080519 russ pulled the globals into a drawing_globals module and broke drawer.py
+into 10 smaller chunks: glprefs.py setup_draw.py shape_vertices.py
+ColorSorter.py CS_workers.py CS_ShapeList.py CS_draw_primitives.py drawers.py
+gl_lighting.py gl_buffers.py
+"""
+
+import os
+import sys
+
+# the imports from math vs. Numeric are as discovered in existing code
+# as of 2007/06/25. It's not clear why acos is coming from math...
+from math import floor, ceil, acos, atan2
+import Numeric
+from Numeric import sin, cos, sqrt, pi
+degreesPerRadian = 180.0 / pi
+
+# russ 080519 No doubt many of the following imports are unused.
+# When the dust settles, the unnecessary ones will be removed.
+from OpenGL.GL import GL_AMBIENT
+from OpenGL.GL import GL_AMBIENT_AND_DIFFUSE
+from OpenGL.GL import glAreTexturesResident
+from OpenGL.GL import GL_ARRAY_BUFFER_ARB
+from OpenGL.GL import GL_BACK
+from OpenGL.GL import glBegin
+from OpenGL.GL import glBindTexture
+from OpenGL.GL import GL_BLEND
+from OpenGL.GL import glBlendFunc
+from OpenGL.GL import glCallList
+from OpenGL.GL import glColor3f
+from OpenGL.GL import glColor3fv
+from OpenGL.GL import glColor4fv
+from OpenGL.GL import GL_COLOR_MATERIAL
+from OpenGL.GL import GL_COMPILE
+from OpenGL.GL import GL_COMPILE_AND_EXECUTE
+from OpenGL.GL import GL_CONSTANT_ATTENUATION
+from OpenGL.GL import GL_CULL_FACE
+from OpenGL.GL import GL_CURRENT_BIT
+from OpenGL.GL import glDeleteLists
+from OpenGL.GL import glDeleteTextures
+from OpenGL.GL import glDepthMask
+from OpenGL.GL import GL_DEPTH_TEST
+from OpenGL.GL import GL_DIFFUSE
+from OpenGL.GL import glDisable
+from OpenGL.GL import glDisableClientState
+from OpenGL.GL import glDrawArrays
+from OpenGL.GL import glDrawElements
+from OpenGL.GL import glDrawElementsub
+from OpenGL.GL import glDrawElementsui
+from OpenGL.GL import glDrawElementsus
+from OpenGL.GL import GL_ELEMENT_ARRAY_BUFFER_ARB
+from OpenGL.GL import glEnable
+from OpenGL.GL import glEnableClientState
+from OpenGL.GL import glEnd
+from OpenGL.GL import glEndList
+from OpenGL.GL import GL_EXTENSIONS
+from OpenGL.GL import GL_FALSE
+from OpenGL.GL import GL_FILL
+from OpenGL.GL import glFinish
+from OpenGL.GL import GL_FLOAT
+from OpenGL.GL import GL_FOG
+from OpenGL.GL import GL_FOG_COLOR
+from OpenGL.GL import GL_FOG_END
+from OpenGL.GL import GL_FOG_MODE
+from OpenGL.GL import GL_FOG_START
+from OpenGL.GL import GL_FRONT
+from OpenGL.GL import GL_FRONT_AND_BACK
+from OpenGL.GL import glGenLists
+from OpenGL.GL import glGenTextures
+from OpenGL.GL import glGetString
+from OpenGL.GL import GL_LIGHT0
+from OpenGL.GL import GL_LIGHT1
+from OpenGL.GL import GL_LIGHT2
+from OpenGL.GL import glLightf
+from OpenGL.GL import glLightfv
+from OpenGL.GL import GL_LIGHTING
+from OpenGL.GL import GL_LINE
+from OpenGL.GL import GL_LINEAR
+from OpenGL.GL import GL_LINE_LOOP
+from OpenGL.GL import GL_LINES
+from OpenGL.GL import GL_LINE_SMOOTH
+from OpenGL.GL import glLineStipple
+from OpenGL.GL import GL_LINE_STIPPLE
+from OpenGL.GL import GL_LINE_STRIP
+from OpenGL.GL import glLineWidth
+from OpenGL.GL import glLoadIdentity
+from OpenGL.GL import glMaterialf
+from OpenGL.GL import glMaterialfv
+from OpenGL.GL import glMatrixMode
+from OpenGL.GL import GL_MODELVIEW
+from OpenGL.GL import glNewList
+from OpenGL.GL import glNormal3fv
+from OpenGL.GL import glNormalPointer
+from OpenGL.GL import glNormalPointerf
+from OpenGL.GL import GL_NORMAL_ARRAY
+from OpenGL.GL import GL_ONE_MINUS_SRC_ALPHA
+from OpenGL.GL import glPointSize
+from OpenGL.GL import GL_POINTS
+from OpenGL.GL import GL_POINT_SMOOTH
+from OpenGL.GL import GL_POLYGON
+from OpenGL.GL import glPolygonMode
+from OpenGL.GL import glPopAttrib
+from OpenGL.GL import glPopMatrix
+from OpenGL.GL import glPopName
+from OpenGL.GL import GL_POSITION
+from OpenGL.GL import glPushAttrib
+from OpenGL.GL import glPushMatrix
+from OpenGL.GL import glPushName
+from OpenGL.GL import GL_QUADS
+from OpenGL.GL import GL_QUAD_STRIP
+from OpenGL.GL import GL_RENDERER
+from OpenGL.GL import GL_RGBA
+from OpenGL.GL import glRotate
+from OpenGL.GL import glRotatef
+from OpenGL.GL import GL_SHININESS
+from OpenGL.GL import GL_SPECULAR
+from OpenGL.GL import GL_SRC_ALPHA
+from OpenGL.GL import GL_STATIC_DRAW
+from OpenGL.GL import glTexCoord2f
+from OpenGL.GL import glTexCoord2fv
+from OpenGL.GL import GL_TEXTURE_2D
+from OpenGL.GL import glTranslate
+from OpenGL.GL import glTranslatef
+from OpenGL.GL import GL_TRIANGLES
+from OpenGL.GL import GL_TRIANGLE_STRIP
+from OpenGL.GL import GL_TRUE
+from OpenGL.GL import GL_UNSIGNED_BYTE
+from OpenGL.GL import GL_UNSIGNED_SHORT
+from OpenGL.GL import GL_VENDOR
+from OpenGL.GL import GL_VERSION
+from OpenGL.GL import glVertex
+from OpenGL.GL import glVertex2f
+from OpenGL.GL import glVertex3f
+from OpenGL.GL import glVertex3fv
+from OpenGL.GL import GL_VERTEX_ARRAY
+from OpenGL.GL import glVertexPointer
+from OpenGL.GL import glVertexPointerf
+
+from OpenGL.GLU import gluBuild2DMipmaps
+
+from geometry.VQT import norm, vlen, V, Q, A
+
+from utilities.constants import white, blue, red
+from utilities.constants import darkgreen, lightblue
+from utilities.constants import DIAMOND_BOND_LENGTH
+from utilities.prefs_constants import material_specular_highlights_prefs_key
+from utilities.prefs_constants import material_specular_shininess_prefs_key
+from utilities.prefs_constants import material_specular_finish_prefs_key
+from utilities.prefs_constants import material_specular_brightness_prefs_key
+
+from utilities.debug_prefs import Choice
+import utilities.debug as debug # for debug.print_compact_traceback
+
+#=
+
+import graphics.drawing.drawing_globals as drawing_globals
+from graphics.drawing.drawers import renderSurface
+
+try:
+ from OpenGL.GLE import glePolyCone
+except:
+ print "GLE module can't be imported. Now trying _GLE"
+ from OpenGL._GLE import glePolyCone
+
+try:
+ from OpenGL.GL import glScale
+except:
+ # The installed version of OpenGL requires argument-typed glScale calls.
+ from OpenGL.GL import glScalef as glScale
+
+from OpenGL.GL import glScalef
+ # Note: this is NOT redundant with the above import of glScale --
+ # without it, displaying an ESP Image gives a NameError traceback
+ # and doesn't work. [Fixed by bruce 070703; bug caught by Eric M using
+ # PyChecker; bug introduced sometime after A9.1 went out.]
+
+### Substitute this for drawsphere_worker to test drawing a lot of spheres.
+def drawsphere_worker_loop(params):
+ (pos, radius, detailLevel) = params
+ for x in range(100): ## 500
+ for y in range(100):
+ newpos = pos + (x+x/10+x/100) * V(1, 0, 0) + (y+y/10+y/100) * V(0, 1, 0)
+ drawsphere_worker((newpos, radius, detailLevel))
+ continue
+ continue
+ return
+
+def drawsphere_worker(params):
+ """Draw a sphere. Receive parameters through a sequence so that this
+ function and its parameters can be passed to another function for
+ deferment. Right now this is only ColorSorter.schedule (see below)"""
+
+ (pos, radius, detailLevel) = params
+
+ vboLevel = drawing_globals.use_drawing_variant
+
+ glPushMatrix()
+ glTranslatef(pos[0], pos[1], pos[2])
+ glScale(radius,radius,radius)
+
+ if vboLevel is 0:
+ glCallList(drawing_globals.sphereList[detailLevel])
+ else: # Array variants.
+ glEnableClientState(GL_VERTEX_ARRAY)
+ glEnableClientState(GL_NORMAL_ARRAY)
+
+ size = len(drawing_globals.sphereArrays[detailLevel])
+ GLIndexType = drawing_globals.sphereGLIndexTypes[detailLevel]
+
+ if vboLevel is 1: # DrawArrays from CPU RAM.
+ verts = drawing_globals.sphereCArrays[detailLevel]
+ glVertexPointer(3, GL_FLOAT, 0, verts)
+ glNormalPointer(GL_FLOAT, 0, verts)
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, size)
+
+ elif vboLevel is 2: # DrawElements from CPU RAM.
+ verts = drawing_globals.sphereCElements[detailLevel][1]
+ glVertexPointer(3, GL_FLOAT, 0, verts)
+ glNormalPointer(GL_FLOAT, 0, verts)
+ # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug.
+ index = drawing_globals.sphereElements[detailLevel][0]
+ glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index)
+
+ elif vboLevel is 3: # DrawArrays from graphics RAM VBO.
+ vbo = drawing_globals.sphereArrayVBOs[detailLevel]
+ vbo.bind()
+ glVertexPointer(3, GL_FLOAT, 0, None)
+ glNormalPointer(GL_FLOAT, 0, None)
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, vbo.size)
+ vbo.unbind()
+
+ elif vboLevel is 4: # DrawElements from index in CPU RAM, verts in VBO.
+ vbo = drawing_globals.sphereElementVBOs[detailLevel][1]
+ vbo.bind() # Vertex and normal data comes from the vbo.
+ glVertexPointer(3, GL_FLOAT, 0, None)
+ glNormalPointer(GL_FLOAT, 0, None)
+ # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug.
+ index = drawing_globals.sphereElements[detailLevel][0]
+ glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index)
+ vbo.unbind()
+
+ elif vboLevel is 5: # VBO/IBO buffered DrawElements from graphics RAM.
+ (ibo, vbo) = drawing_globals.sphereElementVBOs[detailLevel]
+ vbo.bind() # Vertex and normal data comes from the vbo.
+ glVertexPointer(3, GL_FLOAT, 0, None)
+ glNormalPointer(GL_FLOAT, 0, None)
+ ibo.bind() # Index data comes from the ibo.
+ glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, None)
+ vbo.unbind()
+ ibo.unbind()
+ pass
+
+ glDisableClientState(GL_VERTEX_ARRAY)
+ glDisableClientState(GL_NORMAL_ARRAY)
+ pass
+
+ glPopMatrix()
+ return
+
+def drawwiresphere_worker(params):
+ """
+ Draw a wireframe sphere. Receive parameters through a sequence so that this
+ function and its parameters can be passed to another function for
+ deferment. Right now this is only ColorSorter.schedule (see below)
+ """
+
+ (color, pos, radius, detailLevel) = params
+ ## assert detailLevel == 1 # true, but leave out for speed
+ from utilities.debug_prefs import debug_pref, Choice_boolean_True
+ newway = debug_pref("new wirespheres?", Choice_boolean_True) #bruce 060415 experiment, re iMac G4 wiresphere bug; fixes it!
+ oldway = not newway
+ # These objects want a constant line color even if they are selected or highlighted.
+ glColor3fv(color)
+ glDisable(GL_LIGHTING)
+ if oldway:
+ glPolygonMode(GL_FRONT, GL_LINE)
+ glPushMatrix()
+ glTranslatef(pos[0], pos[1], pos[2])
+ glScale(radius,radius,radius)
+ if oldway:
+ glCallList(drawing_globals.sphereList[detailLevel])
+ else:
+ glCallList(drawing_globals.wiresphere1list)
+ glEnable(GL_LIGHTING)
+ glPopMatrix()
+ if oldway:
+ glPolygonMode(GL_FRONT, GL_FILL)
+ return
+
+def drawcylinder_worker(params):
+ """
+ Draw a cylinder. Receive parameters through a sequence so that this
+ function and its parameters can be passed to another function for
+ deferment. Right now this is only ColorSorter.schedule (see below)
+
+ WARNING: our circular cross-section is approximated by a 13-gon
+ whose alignment around the axis is chosen arbitrary, in a way
+ which depends on the direction of the axis; negating the axis usually
+ causes a different alignment of that 13-gon. This effect can cause
+ visual bugs when drawing one cylinder over an identical or slightly
+ smaller one (e.g. when highlighting a bond), unless the axes are kept
+ parallel as opposed to antiparallel.
+ """
+
+ (pos1, pos2, radius, capped) = params
+
+ glPushMatrix()
+ vec = pos2-pos1
+ axis = norm(vec)
+ glTranslatef(pos1[0], pos1[1], pos1[2])
+
+ ##Huaicai 1/17/05: To avoid rotate around (0, 0, 0), which causes
+ ## display problem on some platforms
+ angle = -acos(axis[2])*180.0/pi
+ if (axis[2]*axis[2] >= 1.0):
+ glRotate(angle, 0.0, 1.0, 0.0)
+ else:
+ glRotate(angle, axis[1], -axis[0], 0.0)
+
+ glScale(radius,radius,Numeric.dot(vec,vec)**.5)
+ glCallList(drawing_globals.CylList)
+ if capped: glCallList(drawing_globals.CapList)
+
+ glPopMatrix()
+
+ return
+
+def drawpolycone_worker(params):
+ """
+ Draw a polycone. Receive parameters through a sequence so that this
+ function and its parameters can be passed to another function for
+ deferment. Right now this is only ColorSorter.schedule (see below)
+ """
+ (pos_array, rad_array) = params
+ glePolyCone(pos_array, None, rad_array)
+ return
+
+def drawpolycone_multicolor_worker(params):
+ """
+ Draw a polycone. Receive parameters through a sequence so that this
+ function and its parameters can be passed to another function for
+ deferment. Right now this is only ColorSorter.schedule (see below)
+ piotr 080311: this variant accepts a color array as an additional parameter
+ """
+ (pos_array, color_array, rad_array) = params
+ glEnable(GL_COLOR_MATERIAL) # have to enable GL_COLOR_MATERIAL for
+ # the GLE function
+ glPushAttrib(GL_CURRENT_BIT) # store current attributes in case glePolyCone
+ # modifies the (e.g. current color)
+ # piotr 080411
+ glePolyCone(pos_array, color_array, rad_array)
+ glPopAttrib() # This fixes the 'disappearing cylinder' bug
+ # glPopAttrib doesn't take any arguments
+ # piotr 080415
+ glDisable(GL_COLOR_MATERIAL)
+ return
+
+def drawsurface_worker(params):
+ """Draw a surface. Receive parameters through a sequence so that this
+ function and its parameters can be passed to another function for
+ deferment. Right now this is only ColorSorter.schedule (see below)"""
+
+ (pos, radius, tm, nm) = params
+ glPushMatrix()
+ glTranslatef(pos[0], pos[1], pos[2])
+ glScale(radius,radius,radius)
+ renderSurface(tm, nm)
+ glPopMatrix()
+ return
+
+def drawline_worker(params):
+ """
+ Draw a line. Receive parameters through a sequence so that this
+ function and its parameters can be passed to another function for
+ deferment. Right now this is only ColorSorter.schedule (see below)
+ """
+ (endpt1, endpt2, dashEnabled, stipleFactor, width, isSmooth) = params
+
+ ###glDisable(GL_LIGHTING)
+ ###glColor3fv(color)
+ if dashEnabled:
+ glLineStipple(stipleFactor, 0xAAAA)
+ glEnable(GL_LINE_STIPPLE)
+ if width != 1:
+ glLineWidth(width)
+ if isSmooth:
+ glEnable(GL_LINE_SMOOTH)
+ glBegin(GL_LINES)
+ glVertex(endpt1[0], endpt1[1], endpt1[2])
+ glVertex(endpt2[0], endpt2[1], endpt2[2])
+ glEnd()
+ if isSmooth:
+ glDisable(GL_LINE_SMOOTH)
+ if width != 1:
+ glLineWidth(1.0) # restore default state
+ if dashEnabled:
+ glDisable(GL_LINE_STIPPLE)
+ ###glEnable(GL_LIGHTING)
+ return
diff --git a/cad/src/graphics/drawing/ColorSorter.py b/cad/src/graphics/drawing/ColorSorter.py
new file mode 100755
index 000000000..aafd00db8
--- /dev/null
+++ b/cad/src/graphics/drawing/ColorSorter.py
@@ -0,0 +1,879 @@
+# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
+"""
+ColorSorter.py - A class to group primitive drawing by colors.
+
+This was originally done as a GL optimization to minimize calls on
+apply_material.
+
+Later, it was extended to handle multiple display lists per Chunk object as an
+optimization to avoid rebuilding a single display list when the appearance of
+the object changes for hover-highlighting and selection.
+
+@version: $Id$
+@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
+
+History:
+
+Originated by Josh as drawer.py .
+
+Various developers extended it since then.
+
+Brad G. added ColorSorter features.
+
+At some point Bruce partly cleaned up the use of display lists.
+
+071030 bruce split some functions and globals into draw_grid_lines.py
+and removed some obsolete functions.
+
+080210 russ Split the single display-list into two second-level lists (with and
+without color) and a set of per-color sublists so selection and hover-highlight
+can over-ride Chunk base colors. ColorSortedDisplayList is now a class in the
+parent's displist attr to keep track of all that stuff.
+
+080311 piotr Added a "drawpolycone_multicolor" function for drawing polycone
+tubes with per-vertex colors (necessary for DNA display style)
+
+080313 russ Added triangle-strip icosa-sphere constructor, "getSphereTriStrips".
+
+080420 piotr Solved highlighting and selection problems for multi-colored
+objects (e.g. rainbow colored DNA structures).
+
+080519 russ pulled the globals into a drawing_globals module and broke drawer.py
+into 10 smaller chunks: glprefs.py setup_draw.py shape_vertices.py
+ColorSorter.py CS_workers.py CS_ShapeList.py CS_draw_primitives.py drawers.py
+gl_lighting.py gl_buffers.py
+"""
+
+import os
+import sys
+
+# the imports from math vs. Numeric are as discovered in existing code
+# as of 2007/06/25. It's not clear why acos is coming from math...
+from math import floor, ceil, acos, atan2
+import Numeric
+from Numeric import sin, cos, sqrt, pi
+degreesPerRadian = 180.0 / pi
+
+# russ 080519 No doubt many of the following imports are unused.
+# When the dust settles, the unnecessary ones will be removed.
+from OpenGL.GL import GL_AMBIENT
+from OpenGL.GL import GL_AMBIENT_AND_DIFFUSE
+from OpenGL.GL import glAreTexturesResident
+from OpenGL.GL import GL_ARRAY_BUFFER_ARB
+from OpenGL.GL import GL_BACK
+from OpenGL.GL import glBegin
+from OpenGL.GL import glBindTexture
+from OpenGL.GL import GL_BLEND
+from OpenGL.GL import glBlendFunc
+from OpenGL.GL import glCallList
+from OpenGL.GL import glColor3f
+from OpenGL.GL import glColor3fv
+from OpenGL.GL import glColor4fv
+from OpenGL.GL import GL_COLOR_MATERIAL
+from OpenGL.GL import GL_COMPILE
+from OpenGL.GL import GL_COMPILE_AND_EXECUTE
+from OpenGL.GL import GL_CONSTANT_ATTENUATION
+from OpenGL.GL import GL_CULL_FACE
+from OpenGL.GL import GL_CURRENT_BIT
+from OpenGL.GL import glDeleteLists
+from OpenGL.GL import glDeleteTextures
+from OpenGL.GL import glDepthMask
+from OpenGL.GL import GL_DEPTH_TEST
+from OpenGL.GL import GL_DIFFUSE
+from OpenGL.GL import glDisable
+from OpenGL.GL import glDisableClientState
+from OpenGL.GL import glDrawArrays
+from OpenGL.GL import glDrawElements
+from OpenGL.GL import glDrawElementsub
+from OpenGL.GL import glDrawElementsui
+from OpenGL.GL import glDrawElementsus
+from OpenGL.GL import GL_ELEMENT_ARRAY_BUFFER_ARB
+from OpenGL.GL import glEnable
+from OpenGL.GL import glEnableClientState
+from OpenGL.GL import glEnd
+from OpenGL.GL import glEndList
+from OpenGL.GL import GL_EXTENSIONS
+from OpenGL.GL import GL_FALSE
+from OpenGL.GL import GL_FILL
+from OpenGL.GL import glFinish
+from OpenGL.GL import GL_FLOAT
+from OpenGL.GL import GL_FOG
+from OpenGL.GL import GL_FOG_COLOR
+from OpenGL.GL import GL_FOG_END
+from OpenGL.GL import GL_FOG_MODE
+from OpenGL.GL import GL_FOG_START
+from OpenGL.GL import GL_FRONT
+from OpenGL.GL import GL_FRONT_AND_BACK
+from OpenGL.GL import glGenLists
+from OpenGL.GL import glGenTextures
+from OpenGL.GL import glGetString
+from OpenGL.GL import GL_LIGHT0
+from OpenGL.GL import GL_LIGHT1
+from OpenGL.GL import GL_LIGHT2
+from OpenGL.GL import glLightf
+from OpenGL.GL import glLightfv
+from OpenGL.GL import GL_LIGHTING
+from OpenGL.GL import GL_LINE
+from OpenGL.GL import GL_LINEAR
+from OpenGL.GL import GL_LINE_LOOP
+from OpenGL.GL import GL_LINES
+from OpenGL.GL import GL_LINE_SMOOTH
+from OpenGL.GL import glLineStipple
+from OpenGL.GL import GL_LINE_STIPPLE
+from OpenGL.GL import GL_LINE_STRIP
+from OpenGL.GL import glLineWidth
+from OpenGL.GL import glLoadIdentity
+from OpenGL.GL import glMaterialf
+from OpenGL.GL import glMaterialfv
+from OpenGL.GL import glMatrixMode
+from OpenGL.GL import GL_MODELVIEW
+from OpenGL.GL import glNewList
+from OpenGL.GL import glNormal3fv
+from OpenGL.GL import glNormalPointer
+from OpenGL.GL import glNormalPointerf
+from OpenGL.GL import GL_NORMAL_ARRAY
+from OpenGL.GL import GL_ONE_MINUS_SRC_ALPHA
+from OpenGL.GL import glPointSize
+from OpenGL.GL import GL_POINTS
+from OpenGL.GL import GL_POINT_SMOOTH
+from OpenGL.GL import GL_POLYGON
+from OpenGL.GL import glPolygonMode
+from OpenGL.GL import glPopAttrib
+from OpenGL.GL import glPopMatrix
+from OpenGL.GL import glPopName
+from OpenGL.GL import GL_POSITION
+from OpenGL.GL import glPushAttrib
+from OpenGL.GL import glPushMatrix
+from OpenGL.GL import glPushName
+from OpenGL.GL import GL_QUADS
+from OpenGL.GL import GL_QUAD_STRIP
+from OpenGL.GL import GL_RENDERER
+from OpenGL.GL import GL_RGBA
+from OpenGL.GL import glRotate
+from OpenGL.GL import glRotatef
+from OpenGL.GL import GL_SHININESS
+from OpenGL.GL import GL_SPECULAR
+from OpenGL.GL import GL_SRC_ALPHA
+from OpenGL.GL import GL_STATIC_DRAW
+from OpenGL.GL import glTexCoord2f
+from OpenGL.GL import glTexCoord2fv
+from OpenGL.GL import GL_TEXTURE_2D
+from OpenGL.GL import glTranslate
+from OpenGL.GL import glTranslatef
+from OpenGL.GL import GL_TRIANGLES
+from OpenGL.GL import GL_TRIANGLE_STRIP
+from OpenGL.GL import GL_TRUE
+from OpenGL.GL import GL_UNSIGNED_BYTE
+from OpenGL.GL import GL_UNSIGNED_SHORT
+from OpenGL.GL import GL_VENDOR
+from OpenGL.GL import GL_VERSION
+from OpenGL.GL import glVertex
+from OpenGL.GL import glVertex2f
+from OpenGL.GL import glVertex3f
+from OpenGL.GL import glVertex3fv
+from OpenGL.GL import GL_VERTEX_ARRAY
+from OpenGL.GL import glVertexPointer
+from OpenGL.GL import glVertexPointerf
+
+from OpenGL.GLU import gluBuild2DMipmaps
+
+from geometry.VQT import norm, vlen, V, Q, A
+
+from utilities.constants import white, blue, red
+from utilities.constants import darkgreen, lightblue
+from utilities.constants import DIAMOND_BOND_LENGTH
+from utilities.prefs_constants import material_specular_highlights_prefs_key
+from utilities.prefs_constants import material_specular_shininess_prefs_key
+from utilities.prefs_constants import material_specular_finish_prefs_key
+from utilities.prefs_constants import material_specular_brightness_prefs_key
+
+from utilities.debug_prefs import Choice
+import utilities.debug as debug # for debug.print_compact_traceback
+
+#=
+
+import graphics.drawing.drawing_globals as drawing_globals
+if drawing_globals.quux_module_import_succeeded:
+ import quux
+
+from graphics.drawing.CS_ShapeList import ShapeList_inplace
+from graphics.drawing.CS_workers import drawcylinder_worker
+from graphics.drawing.CS_workers import drawline_worker
+from graphics.drawing.CS_workers import drawpolycone_multicolor_worker
+from graphics.drawing.CS_workers import drawpolycone_worker
+from graphics.drawing.CS_workers import drawsphere_worker
+from graphics.drawing.CS_workers import drawsurface_worker
+from graphics.drawing.CS_workers import drawwiresphere_worker
+from graphics.drawing.gl_lighting import apply_material
+
+class ColorSortedDisplayList: #Russ 080225: Added.
+ """
+ The ColorSorter's parent uses one of these to store color-sorted display list
+ state. It's passed in to ColorSorter.start() .
+ """
+ def __init__(self):
+ self.clear()
+ self.selected = False # Whether to draw in the selection over-ride color.
+ return
+
+ #russ 080320 Experiment with VBO drawing from cached ColorSorter lists.
+ cache_ColorSorter = False ## True
+
+ def clear(self):
+ """
+ Empty state.
+ """
+ self.dl = 0 # Current display list (color or selected.)
+ self.color_dl = 0 # DL to set colors, call each lower level list.
+ self.selected_dl = 0 # DL with a single (selected) over-ride color.
+ self.nocolor_dl = 0 # DL of lower-level calls for color over-rides.
+ self.per_color_dls = [] # Lower level, per-color primitive sublists.
+ return
+
+ def not_clear(self):
+ """
+ Check for empty state.
+ """
+ return self.dl or self.color_dl or self.nocolor_dl or self.selected_dl or \
+ self.per_color_dls and len(self.per_color_dls)
+
+ def activate(self):
+ """
+ Make a top-level display list id ready, but don't fill it in.
+ """
+ # Display list id for the current appearance.
+ if not self.selected:
+ self.color_dl = glGenLists(1)
+ else:
+ self.selected_dl = glGenLists(1)
+ pass
+ self.selectDl()
+ assert type(self.dl) in (type(1), type(1L)) #bruce 070521 added these two asserts
+ assert self.dl != 0 # This failed on Linux, keep checking. (bug 2042)
+ return
+
+ def draw_dl(self): #russ 080320 Added.
+ """
+ Draw the displist (cached display procedure.)
+ """
+ #russ 080320: Experiment with VBO drawing from cached ColorSorter lists.
+ if (ColorSortedDisplayList.cache_ColorSorter and
+ drawing_globals.allow_color_sorting and
+ drawing_globals.use_color_sorted_vbos):
+ ColorSorter.draw_sorted(self.sorted_by_color)
+ else:
+ # Call a normal OpenGL display list.
+ glCallList(self.dl)
+ return
+
+ def selectPick(self, boolVal):
+ """
+ Remember whether we're selected or not.
+ """
+ self.selected = boolVal
+ self.selectDl()
+ return
+
+ def selectDl(self):
+ """
+ Change to either the normal-color display list or the selected one.
+ """
+ self.dl = self.selected and self.selected_dl or self.color_dl
+ return
+
+ def reset(self):
+ """
+ Return to initialized state.
+ """
+ if self.not_clear():
+ # deallocate leaves it clear.
+ self.deallocate_displists()
+ pass
+ return
+
+ def deallocate_displists(self):
+ """
+ Free any allocated display lists.
+ """
+ # With CSDL active, self.dl duplicates either selected_dl or color_dl.
+ if (self.dl is not self.color_dl and
+ self.dl is not self.selected_dl):
+ glDeleteLists(self.dl, 1)
+ for dl in [self.color_dl, self.nocolor_dl, self.selected_dl]:
+ if dl != 0:
+ glDeleteLists(dl, 1)
+ pass
+ continue
+ # piotr 080420: The second level dl's are 2-element lists of DL ids
+ # rather than just a list of ids. The secod DL is used in case
+ # of multi-color objects and is required for highlighting
+ # and selection (not in rc1)
+ for clr, dls in self.per_color_dls: # Second-level dl's.
+ for dl in dls: # iterate over DL pairs.
+ if dl != 0:
+ glDeleteLists(dl, 1)
+ pass
+ continue
+ self.clear()
+ return
+
+ pass # End of ColorSortedDisplayList.
+
+class ColorSorter:
+
+ """
+ State Sorter specializing in color (Really any object that can be
+ passed to apply_material, which on 20051204 is only color 4-tuples)
+
+ Invoke start() to begin sorting.
+ Call finish() to complete sorting and draw all sorted objects.
+
+ Call schedule() with any function and parameters to be sorted by color.
+ If not sorting, schedule() will invoke the function immediately. If
+ sorting, then the function will not be called until "finish()".
+
+ In any function which will take part in sorting which previously did
+ not, create a worker function from the old function except the call to
+ apply_material. Then create a wrapper which calls
+ ColorSorter.schedule with the worker function and its params.
+
+ Also an app can call schedule_sphere and schedule_cylinder to
+ schedule a sphere or a cylinder. Right now this is the only way
+ to directly access the native C++ rendering engine.
+ """
+ __author__ = "grantham@plunk.org"
+
+ # For now, these are class globals. As long as OpenGL drawing is
+ # serialized and Sorting isn't nested, this is okay. When/if
+ # OpenGL drawing becomes multi-threaded, sorters will have to
+ # become instances. This is probably okay because objects and
+ # materials will probably become objects of their own about that
+ # time so the whole system will get a redesign and
+ # reimplementation.
+
+ sorting = False # Guard against nested sorting
+ _sorted = 0 # Number of calls to _add_to_sorter since last
+ # _printstats
+ _immediate = 0 # Number of calls to _invoke_immediately since last
+ # _printstats
+ _gl_name_stack = [0] # internal record of GL name stack; 0 is a sentinel
+
+ def pushName(glname):
+ """
+ Record the current pushed GL name, which must not be 0.
+ """
+ assert glname, "glname of 0 is illegal (used as sentinel)" #bruce 060217 added this assert
+ ColorSorter._gl_name_stack.append(glname)
+
+ pushName = staticmethod(pushName)
+
+
+ def popName():
+ """
+ Record a pop of the GL name.
+ """
+ del ColorSorter._gl_name_stack[-1]
+
+ popName = staticmethod(popName)
+
+
+ def _printstats():
+ """
+ Internal function for developers to call to print stats on number of
+ sorted and immediately-called objects.
+ """
+ print "Since previous 'stats', %d sorted, %d immediate: " % (ColorSorter._sorted, ColorSorter._immediate)
+ ColorSorter._sorted = 0
+ ColorSorter._immediate = 0
+
+ _printstats = staticmethod(_printstats)
+
+
+ def _add_to_sorter(color, func, params):
+ """
+ Internal function that stores 'scheduled' operations for a later
+ sort, between a start/finish
+ """
+ ColorSorter._sorted += 1
+ color = tuple(color)
+ if not ColorSorter.sorted_by_color.has_key(color):
+ ColorSorter.sorted_by_color[color] = []
+ ColorSorter.sorted_by_color[color].append((func, params,
+ ColorSorter._gl_name_stack[-1]))
+
+ _add_to_sorter = staticmethod(_add_to_sorter)
+
+
+ def schedule(color, func, params):
+ if ColorSorter.sorting and drawing_globals.allow_color_sorting:
+
+ ColorSorter._add_to_sorter(color, func, params)
+
+ else:
+
+ ColorSorter._immediate += 1 # for benchmark/debug stats, mostly
+
+ # 20060216 We know we can do this here because the stack is
+ # only ever one element deep
+ name = ColorSorter._gl_name_stack[-1]
+ if name:
+ glPushName(name)
+
+ #Apply appropriate opacity for the object if it is specified
+ #in the 'color' param. (Also do necessary things such as
+ #call glBlendFunc it. -- Ninad 20071009
+
+ if len(color) == 4:
+ opacity = color[3]
+ else:
+ opacity = 1.0
+
+ if opacity >= 0.0 and opacity != 1.0:
+ glDepthMask(GL_FALSE)
+ glEnable(GL_BLEND)
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+ elif opacity == -1:
+ # piotr 080429: I replaced the " < 0" condition with " == -1"
+ # The opacity flag is now used to signal either "unshaded colors"
+ # (opacity == -1) or "multicolor object" (opacity == -2)
+ glDisable(GL_LIGHTING) # Don't forget to re-enable it!
+ glColor3fv(color[:3])
+ pass
+
+ apply_material(color)
+ func(params)
+
+ if opacity > 0.0 and opacity != 1.0:
+ glDisable(GL_BLEND)
+ glDepthMask(GL_TRUE)
+ elif opacity == -1:
+ # piotr 080429: See my comment above.
+ glEnable(GL_LIGHTING)
+
+ if name:
+ glPopName()
+ return
+
+ schedule = staticmethod(schedule)
+
+ def schedule_sphere(color, pos, radius, detailLevel, opacity = 1.0):
+ """
+ Schedule a sphere for rendering whenever ColorSorter thinks is
+ appropriate.
+ """
+ if drawing_globals.use_c_renderer and ColorSorter.sorting:
+ if len(color) == 3:
+ lcolor = (color[0], color[1], color[2], opacity)
+ else:
+ lcolor = color
+ ColorSorter._cur_shapelist.add_sphere(lcolor, pos, radius,
+ ColorSorter._gl_name_stack[-1])
+ # 20060208 grantham - I happen to know that one detailLevel
+ # is chosen for all spheres, I just record it over and
+ # over here, and use the last one for the render
+ if ColorSorter.sphereLevel > -1 and ColorSorter.sphereLevel != detailLevel:
+ raise ValueError, "unexpected different sphere LOD levels within same frame"
+ ColorSorter.sphereLevel = detailLevel
+ else: # Older sorted material rendering
+ if len(color) == 3:
+ lcolor = (color[0], color[1], color[2], opacity)
+ else:
+ lcolor = color
+ ColorSorter.schedule(lcolor, drawsphere_worker, ### drawsphere_worker_loop ### Testing.
+ (pos, radius, detailLevel))
+
+ schedule_sphere = staticmethod(schedule_sphere)
+
+
+ def schedule_wiresphere(color, pos, radius, detailLevel = 1):
+ """
+ Schedule a wiresphere for rendering whenever ColorSorter thinks is
+ appropriate.
+ """
+ if drawing_globals.use_c_renderer and ColorSorter.sorting:
+ if len(color) == 3:
+ lcolor = (color[0], color[1], color[2], 1.0)
+ else:
+ lcolor = color
+ assert 0, "Need to implement a C add_wiresphere function."
+ ColorSorter._cur_shapelist.add_wiresphere(lcolor, pos, radius,
+ ColorSorter._gl_name_stack[-1])
+ else:
+ if len(color) == 3:
+ lcolor = (color[0], color[1], color[2], 1.0)
+ else:
+ lcolor = color
+
+ ColorSorter.schedule(lcolor, drawwiresphere_worker,
+ # Use constant-color line drawing.
+ (color, pos, radius, detailLevel))
+
+ schedule_wiresphere = staticmethod(schedule_wiresphere)
+
+ def schedule_cylinder(color, pos1, pos2, radius, capped = 0, opacity = 1.0 ):
+ """
+ Schedule a cylinder for rendering whenever ColorSorter thinks is
+ appropriate.
+ """
+ if drawing_globals.use_c_renderer and ColorSorter.sorting:
+ if len(color) == 3:
+ lcolor = (color[0], color[1], color[2], 1.0)
+ else:
+ lcolor = color
+ ColorSorter._cur_shapelist.add_cylinder(lcolor, pos1, pos2, radius,
+ ColorSorter._gl_name_stack[-1], capped)
+ else:
+ if len(color) == 3:
+ lcolor = (color[0], color[1], color[2], opacity)
+ else:
+ lcolor = color
+
+ ColorSorter.schedule(lcolor, drawcylinder_worker, (pos1, pos2, radius, capped))
+
+ schedule_cylinder = staticmethod(schedule_cylinder)
+
+ def schedule_polycone(color, pos_array, rad_array, capped = 0, opacity = 1.0):
+ """
+ Schedule a polycone for rendering whenever ColorSorter thinks is
+ appropriate.
+ """
+ if drawing_globals.use_c_renderer and ColorSorter.sorting:
+ if len(color) == 3:
+ lcolor = (color[0], color[1], color[2], 1.0)
+ else:
+ lcolor = color
+ assert 0, "Need to implement a C add_polycone_multicolor function."
+ ColorSorter._cur_shapelist.add_polycone(lcolor, pos_array, rad_array,
+ ColorSorter._gl_name_stack[-1], capped)
+ else:
+ if len(color) == 3:
+ lcolor = (color[0], color[1], color[2], opacity)
+ else:
+ lcolor = color
+
+ ColorSorter.schedule(lcolor, drawpolycone_worker, (pos_array, rad_array))
+
+ schedule_polycone = staticmethod(schedule_polycone)
+
+ def schedule_polycone_multicolor(color, pos_array, color_array, rad_array, capped = 0, opacity = 1.0):
+ """
+ Schedule a polycone for rendering whenever ColorSorter thinks is
+ appropriate.
+ piotr 080311: this variant accepts a color array as an additional parameter
+ """
+ if drawing_globals.use_c_renderer and ColorSorter.sorting:
+ if len(color) == 3:
+ lcolor = (color[0], color[1], color[2], 1.0)
+ else:
+ lcolor = color
+ assert 0, "Need to implement a C add_polycone function."
+ ColorSorter._cur_shapelist.add_polycone_multicolor(lcolor, pos_array, color_array, rad_array,
+ ColorSorter._gl_name_stack[-1], capped)
+ else:
+ if len(color) == 3:
+ lcolor = (color[0], color[1], color[2], opacity)
+ else:
+ lcolor = color
+
+ ColorSorter.schedule(lcolor, drawpolycone_multicolor_worker, (pos_array, color_array, rad_array))
+
+ schedule_polycone_multicolor = staticmethod(schedule_polycone_multicolor)
+
+ def schedule_surface(color, pos, radius, tm, nm):
+ """
+ Schedule a surface for rendering whenever ColorSorter thinks is
+ appropriate.
+ """
+ ColorSorter.schedule(color, drawsurface_worker, (pos, radius, tm, nm))
+
+ schedule_surface = staticmethod(schedule_surface)
+
+ def schedule_line(color, endpt1, endpt2, dashEnabled,
+ stipleFactor, width, isSmooth):
+ """
+ Schedule a line for rendering whenever ColorSorter thinks is
+ appropriate.
+ """
+ #russ 080306: Signal "unshaded colors" for lines by a negative alpha. (Hack!)
+ color = tuple(color) + (-1,)
+ ColorSorter.schedule(color, drawline_worker,
+ (endpt1, endpt2, dashEnabled,
+ stipleFactor, width, isSmooth))
+
+ schedule_line = staticmethod(schedule_line)
+
+ def start(csdl, pickstate=None):
+ """
+ Start sorting - objects provided to "schedule", "schedule_sphere", and
+ "schedule_cylinder" will be stored for a sort at the time "finish" is called.
+ csdl is a ColorSortedDisplayList or None, in which case immediate drawing is done.
+ pickstate (optional) indicates whether the parent is currently selected.
+ """
+
+ #russ 080225: Moved glNewList here for displist re-org.
+ ColorSorter.parent_csdl = csdl # Remember, used by finish().
+ if pickstate is not None:
+ csdl.selectPick(pickstate)
+ pass
+
+ if csdl != None:
+ if not (drawing_globals.allow_color_sorting and
+ (drawing_globals.use_color_sorted_dls
+ or drawing_globals.use_color_sorted_vbos)): #russ 080320
+ # This is the beginning of the single display list created when color
+ # sorting is turned off. It is ended in ColorSorter.finish . In
+ # between, the calls to draw{sphere,cylinder,polycone} methods pass
+ # through ColorSorter.schedule_* but are immediately sent to *_worker
+ # where they do OpenGL drawing that is captured into the display list.
+ try:
+ if csdl.dl is 0:
+ csdl.activate() # Allocate a display list for our use.
+ pass
+ glNewList(csdl.dl, GL_COMPILE_AND_EXECUTE) # Start a single-level list.
+ except:
+ print "data related to following exception: csdl.dl = %r" % (csdl.dl,) #bruce 070521
+ raise
+
+ assert not ColorSorter.sorting, "Called ColorSorter.start but already sorting?!"
+ ColorSorter.sorting = True
+ if drawing_globals.use_c_renderer and ColorSorter.sorting:
+ ColorSorter._cur_shapelist = ShapeList_inplace()
+ ColorSorter.sphereLevel = -1
+ else:
+ ColorSorter.sorted_by_color = {}
+
+ start = staticmethod(start)
+
+ def finish():
+ """
+ Finish sorting - objects recorded since "start" will
+ be sorted and invoked now.
+ """
+ from utilities.debug_prefs import debug_pref, Choice_boolean_False
+ debug_which_renderer = debug_pref("debug print which renderer", Choice_boolean_False) #bruce 060314, imperfect but tolerable
+
+ parent_csdl = ColorSorter.parent_csdl
+ if drawing_globals.use_c_renderer:
+ quux.shapeRendererInit()
+ if debug_which_renderer:
+ #bruce 060314 uncommented/revised the next line; it might have to come after shapeRendererInit (not sure);
+ # it definitely has to come after a graphics context is created and initialized.
+ # 20060314 grantham - yes, has to come after quux.shapeRendererInit
+ print "using C renderer: VBO %s enabled" % (('is NOT', 'is')[quux.shapeRendererGetInteger(quux.IS_VBO_ENABLED)])
+ quux.shapeRendererSetUseDynamicLOD(0)
+ if ColorSorter.sphereLevel != -1:
+ quux.shapeRendererSetStaticLODLevels(ColorSorter.sphereLevel, 1)
+ quux.shapeRendererStartDrawing()
+ ColorSorter._cur_shapelist.draw()
+ quux.shapeRendererFinishDrawing()
+ ColorSorter.sorting = False
+
+ # So chunks can actually record their shapelist
+ # at some point if they want to
+ # ColorSorter._cur_shapelist.petrify()
+ # return ColorSorter._cur_shapelist
+
+ else:
+ if debug_which_renderer:
+ print "using Python renderer: use_color_sorted_dls %s enabled" \
+ % (drawing_globals.use_color_sorted_dls and 'IS'
+ or 'is NOT')
+ print "using Python renderer: use_color_sorted_vbos %s enabled" \
+ % (drawing_globals.use_color_sorted_vbos and 'IS'
+ or 'is NOT')
+ color_groups = len(ColorSorter.sorted_by_color)
+ objects_drawn = 0
+
+ if (not (drawing_globals.allow_color_sorting and
+ drawing_globals.use_color_sorted_dls)
+ or (ColorSortedDisplayList.cache_ColorSorter and
+ drawing_globals.allow_color_sorting and
+ drawing_globals.use_color_sorted_vbos)
+ or parent_csdl is None): #russ 080225 Added, 080320 VBO experiment.
+
+ # Either all in one display list, or immediate-mode drawing.
+ objects_drawn += ColorSorter.draw_sorted(ColorSorter.sorted_by_color)
+
+ #russ 080225: Moved glEndList here for displist re-org.
+ if parent_csdl is not None:
+ #russ 080320: Experiment with VBO drawing from cached ColorSorter lists.
+ if (ColorSortedDisplayList.cache_ColorSorter and
+ drawing_globals.allow_color_sorting and
+ drawing_globals.use_color_sorted_vbos):
+ # Remember the ColorSorter lists for use as a pseudo-display-list.
+ parent_csdl.sorted_by_color = ColorSorter.sorted_by_color
+ else:
+ # Terminate a single display list, created when color sorting
+ # is turned off. It was started in ColorSorter.start .
+ glEndList()
+ pass
+ pass
+
+ else: #russ 080225
+
+ parent_csdl.reset()
+
+ # First build the lower level per-color sublists of primitives.
+ for color, funcs in ColorSorter.sorted_by_color.iteritems():
+ sublists = [glGenLists(1), 0]
+
+ # Remember the display list ID for this color.
+ parent_csdl.per_color_dls.append([color, sublists])
+
+ glNewList(sublists[0], GL_COMPILE)
+ opacity = color[3]
+
+ if opacity == -1:
+ #russ 080306: "Unshaded colors" for lines are signaled
+ # by an opacity of -1 (4th component of the color.)
+ glDisable(GL_LIGHTING) # Don't forget to re-enable it!
+ pass
+
+ for func, params, name in funcs:
+ objects_drawn += 1
+ if name != 0:
+ glPushName(name)
+ func(params)
+ if name != 0:
+ glPopName()
+ pass
+ continue
+
+ if opacity == -1:
+ # Enable lighting after drawing "unshaded" objects.
+ glEnable(GL_LIGHTING)
+ pass
+ glEndList()
+
+ if opacity == -2:
+ # piotr 080419: Special case for drawpolycone_multicolor
+ # create another display list that ignores
+ # the contents of color_array.
+ # Remember the display list ID for this color.
+
+ sublists[1] = glGenLists(1)
+
+ glNewList(sublists[1], GL_COMPILE)
+
+ for func, params, name in funcs:
+ objects_drawn += 1
+ if name != 0:
+ glPushName(name)
+ pos_array, color_array, rad_array = params
+ if func == drawpolycone_multicolor_worker:
+ # Just to be sure, check if the func
+ # is drawpolycone_multicolor_worker
+ # and call drawpolycone_worker instead.
+ # I think in the future we can figure out
+ # a more general way of handling the
+ # GL_COLOR_MATERIAL objects. piotr 080420
+ drawpolycone_worker((pos_array, rad_array))
+ if name != 0:
+ glPopName()
+ pass
+ continue
+ glEndList()
+
+ continue
+
+ # Now the upper-level lists call all of the per-color sublists.
+ # One with colors.
+ color_dl = parent_csdl.color_dl = glGenLists(1)
+ glNewList(color_dl, GL_COMPILE)
+
+ for color, dls in parent_csdl.per_color_dls:
+
+ opacity = color[3]
+ if opacity < 0:
+ #russ 080306: "Unshaded colors" for lines are signaled
+ # by a negative alpha.
+ glColor3fv(color[:3])
+ # piotr 080417: for opacity == -2, i.e. if
+ # GL_COLOR_MATERIAL is enabled, the color is going
+ # to be ignored, anyway, so it is not necessary
+ # to be tested here
+ else:
+ apply_material(color)
+
+ glCallList(dls[0])
+
+ continue
+ glEndList()
+
+ # A second one without any colors.
+ nocolor_dl = parent_csdl.nocolor_dl = glGenLists(1)
+ glNewList(nocolor_dl, GL_COMPILE)
+ for color, dls in parent_csdl.per_color_dls:
+ opacity = color[3]
+
+ if opacity == -2 \
+ and dls[1] > 0:
+ # piotr 080420: If GL_COLOR_MATERIAL is enabled,
+ # use a regular, single color dl rather than the
+ # multicolor one. Btw, dls[1] == 0 should never
+ # happen.
+ glCallList(dls[1])
+ else:
+ glCallList(dls[0])
+
+ glEndList()
+
+ # A third overlays the second with a single color for selection.
+ selected_dl = parent_csdl.selected_dl = glGenLists(1)
+ glNewList(selected_dl, GL_COMPILE)
+ apply_material(darkgreen)
+ glCallList(nocolor_dl)
+ glEndList()
+
+ # Use either the normal-color display list or the selected one.
+ parent_csdl.selectDl()
+
+ # Draw the newly-built display list.
+ parent_csdl.draw_dl()
+ pass
+
+ ColorSorter.sorted_by_color = None
+ pass
+ ColorSorter.sorting = False
+ return
+
+ finish = staticmethod(finish)
+
+ def draw_sorted(sorted_by_color): #russ 080320: factored out of finish().
+ """
+ Traverse color-sorted lists, invoking worker procedures.
+ """
+ objects_drawn = 0 # Keep track and return.
+ glEnable(GL_LIGHTING)
+
+ for color, funcs in sorted_by_color.iteritems():
+
+ opacity = color[3]
+ if opacity == -1:
+ #piotr 080429: Opacity == -1 signals the "unshaded color".
+ # Also, see my comment in "schedule".
+ glDisable(GL_LIGHTING) # Don't forget to re-enable it!
+ glColor3fv(color[:3])
+ else:
+ apply_material(color)
+ pass
+
+ for func, params, name in funcs:
+ objects_drawn += 1
+ if name != 0:
+ glPushName(name)
+ func(params)
+ if name != 0:
+ glPopName()
+ pass
+ continue
+
+ if opacity == -1:
+ glEnable(GL_LIGHTING)
+
+ continue
+ return objects_drawn
+
+ draw_sorted = staticmethod(draw_sorted)
+
+ pass # End of class ColorSorter.
diff --git a/cad/src/graphics/drawing/Font3D.py b/cad/src/graphics/drawing/Font3D.py
index 1311d8771..be150461f 100755
--- a/cad/src/graphics/drawing/Font3D.py
+++ b/cad/src/graphics/drawing/Font3D.py
@@ -23,7 +23,7 @@ from Numeric import dot
from OpenGL.GL import glVertex
from geometry.VQT import cross
-from graphics.drawing.drawer import drawline # import cycle
+from graphics.drawing.CS_draw_primitives import drawline # import cycle
_font = {
' ': ( ),
diff --git a/cad/src/graphics/drawing/bond_drawer.py b/cad/src/graphics/drawing/bond_drawer.py
index 561b60d9b..54e046437 100755
--- a/cad/src/graphics/drawing/bond_drawer.py
+++ b/cad/src/graphics/drawing/bond_drawer.py
@@ -24,11 +24,11 @@ from PyQt4.Qt import QFont, QString, QColor
from geometry.VQT import V
from geometry.VQT import norm, vlen
-from graphics.drawing.drawer import ColorSorter
-from graphics.drawing.drawer import drawline
-from graphics.drawing.drawer import drawcylinder
-from graphics.drawing.drawer import drawsphere
-from graphics.drawing.drawer import drawpolycone
+from graphics.drawing.ColorSorter import ColorSorter
+from graphics.drawing.CS_draw_primitives import drawline
+from graphics.drawing.CS_draw_primitives import drawcylinder
+from graphics.drawing.CS_draw_primitives import drawsphere
+from graphics.drawing.CS_draw_primitives import drawpolycone
import foundation.env as env
from utilities import debug_flags
diff --git a/cad/src/graphics/drawing/dimensions.py b/cad/src/graphics/drawing/dimensions.py
index 5335ddcb8..4d7f0cde7 100755
--- a/cad/src/graphics/drawing/dimensions.py
+++ b/cad/src/graphics/drawing/dimensions.py
@@ -21,7 +21,7 @@ from utilities import debug_flags
from geometry.VQT import cross
from geometry.VQT import vlen
from geometry.VQT import norm
-from graphics.drawing.drawer import drawline
+from graphics.drawing.CS_draw_primitives import drawline
from graphics.drawing.Font3D import Font3D, WIDTH, HEIGHT
# TODO: WIDTH, HEIGHT should be Font3D attributes [bruce 071030 comment]
diff --git a/cad/src/graphics/drawing/drawDnaLadder.py b/cad/src/graphics/drawing/drawDnaLadder.py
index 0b931d35a..2d7c429e6 100755
--- a/cad/src/graphics/drawing/drawDnaLadder.py
+++ b/cad/src/graphics/drawing/drawDnaLadder.py
@@ -21,9 +21,9 @@ from OpenGL.GL import glPopMatrix
from OpenGL.GL import glPushMatrix
from OpenGL.GL import glTranslatef
-from graphics.drawing.drawer import drawArrowHead
-from graphics.drawing.drawer import drawline
-from graphics.drawing.drawer import drawPoint
+from graphics.drawing.drawers import drawArrowHead
+from graphics.drawing.CS_draw_primitives import drawline
+from graphics.drawing.drawers import drawPoint
from geometry.VQT import norm, vlen, V, cross
diff --git a/cad/src/graphics/drawing/drawDnaRibbons.py b/cad/src/graphics/drawing/drawDnaRibbons.py
index e6ef153dc..093eb3a60 100755
--- a/cad/src/graphics/drawing/drawDnaRibbons.py
+++ b/cad/src/graphics/drawing/drawDnaRibbons.py
@@ -26,11 +26,11 @@ from OpenGL.GL import glPopMatrix
from OpenGL.GL import glPushMatrix
from OpenGL.GL import glTranslatef
-from graphics.drawing.drawer import drawArrowHead
-from graphics.drawing.drawer import drawline
-from graphics.drawing.drawer import drawPoint
-from graphics.drawing.drawer import drawsphere
-from graphics.drawing.drawer import drawtext
+from graphics.drawing.drawers import drawArrowHead
+from graphics.drawing.CS_draw_primitives import drawline
+from graphics.drawing.drawers import drawPoint
+from graphics.drawing.CS_draw_primitives import drawsphere
+from graphics.drawing.drawers import drawtext
from geometry.VQT import norm, vlen, V, cross, Q
from geometry.VQT import orthodist, angleBetween
diff --git a/cad/src/graphics/drawing/drawNanotubeLadder.py b/cad/src/graphics/drawing/drawNanotubeLadder.py
index 2a26b3b8b..33c7a6d86 100644
--- a/cad/src/graphics/drawing/drawNanotubeLadder.py
+++ b/cad/src/graphics/drawing/drawNanotubeLadder.py
@@ -15,9 +15,9 @@ from OpenGL.GL import glPopMatrix
from OpenGL.GL import glPushMatrix
from OpenGL.GL import glTranslatef
-from graphics.drawing.drawer import drawline
-from graphics.drawing.drawer import drawPoint
-from graphics.drawing.drawer import drawCircle
+from graphics.drawing.CS_draw_primitives import drawline
+from graphics.drawing.drawers import drawPoint
+from graphics.drawing.drawers import drawCircle
from geometry.VQT import norm, vlen, V, cross
diff --git a/cad/src/graphics/drawing/draw_bond_vanes.py b/cad/src/graphics/drawing/draw_bond_vanes.py
index 21bedfa26..ee7227d8e 100755
--- a/cad/src/graphics/drawing/draw_bond_vanes.py
+++ b/cad/src/graphics/drawing/draw_bond_vanes.py
@@ -32,7 +32,7 @@ from OpenGL.GL import GL_FALSE
from geometry.VQT import cross, vlen, norm
import foundation.env as env
-from graphics.drawing.drawer import apply_material
+from graphics.drawing.gl_lighting import apply_material
from utilities.constants import white
from utilities.prefs_constants import pibondStyle_prefs_key
diff --git a/cad/src/graphics/drawing/draw_grid_lines.py b/cad/src/graphics/drawing/draw_grid_lines.py
index 60b7de0d9..2ad5047da 100644
--- a/cad/src/graphics/drawing/draw_grid_lines.py
+++ b/cad/src/graphics/drawing/draw_grid_lines.py
@@ -55,7 +55,7 @@ from OpenGL.GL import glVertex3fv
from OpenGL.GL import glEndList
from OpenGL.GL import glColor3fv
-from graphics.drawing.drawer import drawtext
+from graphics.drawing.drawers import drawtext
from geometry.VQT import V
from graphics.drawing.Font3D import Font3D
diff --git a/cad/src/graphics/drawing/drawer.py b/cad/src/graphics/drawing/drawer.py
deleted file mode 100755
index a2b777571..000000000
--- a/cad/src/graphics/drawing/drawer.py
+++ /dev/null
@@ -1,3975 +0,0 @@
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-drawer.py - OpenGL drawing utilities.
-
-@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
-
-TODO:
-
-This module is too large. It needs to be split into
-several smaller files. Don't add new functions to it --
-add them in new files whose names start with "draw".
-
-History:
-
-Originated by Josh.
-
-Various developers extended it since then.
-
-Brad G. added ColorSorter features.
-
-At some point Bruce partly cleaned up the use of display lists.
-
-071030 bruce split some functions and globals into draw_grid_lines.py
-and removed some obsolete functions.
-
-080210 russ Split the single display-list into two second-level lists (with and without color)
-and a set of per-color sublists so selection and hover-highlight can over-ride Chunk base colors.
-ColorSortedDisplayList is now a class in the parent's displist attr to keep track of all that stuff.
-
-080311 piotr Added a "drawpolycone_multicolor" function for drawing polycone
-tubes with per-vertex colors (necessary for DNA display style)
-
-080313 russ Added triangle-strip icosa-sphere constructor, "getSphereTriStrips".
-
-080420 piotr Solved highlighting and selection problems for multi-colored
-objects (e.g. rainbow colored DNA structures).
-
-"""
-
-import os
-import sys
-
-# the imports from math vs. Numeric are as discovered in existing code
-# as of 2007/06/25. It's not clear why acos is coming from math...
-from math import floor, ceil, acos, atan2
-import Numeric
-from Numeric import sin, cos, sqrt, pi
-degreesPerRadian = 180.0 / pi
-
-from OpenGL.GL import GL_AMBIENT
-from OpenGL.GL import GL_AMBIENT_AND_DIFFUSE
-from OpenGL.GL import glAreTexturesResident
-from OpenGL.GL import GL_ARRAY_BUFFER_ARB
-from OpenGL.GL import GL_BACK
-from OpenGL.GL import glBegin
-from OpenGL.GL import glBindTexture
-from OpenGL.GL import GL_BLEND
-from OpenGL.GL import glBlendFunc
-from OpenGL.GL import glCallList
-from OpenGL.GL import glColor3f
-from OpenGL.GL import glColor3fv
-from OpenGL.GL import glColor4fv
-from OpenGL.GL import GL_COLOR_MATERIAL
-from OpenGL.GL import GL_COMPILE
-from OpenGL.GL import GL_COMPILE_AND_EXECUTE
-from OpenGL.GL import GL_CONSTANT_ATTENUATION
-from OpenGL.GL import GL_CULL_FACE
-from OpenGL.GL import GL_CURRENT_BIT
-from OpenGL.GL import glDeleteLists
-from OpenGL.GL import glDeleteTextures
-from OpenGL.GL import glDepthMask
-from OpenGL.GL import GL_DEPTH_TEST
-from OpenGL.GL import GL_DIFFUSE
-from OpenGL.GL import glDisable
-from OpenGL.GL import glDisableClientState
-from OpenGL.GL import glDrawArrays
-from OpenGL.GL import glDrawElements
-from OpenGL.GL import glDrawElementsub
-from OpenGL.GL import glDrawElementsui
-from OpenGL.GL import glDrawElementsus
-from OpenGL.GL import GL_ELEMENT_ARRAY_BUFFER_ARB
-from OpenGL.GL import glEnable
-from OpenGL.GL import glEnableClientState
-from OpenGL.GL import glEnd
-from OpenGL.GL import glEndList
-from OpenGL.GL import GL_EXTENSIONS
-from OpenGL.GL import GL_FALSE
-from OpenGL.GL import GL_FILL
-from OpenGL.GL import glFinish
-from OpenGL.GL import GL_FLOAT
-from OpenGL.GL import GL_FOG
-from OpenGL.GL import GL_FOG_COLOR
-from OpenGL.GL import GL_FOG_END
-from OpenGL.GL import GL_FOG_MODE
-from OpenGL.GL import GL_FOG_START
-from OpenGL.GL import GL_FRONT
-from OpenGL.GL import GL_FRONT_AND_BACK
-from OpenGL.GL import glGenLists
-from OpenGL.GL import glGenTextures
-from OpenGL.GL import glGetString
-from OpenGL.GL import GL_LIGHT0
-from OpenGL.GL import GL_LIGHT1
-from OpenGL.GL import GL_LIGHT2
-from OpenGL.GL import glLightf
-from OpenGL.GL import glLightfv
-from OpenGL.GL import GL_LIGHTING
-from OpenGL.GL import GL_LINE
-from OpenGL.GL import GL_LINEAR
-from OpenGL.GL import GL_LINE_LOOP
-from OpenGL.GL import GL_LINES
-from OpenGL.GL import GL_LINE_SMOOTH
-from OpenGL.GL import glLineStipple
-from OpenGL.GL import GL_LINE_STIPPLE
-from OpenGL.GL import GL_LINE_STRIP
-from OpenGL.GL import glLineWidth
-from OpenGL.GL import glLoadIdentity
-from OpenGL.GL import glMaterialf
-from OpenGL.GL import glMaterialfv
-from OpenGL.GL import glMatrixMode
-from OpenGL.GL import GL_MODELVIEW
-from OpenGL.GL import glNewList
-from OpenGL.GL import glNormal3fv
-from OpenGL.GL import glNormalPointer
-from OpenGL.GL import glNormalPointerf
-from OpenGL.GL import GL_NORMAL_ARRAY
-from OpenGL.GL import GL_ONE_MINUS_SRC_ALPHA
-from OpenGL.GL import glPointSize
-from OpenGL.GL import GL_POINTS
-from OpenGL.GL import GL_POINT_SMOOTH
-from OpenGL.GL import GL_POLYGON
-from OpenGL.GL import glPolygonMode
-from OpenGL.GL import glPopAttrib
-from OpenGL.GL import glPopMatrix
-from OpenGL.GL import glPopName
-from OpenGL.GL import GL_POSITION
-from OpenGL.GL import glPushAttrib
-from OpenGL.GL import glPushMatrix
-from OpenGL.GL import glPushName
-from OpenGL.GL import GL_QUADS
-from OpenGL.GL import GL_QUAD_STRIP
-from OpenGL.GL import GL_RENDERER
-from OpenGL.GL import GL_RGBA
-from OpenGL.GL import glRotate
-from OpenGL.GL import glRotatef
-from OpenGL.GL import GL_SHININESS
-from OpenGL.GL import GL_SPECULAR
-from OpenGL.GL import GL_SRC_ALPHA
-from OpenGL.GL import GL_STATIC_DRAW
-from OpenGL.GL import glTexCoord2f
-from OpenGL.GL import glTexCoord2fv
-from OpenGL.GL import GL_TEXTURE_2D
-from OpenGL.GL import glTranslate
-from OpenGL.GL import glTranslatef
-from OpenGL.GL import GL_TRIANGLES
-from OpenGL.GL import GL_TRIANGLE_STRIP
-from OpenGL.GL import GL_TRUE
-from OpenGL.GL import GL_UNSIGNED_BYTE
-from OpenGL.GL import GL_UNSIGNED_SHORT
-from OpenGL.GL import GL_VENDOR
-from OpenGL.GL import GL_VERSION
-from OpenGL.GL import glVertex
-from OpenGL.GL import glVertex2f
-from OpenGL.GL import glVertex3f
-from OpenGL.GL import glVertex3fv
-from OpenGL.GL import GL_VERTEX_ARRAY
-from OpenGL.GL import glVertexPointer
-from OpenGL.GL import glVertexPointerf
-
-from OpenGL.GLU import gluBuild2DMipmaps
-
-try:
- from OpenGL.GL import glScale
-except:
- # The installed version of OpenGL requires argument-typed glScale calls.
- from OpenGL.GL import glScalef as glScale
-
-from OpenGL.GL import glScalef
- # Note: this is NOT redundant with the above import of glScale --
- # without it, displaying an ESP Image gives a NameError traceback
- # and doesn't work. [Fixed by bruce 070703; bug caught by Eric M using
- # PyChecker; bug introduced sometime after A9.1 went out.]
-
-try:
- from OpenGL.GL import glFog
- from OpenGL.GL import glFogv # piotr 080515
-except:
- # The installed version of OpenGL requires argument-typed glFog calls.
- from OpenGL.GL import glFogf as glFog
- from OpenGL.GL import glFogfv as glFogv
-
-from geometry.VQT import norm, vlen, V, Q, A
-
-from utilities.constants import white, blue, red
-from utilities.constants import darkgreen, lightblue
-from utilities.constants import DIAMOND_BOND_LENGTH
-from utilities.prefs_constants import material_specular_highlights_prefs_key
-from utilities.prefs_constants import material_specular_shininess_prefs_key
-from utilities.prefs_constants import material_specular_finish_prefs_key
-from utilities.prefs_constants import material_specular_brightness_prefs_key
-
-import graphics.drawing.drawing_globals as drawing_globals
-
-from utilities.debug_prefs import Choice
-import utilities.debug as debug # for debug.print_compact_traceback
-
-# this can't be done at toplevel due to a recursive import issue.
-# TODO: fix by splitting this module (drawer) into smaller files.
-## from Font3D import Font3D
-
-import utilities.EndUser as EndUser
-
-import numpy
-
-#================================================================ shape_vertices.py
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-shape_vertices.py - Geometric constructions of vertex lists used by the drawing functions.
-
-This includes vertices for the shapes of primitives that will go into display
-lists in the setup_drawer function in setup_draw.py .
-
-@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-
-import graphics.drawing.drawing_globals as drawing_globals
-
-def init_icos():
- global icosa, icosix
-
- # the golden ratio
- global phi
- phi = (1.0+sqrt(5.0))/2.0
- vert = norm(V(phi,0,1))
- a = vert[0]
- b = vert[1]
- c = vert[2]
-
- # vertices of an icosahedron
- icosa = ((-a,b,c), (b,c,-a), (b,c,a), (a,b,-c), (-c,-a,b), (-c,a,b),
- (b,-c,a), (c,a,b), (b,-c,-a), (a,b,c), (c,-a,b), (-a,b,-c))
- icosix = ((9, 2, 6), (1, 11, 5), (11, 1, 8), (0, 11, 4), (3, 1, 7),
- (3, 8, 1), (9, 3, 7), (0, 6, 2), (4, 10, 6), (1, 5, 7),
- (7, 5, 2), (8, 3, 10), (4, 11, 8), (9, 7, 2), (10, 9, 6),
- (0, 5, 11), (0, 2, 5), (8, 10, 4), (3, 9, 10), (6, 0, 4))
- return
-init_icos()
-
-# generate geodesic spheres by subdividing the faces of an icosahedron
-# recursively:
-# /\ /\
-# / \ / \
-# / \ /____\
-# / \ => /\ /\
-# / \ / \ / \
-# /__________\ /____\/____\
-#
-# and normalizing the resulting vectors to the surface of a sphere
-
-def subdivide(tri,deep):
- if deep:
- a = tri[0]
- b = tri[1]
- c = tri[2]
- a1 = norm(A(tri[0]))
- b1 = norm(A(tri[1]))
- c1 = norm(A(tri[2]))
- d = tuple(norm(a1+b1))
- e = tuple(norm(b1+c1))
- f = tuple(norm(c1+a1))
- return subdivide((a,d,f), deep-1) + subdivide((d,e,f), deep-1) +\
- subdivide((d,b,e), deep-1) + subdivide((f,e,c), deep-1)
- else: return [tri]
-
-## Get the specific detail level of triangles approximation of a sphere
-def getSphereTriangles(level):
- ocdec = []
- for i in icosix:
- ocdec += subdivide((icosa[i[0]],icosa[i[1]],icosa[i[2]]),level)
- return ocdec
-
-# ==
-
-# Instead of the above recursive scheme that orients the icosahedron with the
-# midpoints of six edges perpendicular to the major axes, use a ring approach
-# to make subdivided icosa-spheres for Triangle Strips. The vertices are
-# grouped in rings from the North Pole to the South Pole. Each strip zig-zags
-# between two rings, and the poles are surrounded by pentagonal Triangle Fans.
-#
-# ----------------
-#
-# The pattern of five-fold vertices in a "twisted orange-slice" segment
-# covering one-fifth of the icosahedron is:
-#
-# ... [3,0] ... (North Pole)
-# / | \
-# / | ...
-# / |
-# ... [2,1]---[2,0] ...
-# / \ / \
-# ... \ / \ ...
-# \ / \ /
-# ... [1,1]---[1,0] ...
-# | /
-# ... | /
-# \ | /
-# ... [0,0] ... (South Pole)
-#
-# ----------------
-#
-# Higher subdivision levels step the strip verts along the icos edges,
-# interpolating intermediate points on the icos and projecting each onto the
-# sphere. Note: sphere vertex normals are the same as their coords.
-#
-# The "*"s show approximate vertex locations at each subdivision level.
-# Bands are numbered from South to North. (Reason explained below.)
-# Sub-band numbers are in angle-brackets, "<>".
-#
-# Level 0 [3*0] Level 1 [6*0] Level 2 [12*0] _<3>
-# / | (2 steps) / | <1> (4 steps) *-* _<2>
-# Band 2 / | * - * *-*-* _<1>
-# / | / | / | <0> *-*-*-* _<0>
-# [2*1]- -[2*0] => [4*2]-*-[4*0] => [8*4]***[8*0] _<3>
-# \ / \ \ / \ / \ <1> *-*-*-*-* _<2>
-# Band 1 \ / \ * - * - * *-*-*-*-* _<1>
-# \ / \ \ / \ / \ <0> *-*-*-*-* _<0>
-# [1*1]---[1*0] [2*2]-*-[2*0] [4*4]***[4*0]_<3>
-# | / | \ | / <1> *-*-*-* _<2>
-# Band 0 | / * - * *-*-* _<1>
-# | / | / <0> *-* _<0>
-# [0*0] [0*0] [0*0]
-#
-# ----------------
-#
-# The reason for rotating east, then going west along the latitude lines, is
-# that the "grain" of triangle strip diagonals runs that way in the middle
-# band of the icos:
-#
-# Triangle Strip triangles
-#
-# 6 ----- 4 ----- 2
-# \5,4,6/ \3,2,4/ \
-# ... \ / \ / \
-# \ /3,4,5\ /1,2,3\
-# 5 ----- 3 ----- 1 <- Vertex order
-#
-# This draws triangles 1-2-3, 3-2-4, 3-4-5, and 5-4-6, all counter-clockwise
-# so the normal directions don't flip-flop.
-#
-# ----------------
-#
-# This version optimizes by concatenating vertices for separate Triangle Fan
-# and Triangle Strip calls into a single long Triangle Strip to minimize calls.
-#
-# In the "pentagon cap" band at the top of the icos, points 2, 4, and 6 in the
-# above example are collapsed to the North Pole; at the bottom, points 1, 3,
-# and 5 are collapsed to the South Pole. This makes "null triangles" with one
-# zero-length edge, and the other two edges echoing one of the other triangle
-# edges (5,4,6 and 3,2,4 at the top, and 3,4,5 and 1,2,3 at the bottom.)
-#
-# In the subdivided caps, the icosahedron bands are split into horizontal
-# sub-bands. In the tapering-in sub-bands in the North cap, there is one less
-# vertex on the top edges of sub-bands, so we collapse the *LAST* triangle
-# there (e.g. 5,4,6 above) On the bottom edges of the South cap bands there
-# is one less vertex, so we collapse the *FIRST* triangle (e.g. 1,2,3.)
-#
-# Similarly, moving from the end of each sub-band to the beginning of the next
-# requires a *pair* of null triangles. We get that by simply concatenating the
-# wrapped triangle strips. We orient point pairs in the triangle strip from
-# south to north, so this works as long as we jog northward between (sub-)bands.
-# This is the reason we start the Triangle Strip with the South Pole band.
-#
-def getSphereTriStrips(level):
- steps = 2**level
- points = [] # Triangle Strip vertices o be returned.
-
- # Construct an icosahedron with two vertices at the North and South Poles,
- # +-1 on the Y axis, as you look toward the X-Y plane with the Z axis
- # pointing out at you. The "middle ring" vertices are all at the same
- # +-latitudes, on the intersection circles of the globe with a polar-axis
- # cylinder of the proper radius.
- #
- # The third "master vertex" of the icosahedron is placed on the X-Y plane,
- # which intersects the globe at the Greenwich Meridian (the semi-circle at
- # longitude 0, through Greenwich Observatory, 5 miles south-east of London.)
- #
- # The X (distance from the polar axis) and Y (height above the equatorial
- # plane) of the master vertex make a "golden rectangle", one unit high by
- # "phi" (1.6180339887498949) wide. We normalize this to put it on the
- # unit-radius sphere, and take the distance from the axis as the cylinder
- # radius used to generate the rest of the vertices of the two middle rings.
- #
- # Plotted on the globe, the master vertex (first vertex of the North ring)
- # is lat-long 31.72,0 due south of London in Africa, about 45 miles
- # south-southwest of Benoud, Algeria. The first vertex of the south ring is
- # rotated 1/10 of a circle east, at lat-long -31.72,36 in the south end of
- # the Indian Ocean, about 350 miles east-southeast of Durban, South Africa.
- #
- vert0 = norm(V(phi,1,0)) # Project the "master vertex" onto a unit sphere.
- cylRad = vert0[0] # Icos vertex distance from the Y axis.
- ringLat = atan2(vert0[1], vert0[0]) * degreesPerRadian # Latitude +-31.72 .
-
- # Basic triangle-strip icosahedron vertices. Start and end with the Poles.
- # Reflect the master vertex into the southern hemisphere and rotate 5 copies
- # to make the middle rings of 5 vertices at North and South latitudes.
- p2_5 = 2*pi / 5.0
- # Simplify indexing by replicating the Poles, so everything is in fives.
- icosRings = [ 5 * [V(0.0, -1.0, 0.0)], # South Pole.
-
- # South ring, first edge *centered on* the Greenwich Meridian.
- [V(cylRad*cos((i-.5)*p2_5), -vert0[1], cylRad*sin((i-.5)*p2_5))
- for i in range(5)],
-
- # North ring, first vertex *on* the Greenwich Meridian.
- [V(cylRad*cos(i*p2_5 ), vert0[1], cylRad*sin(i*p2_5))
- for i in range(5)],
-
- 5 * [V(0.0, 1.0, 0.0)] ] # North Pole.
-
-
- # Three bands, going from bottom to top (South to North.)
- for band in range(3):
- lowerRing = icosRings[band]
- upperRing = icosRings[band+1]
-
- # Subdivide bands into sub-bands. When level == 0, steps == 1,
- # subBand == 0, and we get just the icosahedron out. (Really!)
- for subBand in range(steps):
-
- # Account for the tapering-in at the poles, making less points on
- # one edge of a sub-band than there are on the other edge.
- botOffset = 0
- if band is 0: # South.
- botSteps = max(subBand, 1) # Don't divide by zero.
- topSteps = subBand + 1
- # Collapse the *first* triangle of south sub-band bottom edges.
- botOffset = -1
- elif band is 1: # Middle.
- botSteps = topSteps = steps
- else: # band is 2: North.
- botSteps = steps - subBand
- topSteps = max(steps - (subBand+1), 1)
- pass
- subBandSteps = max(botSteps, topSteps)
-
- # Do five segments, clockwise around the North Pole (East to West.)
- for seg in range(5):
- nextseg = (seg+1) % 5 # Wrap-around.
-
- # Interpolate ends of bottom & top edges of a sub-band segment.
- fractBot = float(subBand)/float(steps)
- fractTop = float(subBand+1)/float(steps)
- sbBotRight = fractBot * upperRing[seg] + \
- (1.0-fractBot) * lowerRing[seg]
- sbTopRight = fractTop * upperRing[seg] + \
- (1.0-fractTop) * lowerRing[seg]
- sbBotLeft = fractBot * upperRing[nextseg] + \
- (1.0-fractBot) * lowerRing[nextseg]
- sbTopLeft = fractTop * upperRing[nextseg] + \
- (1.0-fractTop) * lowerRing[nextseg]
-
- # Output the right end of the first segment of the sub-band.
- # We'll end up wrapping around to this same pair of points at
- # the left end of the last segment of the sub-band.
- if seg is 0:
- # Project verts from icosahedron faces onto the unit sphere.
- points += [norm(sbBotRight), norm(sbTopRight)]
-
- # Step across the sub-band edges from right to left,
- # stitching triangle pairs from their lower to upper edges.
- for step in range(1, subBandSteps+1):
-
- # Interpolate step point pairs along the sub-band edges.
- fractLower = float(step+botOffset)/float(botSteps)
- lower = fractLower * sbBotLeft + \
- (1.0-fractLower) * sbBotRight
- # Collapse the *last* triangle of north sub-band top edges.
- fractUpper = float(min(step, topSteps))/float(topSteps)
- upper = fractUpper * sbTopLeft + \
- (1.0-fractUpper) * sbTopRight
-
- # Output verts, projected from icos faces onto unit sphere.
- points += [norm(lower), norm(upper)]
-
- continue # step
- continue # seg
- continue # subBand
- continue # band
- return points
-
-def indexVerts(verts, close):
- """
- Compress a vertex array into an array of unique vertices, and an array of
- index values into the unique vertices. This is good for converting input
- for glDrawArrays into input for glDrawElements.
-
- The second arg is 'close', the distance between vertices which are close
- enough to be considered a single vertex.
-
- The return value is a pair of arrays (index, verts).
- """
- unique = []
- index = []
- for v in verts:
- for i in range(len(unique)):
- if vlen(unique[i] - v) < close:
- index += [i]
- break
- pass
- else:
- index += [len(unique)]
- unique += [v]
- pass
- continue
- return (index, unique)
-
-# ==
-
-def init_cyls():
- # generate two circles in space as 13-gons,
- # one rotated half a segment with respect to the other
- # these are used as cylinder ends [not quite true anymore, see comments just below]
- slices = 13
- circ1 = map((lambda n: n*2.0*pi/slices), range(slices+1))
- circ2 = map((lambda a: a+pi/slices), circ1)
- drawing_globals.drum0 = drum0 = map((lambda a: (cos(a), sin(a), 0.0)), circ1)
- drum1 = map((lambda a: (cos(a), sin(a), 1.0)), circ2)
- drum1n = map((lambda a: (cos(a), sin(a), 0.0)), circ2)
-
- # grantham 20051213 I finally decided the look of the oddly twisted
- # cylinder bonds was not pretty enough, so I made a "drum2" which is just
- # drum0 with a 1.0 Z coordinate, a la drum1.
- #bruce 060609: this apparently introduced the bug of the drum1 end-cap of a cylinder being "ragged"
- # (letting empty space show through), which I fixed by using drum2 for that cap rather than drum1.
- # drum1 is no longer used except as an intermediate value in the next few lines.
- drawing_globals.drum2 = drum2 = map((lambda a: (cos(a), sin(a), 1.0)), circ1)
-
- # This edge list zips up the "top" vertex and normal and then
- # the "bottom" vertex and normal.
- # Thus each tuple in the sequence would be (vtop, ntop, vbot, nbot) [grantham 20051213]
- # (bruce 051215 simplified the python usage in a way which should create the same list.)
- drawing_globals.cylinderEdges = zip(drum0, drum0, drum2, drum0)
-
- circle = zip(drum0[:-1],drum0[1:],drum1[:-1]) +\
- zip(drum1[:-1],drum0[1:],drum1[1:])
- circlen = zip(drum0[:-1],drum0[1:],drum1n[:-1]) +\
- zip(drum1n[:-1],drum0[1:],drum1n[1:])
-
- drawing_globals.cap0n = (0.0, 0.0, -1.0)
- drawing_globals.cap1n = (0.0, 0.0, 1.0)
- drum0.reverse()
- return
-init_cyls()
-
-def init_motors():
- ###data structure to construct the rotation sign for rotary motor
- numSeg = 20
- rotS = map((lambda n: pi/2+n*2.0*pi/numSeg), range(numSeg*3/4 + 1))
- zOffset = 0.005
- scaleS = 0.4
- drawing_globals.rotS0n = rotS0n = map(
- (lambda a: (scaleS*cos(a), scaleS*sin(a), 0.0 - zOffset)), rotS)
- drawing_globals.rotS1n = rotS1n = map(
- (lambda a: (scaleS*cos(a), scaleS*sin(a), 1.0 + zOffset)), rotS)
-
- ###Linear motor arrow sign data structure
- drawing_globals.halfHeight = 0.45
- drawing_globals.halfEdge = halfEdge = 3.0 * scaleS * sin(pi/numSeg)
-
- arrow0Vertices = [
- (rotS0n[-1][0]-halfEdge, rotS0n[-1][1], rotS0n[-1][2]),
- (rotS0n[-1][0]+halfEdge, rotS0n[-1][1], rotS0n[-1][2]),
- (rotS0n[-1][0], rotS0n[-1][1] + 2.0*halfEdge, rotS0n[-1][2])]
- arrow0Vertices.reverse()
- drawing_globals.arrow0Vertices = arrow0Vertices
-
- drawing_globals.arrow1Vertices = [
- (rotS1n[-1][0]-halfEdge, rotS1n[-1][1], rotS1n[-1][2]),
- (rotS1n[-1][0]+halfEdge, rotS1n[-1][1], rotS1n[-1][2]),
- (rotS1n[-1][0], rotS1n[-1][1] + 2.0*halfEdge, rotS1n[-1][2])]
-
- drawing_globals.halfEdge = halfEdge = 1.0/3.0 ##1.0/8.0
- drawing_globals.linearArrowVertices = [
- (0.0, -halfEdge, 0.0), (0.0, halfEdge, 0.0), (0.0, 0.0,2*halfEdge)]
-
- return
-init_motors()
-
-def init_diamond():
- # a chunk of diamond grid, to be tiled out in 3d
- sp0 = 0.0
- #bruce 051102 replaced 1.52 with this constant (1.544), re bug 900 (partial fix)
- sp1 = DIAMOND_BOND_LENGTH / sqrt(3.0)
- sp2 = 2.0*sp1
- sp3 = 3.0*sp1
- sp4 = 4.0*sp1
-
- digrid=[[[sp0, sp0, sp0], [sp1, sp1, sp1]], [[sp1, sp1, sp1], [sp2, sp2, sp0]],
- [[sp2, sp2, sp0], [sp3, sp3, sp1]], [[sp3, sp3, sp1], [sp4, sp4, sp0]],
- [[sp2, sp0, sp2], [sp3, sp1, sp3]], [[sp3, sp1, sp3], [sp4, sp2, sp2]],
- [[sp2, sp0, sp2], [sp1, sp1, sp1]], [[sp1, sp1, sp1], [sp0, sp2, sp2]],
- [[sp0, sp2, sp2], [sp1, sp3, sp3]], [[sp1, sp3, sp3], [sp2, sp4, sp2]],
- [[sp2, sp4, sp2], [sp3, sp3, sp1]], [[sp3, sp3, sp1], [sp4, sp2, sp2]],
- [[sp4, sp0, sp4], [sp3, sp1, sp3]], [[sp3, sp1, sp3], [sp2, sp2, sp4]],
- [[sp2, sp2, sp4], [sp1, sp3, sp3]], [[sp1, sp3, sp3], [sp0, sp4, sp4]]]
- drawing_globals.digrid = A(digrid)
- drawing_globals.DiGridSp = sp4
- return
-init_diamond()
-
-def init_cube():
- drawing_globals.cubeVertices = cubeVertices = [
- [-1.0, 1.0, -1.0], [-1.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 1.0, -1.0],
- [-1.0, -1.0, -1.0], [-1.0, -1.0, 1.0], [1.0, -1.0, 1.0], [1.0, -1.0, -1.0]]
-
- #bruce 051117: compute this rather than letting a subroutine hardcode it as
- # a redundant constant
- flatCubeVertices = []
- for threemore in cubeVertices:
- flatCubeVertices.extend(threemore)
- flatCubeVertices = list(flatCubeVertices) #k probably not needed
- drawing_globals.flatCubeVertices = flatCubeVertices
-
- if 1: # remove this when it works
- flatCubeVertices_hardcoded = [-1.0, 1.0, -1.0,
- -1.0, 1.0, 1.0,
- 1.0, 1.0, 1.0,
- 1.0, 1.0, -1.0,
- -1.0, -1.0, -1.0,
- -1.0, -1.0, 1.0,
- 1.0, -1.0, 1.0,
- 1.0, -1.0, -1.0]
- assert flatCubeVertices == flatCubeVertices_hardcoded
-
- sq3 = sqrt(3.0)/3.0
- drawing_globals.cubeNormals = [
- [-sq3, sq3, -sq3], [-sq3, sq3, sq3],
- [sq3, sq3, sq3], [sq3, sq3, -sq3],
- [-sq3, -sq3, -sq3], [-sq3, -sq3, sq3],
- [sq3, -sq3, sq3], [sq3, -sq3, -sq3]]
- drawing_globals.cubeIndices = [
- [0, 1, 2, 3], [0, 4, 5, 1], [1, 5, 6, 2],
- [2, 6, 7, 3], [0, 3, 7, 4], [4, 7, 6, 5]]
-
- return
-init_cube()
-
-
-# Some variables used by the Lonsdaleite lattice construction.
-ux = 1.262; uy = 0.729; dz = 0.5153; ul = 1.544
-drawing_globals.XLen = XLen = 2*ux
-drawing_globals.YLen = YLen = 6*uy
-drawing_globals.ZLen = ZLen = 2*(ul + dz)
-
-def _makeLonsCell():
- """Data structure to construct a Lonsdaleite lattice cell"""
- lVp = [# 2 outward vertices
- [-ux, -2*uy, 0.0], [0.0, uy, 0.0],
- # Layer 1: 7 vertices
- [ux, -2*uy, ul], [-ux, -2*uy, ul], [0.0, uy, ul],
- [ux, 2*uy, ul+dz], [-ux, 2*uy, ul+dz], [0.0, -uy, ul+dz],
- [-ux, 4*uy, ul],
- # Layer 2: 7 vertices
- [ux, -2*uy, 2*(ul+dz)], [-ux, -2*uy, 2*(ul+dz)], [0.0, uy, 2*(ul+dz)],
- [ux, 2*uy, 2*ul+dz], [-ux, 2*uy, 2*ul+dz], [0.0, -uy, 2*ul+dz],
- [-ux, 4*uy, 2*(ul+dz)]
- ]
-
- res = [ # 2 outward vertical edges for layer 1
- [lVp[0], lVp[3]], [lVp[1], lVp[4]],
- # 6 xy Edges for layer 1
- [lVp[2], lVp[7]], [lVp[3], lVp[7]], [lVp[7], lVp[4]],
- [lVp[4], lVp[6]], [lVp[4], lVp[5]],
- [lVp[6], lVp[8]],
- # 2 outward vertical edges for layer 2
- [lVp[14], lVp[7]], [lVp[13], lVp[6]],
- # 6 xy Edges for layer 2
- [lVp[14], lVp[9]], [lVp[14], lVp[10]], [lVp[14], lVp[11]],
- [lVp[11], lVp[13]], [lVp[11], lVp[12]],
- [lVp[13], lVp[15]]
- ]
- return res
-drawing_globals.lonsEdges = _makeLonsCell()
-
-#================================================================ glprefs.py
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-glprefs.py - Attributes from drawing-related prefs stored in the prefs db cache.
-
-@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-
-import graphics.drawing.drawing_globals as drawing_globals
-
-import foundation.env as env #bruce 051126
-
-if EndUser.getAlternateSourcePath() != None:
- sys.path.append(os.path.join( EndUser.getAlternateSourcePath(), "experimental/pyrex-opengl"))
-else:
- sys.path.append("./experimental/pyrex-opengl")
-
-binPath = os.path.normpath(os.path.dirname(os.path.abspath(sys.argv[0])) + '/../bin')
-if binPath not in sys.path:
- sys.path.append(binPath)
-
-try:
- import quux
- drawing_globals.quux_module_import_succeeded = True
- if "experimental" in os.path.dirname(quux.__file__):
- # should never happen for end users, but if it does we want to print the warning
- if env.debug() or not EndUser.enableDeveloperFeatures():
- print "debug: fyi: Using experimental version of C rendering code:", quux.__file__
-except:
- drawing_globals.use_c_renderer = False
- drawing_globals.quux_module_import_succeeded = False
- if env.debug(): #bruce 060323 added condition
- print "WARNING: unable to import C rendering code (quux module). Only Python rendering will be available."
- pass
-
-# grantham 20051118; revised by bruce 051126
-class glprefs:
-
- def __init__(self):
-## self.override_material_specular = None
-## # set to 4-element sequence to override material specular component
-## self.override_shininess = None
-## # if exists, overrides shininess
-## self.override_light_specular = None
-## # set to 4-element sequence to override light specular component
- import foundation.preferences as preferences #bruce 051126 KLUGE: make sure env.prefs exists (could use cleanup, but that's not trivial)
- self.update()
-
- def update(self): #bruce 051126 added this method
- """Update attributes from current drawing-related prefs stored in prefs db cache.
- This should be called at the start of each complete redraw, or whenever the user changes these global prefs values
- (whichever is more convenient).
- (Note: When this is called during redraw, its prefs db accesses (like any others)
- record those prefs as potentially affecting what should be drawn, so that subsequent
- changes to those prefs values cause an automatic gl_update.)
- Using these attributes in drawing code (rather than directly accessing prefs db cache)
- is desirable for efficiency, since direct access to prefs db cache is a bit slow.
- (Our drawing code still does that in other places -- those might also benefit from this system,
- though this will soon be moot when low-level drawing code gets rewritten in C.)
- """
- self.enable_specular_highlights = not not env.prefs[
- material_specular_highlights_prefs_key] # boolean
- if self.enable_specular_highlights:
- self.override_light_specular = None # used in glpane
- # self.specular_shininess: float; shininess exponent for all specular highlights
- self.specular_shininess = float(env.prefs[material_specular_shininess_prefs_key])
- # self.specular_whiteness: float; whiteness for all material specular colors
- self.specular_whiteness = float(env.prefs[material_specular_finish_prefs_key])
- # self.specular_brightness: float; for all material specular colors
- self.specular_brightness = float(env.prefs[material_specular_brightness_prefs_key])
- else:
- self.override_light_specular = (0.0, 0.0, 0.0, 0.0) # used in glpane
- # Set these to reasonable values, though these attributes are presumably never used in this case.
- # Don't access the prefs db in this case, since that would cause UI prefs changes to do unnecessary gl_updates.
- # (If we ever add a scenegraph node which can enable specular highlights but use outside values for these parameters,
- # then to make it work correctly we'll need to revise this code.)
- self.specular_shininess = 20.0
- self.specular_whiteness = 1.0
- self.specular_brightness = 1.0
-
- drawing_globals.allow_color_sorting = env.prefs.get(
- drawing_globals.allow_color_sorting_prefs_key,
- drawing_globals.allow_color_sorting_default)
- drawing_globals.use_color_sorted_dls = env.prefs.get(
- drawing_globals.use_color_sorted_dls_prefs_key,
- drawing_globals.use_color_sorted_dls_default)
- drawing_globals.use_color_sorted_vbos = env.prefs.get(
- drawing_globals.use_color_sorted_vbos_prefs_key,
- drawing_globals.use_color_sorted_vbos_default)
- drawing_globals.use_drawing_variant = env.prefs.get(
- drawing_globals.use_drawing_variant_prefs_key,
- drawing_globals.use_drawing_variant_default)
- drawing_globals.use_c_renderer = (
- drawing_globals.quux_module_import_succeeded and
- env.prefs.get(drawing_globals.use_c_renderer_prefs_key,
- drawing_globals.use_c_renderer_default))
-
- if drawing_globals.use_c_renderer:
- quux.shapeRendererSetMaterialParameters(self.specular_whiteness,
- self.specular_brightness,
- self.specular_shininess);
- return
-
- def materialprefs_summary(self): #bruce 051126
- """
- Return a Python data object summarizing our prefs which affect chunk display lists,
- so that memoized display lists should become invalid (due to changes in this object)
- if and only if this value becomes different.
- """
- res = (self.enable_specular_highlights,)
- if self.enable_specular_highlights:
- res = res + ( self.specular_shininess,
- self.specular_whiteness,
- self.specular_brightness )
-
- # grantham 20060314
- res += (drawing_globals.quux_module_import_succeeded and
- env.prefs.get(drawing_globals.use_c_renderer_prefs_key,
- drawing_globals.use_c_renderer_default),)
-
- # grantham 20060314 - Not too sure this next addition is
- # really necessary, but it seems to me that for testing
- # purposes it is important to rebuild display lists if the
- # color sorting pref is changed.
- res += (env.prefs.get(drawing_globals.allow_color_sorting_prefs_key,
- drawing_globals.allow_color_sorting_default),)
- res += (env.prefs.get(drawing_globals.use_color_sorted_dls_prefs_key,
- drawing_globals.use_color_sorted_dls_default),)
- res += (env.prefs.get(drawing_globals.use_color_sorted_vbos_prefs_key,
- drawing_globals.use_color_sorted_vbos_default),)
- res += (env.prefs.get(drawing_globals.use_drawing_variant_prefs_key,
- drawing_globals.use_drawing_variant_default),)
- return res
-
- pass # end of class glprefs
-
-drawing_globals.glprefs = glprefs()
-
-#================================================================ gl_lighting.py
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-gl_lighting.py - Lights, materials, and special effects.
-
-@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-import graphics.drawing.drawing_globals as drawing_globals
-
-# ==
-# Helper functions for use by GL widgets wanting to set up lighting.
-
-#bruce 051212 made these from the code in GLPane which now calls them, so they can also be used in ThumbView
-
-# Default lights tuples (format is as used by setup_standard_lights; perhaps also assumed by other code).
-#grantham 20051121 comment - Light should probably be a class. Right now,
-# changing the behavior of lights requires changing a bunch of
-# ambiguous tuples and tuple packing/unpacking.
-#bruce 051212 moved this here from GLPane; maybe it belongs in prefs_constants instead?
-# Note: I'm not sure whether this is the only place where this data is coded.
-_default_lights = ((white, 0.1, 0.5, 0.5, -50, 70, 30, True),
- (white, 0.1, 0.5, 0.5, -20, 20, 20, True),
- (white, 0.1, 0.1, 0.1, 0, 0, 100, False))
- # for each of 3 lights, this stores ((r,g,b),a,d,s,x,y,z,e)
- # revised format to include s,x,y,z. Mark 051202.
- # revised format to include c (r,g,b). Mark 051204.
- # Be sure to keep the lightColor prefs keys and _lights colors synchronized.
- # Mark 051204. [a comment from when this was located in GLPane]
-
-def glprefs_data_used_by_setup_standard_lights( glprefs = None): #bruce 051212
- """
- Return a summary of the glprefs data used by setup_standard_lights,
- for use in later deciding whether it needs to be called again due to changes in glprefs.
- """
- if glprefs is None:
- glprefs = drawing_globals.glprefs
- pass
- # This must be kept in sync with what's used by setup_standard_lights() .
- return (glprefs.override_light_specular,)
-
-def setup_standard_lights( lights, glprefs = None):
- """
- Set up lighting in the current GL context using the supplied "lights" tuple (in the format used by GLPane's prefs)
- and the optional glprefs object (which defaults to drawing_globals.glprefs ).
- Note: the glprefs data used can be summarized by the related function glprefs_data_used_by_setup_standard_lights (which see).
- Warning: has side effects on GL_MODELVIEW matrix.
- Note: If GL_NORMALIZE needs to be enabled, callers should do that themselves,
- since this depends on what they will draw and might slow down drawing.
- """
- #e not sure whether projection matrix also needs to be reset here [bruce 051212]
- glMatrixMode(GL_MODELVIEW)
- glLoadIdentity()
-
- if glprefs is None:
- glprefs = drawing_globals.glprefs
- # note: whatever glprefs data is used below must also be present
- # in the return value of glprefs_data_used_by_setup_standard_lights(). [bruce 051212]
-
- try:
- # new code
- (((r0,g0,b0),a0,d0,s0,x0,y0,z0,e0), \
- ( (r1,g1,b1),a1,d1,s1,x1,y1,z1,e1), \
- ( (r2,g2,b2),a2,d2,s2,x2,y2,z2,e2)) = lights
-
- # Great place for a print statement for debugging lights. Keep this. Mark 051204. [revised by bruce 051212]
- #print "-------------------------------------------------------------"
- #print "setup_standard_lights: lights[0]=", lights[0]
- #print "setup_standard_lights: lights[1]=", lights[1]
- #print "setup_standard_lights: lights[2]=", lights[2]
-
- glLightfv(GL_LIGHT0, GL_POSITION, (x0, y0, z0, 0))
- glLightfv(GL_LIGHT0, GL_AMBIENT, (r0*a0, g0*a0, b0*a0, 1.0))
- glLightfv(GL_LIGHT0, GL_DIFFUSE, (r0*d0, g0*d0, b0*d0, 1.0))
- if glprefs.override_light_specular is not None:
- glLightfv(GL_LIGHT0, GL_SPECULAR, glprefs.override_light_specular)
- else:
- # grantham 20051121 - this should be a component on its own
- # not replicating the diffuse color.
- # Added specular (s0) as its own component. mark 051202.
- glLightfv(GL_LIGHT0, GL_SPECULAR, (r0*s0, g0*s0, b0*s0, 1.0))
- glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0)
-
- glLightfv(GL_LIGHT1, GL_POSITION, (x1, y1, z1, 0))
- glLightfv(GL_LIGHT1, GL_AMBIENT, (r1*a1, g1*a1, b1*a1, 1.0))
- glLightfv(GL_LIGHT1, GL_DIFFUSE, (r1*d1, g1*d1, b1*d1, 1.0))
- if glprefs.override_light_specular is not None:
- glLightfv(GL_LIGHT1, GL_SPECULAR, glprefs.override_light_specular)
- else:
- glLightfv(GL_LIGHT1, GL_SPECULAR, (r1*s1, g1*s1, b1*s1, 1.0))
- glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0)
-
- glLightfv(GL_LIGHT2, GL_POSITION, (x2, y2, z2, 0))
- glLightfv(GL_LIGHT2, GL_AMBIENT, (r2*a2, g2*a2, b2*a2, 1.0))
- glLightfv(GL_LIGHT2, GL_DIFFUSE, (r2*d2, g2*d2, b2*d2, 1.0))
- if glprefs.override_light_specular is not None:
- glLightfv(GL_LIGHT2, GL_SPECULAR, glprefs.override_light_specular)
- else:
- glLightfv(GL_LIGHT2, GL_SPECULAR, (r2*s2, g2*s2, b2*s2, 1.0))
- glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, 1.0)
-
- glEnable(GL_LIGHTING)
-
- if e0:
- glEnable(GL_LIGHT0)
- else:
- glDisable(GL_LIGHT0)
-
- if e1:
- glEnable(GL_LIGHT1)
- else:
- glDisable(GL_LIGHT1)
-
- if e2:
- glEnable(GL_LIGHT2)
- else:
- glDisable(GL_LIGHT2)
- except:
- debug.print_compact_traceback("bug (worked around): setup_standard_lights reverting to old code, because: ")
- # old code, used only to set up some sort of workable lighting in case of bugs
- # (this is not necessarily using the same values as _default_lights; doesn't matter since never used unless there are bugs)
- glLightfv(GL_LIGHT0, GL_POSITION, (-50, 70, 30, 0))
- glLightfv(GL_LIGHT0, GL_AMBIENT, (0.3, 0.3, 0.3, 1.0))
- glLightfv(GL_LIGHT0, GL_DIFFUSE, (0.8, 0.8, 0.8, 1.0))
- glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0)
-
- glLightfv(GL_LIGHT1, GL_POSITION, (-20, 20, 20, 0))
- glLightfv(GL_LIGHT1, GL_AMBIENT, (0.4, 0.4, 0.4, 1.0))
- glLightfv(GL_LIGHT1, GL_DIFFUSE, (0.4, 0.4, 0.4, 1.0))
- glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0)
-
- glLightfv(GL_LIGHT2, GL_POSITION, (0, 0, 100, 0))
- glLightfv(GL_LIGHT2, GL_AMBIENT, (1.0, 1.0, 1.0, 1.0))
- glLightfv(GL_LIGHT2, GL_DIFFUSE, (1.0, 1.0, 1.0, 1.0))
- glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, 1.0)
-
- glEnable(GL_LIGHTING)
-
- glEnable(GL_LIGHT0)
- glEnable(GL_LIGHT1)
- glDisable(GL_LIGHT2)
- return # from setup_standard_lights
-
-# ==
-
-def setup_fog(fog_start, fog_end, fog_color):
-
- glFog(GL_FOG_MODE, GL_LINEAR)
- glFog(GL_FOG_START, fog_start)
- glFog(GL_FOG_END, fog_end)
- if len(fog_color) == 3:
- fog_color = (fog_color[0], fog_color[1], fog_color[2], 1.0)
- glFogv(GL_FOG_COLOR, fog_color) # piotr 080515
-
-def enable_fog():
- glEnable(GL_FOG)
-
-def disable_fog():
- glDisable(GL_FOG)
-
-# ==
-
-def apply_material(color): # grantham 20051121, renamed 20051201; revised by bruce 051126, 051203 (added specular_brightness), 051215
- """
- Set OpenGL material parameters based on the given color (length 3 or 4) and
- the material-related prefs values in drawing_globals.glprefs.
- """
-
- #bruce 051215: make sure color is a tuple, and has length exactly 4, for all uses inside this function,
- # assuming callers pass sequences of length 3 or 4. Needed because glMaterial requires four-component
- # vector and PyOpenGL doesn't check. [If this is useful elsewhere, we can split it into a separate function.]
- color = tuple(color)
- if len(color) == 3:
- color = color + (1.0,) # usual case
- elif len(color) != 4:
- # should never happen; if it does, this assert will always fail
- assert len(color) in [3,4], "color tuples must have length 3 or 4, unlike %r" % (color,)
-
- glColor4fv(color) # For drawing lines with lighting disabled.
-
- if not drawing_globals.glprefs.enable_specular_highlights:
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color)
- # glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (0,0,0,1))
- return
-
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color)
-
- whiteness = drawing_globals.glprefs.specular_whiteness
- brightness = drawing_globals.glprefs.specular_brightness
- if whiteness == 1.0:
- specular = (1.0, 1.0, 1.0, 1.0) # optimization
- else:
- if whiteness == 0.0:
- specular = color # optimization
- else:
- # assume color[3] (alpha) is not passed or is always 1.0
- c1 = 1.0 - whiteness
- specular = ( c1 * color[0] + whiteness, c1 * color[1] + whiteness, c1 * color[2] + whiteness, 1.0 )
- if brightness != 1.0:
- specular = ( specular[0] * brightness, specular[1] * brightness, specular[2] * brightness, 1.0 )
- #e could optimize by merging this with above 3 cases (or, of course, by doing it in C, which we'll do eventually)
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular)
-
- glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS,
- drawing_globals.glprefs.specular_shininess)
- return
-
-# ==
-
-#russ 080515: We should find a better place for this!
-def get_gl_info_string(glpane): # grantham 20051129
- """Return a string containing some useful information about the OpenGL implementation.
- Use the GL context from the given QGLWidget glpane (by calling glpane.makeCurrent()).
- """
-
- glpane.makeCurrent() #bruce 070308 added glpane arg and makeCurrent call
-
- gl_info_string = ''
-
- gl_info_string += 'GL_VENDOR : "%s"\n' % glGetString(GL_VENDOR)
- gl_info_string += 'GL_VERSION : "%s"\n' % glGetString(GL_VERSION)
- gl_info_string += 'GL_RENDERER : "%s"\n' % glGetString(GL_RENDERER)
- gl_info_string += 'GL_EXTENSIONS : "%s"\n' % glGetString(GL_EXTENSIONS)
-
- from utilities.debug_prefs import debug_pref, Choice_boolean_False
- if debug_pref("get_gl_info_string call glAreTexturesResident?", Choice_boolean_False):
- # Give a practical indication of how much video memory is available.
- # Should also do this with VBOs.
-
- # I'm pretty sure this code is right, but PyOpenGL seg faults in
- # glAreTexturesResident, so it's disabled until I can figure that
- # out. [grantham] [bruce 070308 added the debug_pref]
-
- all_tex_in = True
- tex_bytes = '\0' * (512 * 512 * 4)
- tex_names = []
- tex_count = 0
- tex_names = glGenTextures(1024)
- glEnable(GL_TEXTURE_2D)
- while all_tex_in:
- glBindTexture(GL_TEXTURE_2D, tex_names[tex_count])
- gluBuild2DMipmaps(GL_TEXTURE_2D, 4, 512, 512, GL_RGBA,
- GL_UNSIGNED_BYTE, tex_bytes)
- tex_count += 1
-
- glTexCoord2f(0.0, 0.0)
- glBegin(GL_QUADS)
- glVertex2f(0.0, 0.0)
- glVertex2f(1.0, 0.0)
- glVertex2f(1.0, 1.0)
- glVertex2f(0.0, 1.0)
- glEnd()
- glFinish()
-
- residences = glAreTexturesResident(tex_names[:tex_count])
- all_tex_in = reduce(lambda a,b: a and b, residences)
- # bruce 070308 sees this exception from this line:
- # TypeError: reduce() arg 2 must support iteration
-
- glDisable(GL_TEXTURE_2D)
- glDeleteTextures(tex_names)
-
- gl_info_string += "Could create %d 512x512 RGBA resident textures\n", tex_count
- return gl_info_string
-
-#================================================================ gl_buffers.py
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-gl_buffers.py - OpenGL data buffer objects.
-
-@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-
-# Vertex Buffer Object (VBO) and Index Buffer Object (IBO) support.
-# For docs see http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml .
-
-# Notice that the ARB-suffixed versions of the OpenGL calls are used here.
-# They're the ones with PyConvert ctypes wrappers, see: (the incomprehensible)
-# http://pyopengl.sourceforge.net/ctypes/pydoc/OpenGL.GL.ARB.vertex_buffer_object.html
-# The sources will do you more good. Also see "Array Handling Routines" here:
-# http://pyopengl.sourceforge.net/documentation/opengl_diffs.html
-#
-from OpenGL.GL.ARB.vertex_buffer_object import glGenBuffersARB
-from OpenGL.GL.ARB.vertex_buffer_object import glDeleteBuffersARB
-# Patched versions.
-from graphics.drawing.vbo_patch import glBufferDataARB, glBufferSubDataARB
-
-from OpenGL.raw.GL.ARB.vertex_buffer_object import glBindBufferARB # Unwrappered.
-
-class GLBufferObject(object):
- """
- Buffer data in the graphics card's RAM space.
-
- Useful man pages for glBind, glBufferData, etc. for OpenGL 2.1 are at:
- http://www.opengl.org/sdk/docs/man
- PyOpenGL versions are at:
- http://pyopengl.sourceforge.net/ctypes/pydoc/OpenGL.html
-
- 'target' is GL_ARRAY_BUFFER_ARB for vertex/normal buffers (VBO's), and
- GL_ELEMENT_ARRAY_BUFFER_ARB for index buffers (IBO's.)
-
- 'data' is a numpy.array, with dtype=numpy.<datatype> .
-
- 'usage' is one of the hint constants, like GL_STATIC_DRAW.
- """
-
- def __init__(self, target, data, usage):
- self.buffer = glGenBuffersARB(1) # Returns a numpy.ndarray for > 1.
- self.target = target
-
- self.bind()
- self.size = len(data)
-
- # Push the data over to Graphics card RAM.
- glBufferDataARB(target, data, usage)
-
- self.unbind()
- return
-
- def __del__(self):
- """
- Delete a GLBufferObject. We don't expect that there will be a lot of
- deleting of GLBufferObjects, but don't want them to sit on a lot of graphics
- card RAM if we did.
- """
-
- # Since may be too late to clean up buffer objects through the Graphics
- # Context while exiting, we trust that OpenGL or the device driver will
- # deallocate the graphics card RAM when the Python process exits.
- try:
- glDeleteBuffersARB(1, [self.buffer])
- except:
- ##print "Exception in glDeleteBuffersARB."
- pass
- return
-
- def bind(self):
- """
- Have to bind a particular buffer to its target to fill or draw from it.
- Don't forget to unbind() it!
- """
- glBindBufferARB(self.target, self.buffer)
- return
-
- def unbind(self):
- """
- Unbind a buffer object from its target after use.
- Failure to do this can kill Python on some graphics platforms!
- """
- glBindBufferARB(self.target, 0)
- return
-
- pass # End of class GLBufferObject.
-
-#================================================================ CS_workers.py
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-CS_workers.py - Drawing functions for primitives drawn by the ColorSorter.
-
-@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-
-import graphics.drawing.drawing_globals as drawing_globals
-
-try:
- from OpenGL.GLE import glePolyCone
-except:
- print "GLE module can't be imported. Now trying _GLE"
- from OpenGL._GLE import glePolyCone
-
-### Substitute this for drawsphere_worker to test drawing a lot of spheres.
-def drawsphere_worker_loop(params):
- (pos, radius, detailLevel) = params
- for x in range(100): ## 500
- for y in range(100):
- newpos = pos + (x+x/10+x/100) * V(1, 0, 0) + (y+y/10+y/100) * V(0, 1, 0)
- drawsphere_worker((newpos, radius, detailLevel))
- continue
- continue
- return
-
-def drawsphere_worker(params):
- """Draw a sphere. Receive parameters through a sequence so that this
- function and its parameters can be passed to another function for
- deferment. Right now this is only ColorSorter.schedule (see below)"""
-
- (pos, radius, detailLevel) = params
-
- vboLevel = drawing_globals.use_drawing_variant
-
- glPushMatrix()
- glTranslatef(pos[0], pos[1], pos[2])
- glScale(radius,radius,radius)
-
- if vboLevel is 0:
- glCallList(drawing_globals.sphereList[detailLevel])
- else: # Array variants.
- glEnableClientState(GL_VERTEX_ARRAY)
- glEnableClientState(GL_NORMAL_ARRAY)
-
- size = len(drawing_globals.sphereArrays[detailLevel])
- GLIndexType = drawing_globals.sphereGLIndexTypes[detailLevel]
-
- if vboLevel is 1: # DrawArrays from CPU RAM.
- verts = drawing_globals.sphereCArrays[detailLevel]
- glVertexPointer(3, GL_FLOAT, 0, verts)
- glNormalPointer(GL_FLOAT, 0, verts)
- glDrawArrays(GL_TRIANGLE_STRIP, 0, size)
-
- elif vboLevel is 2: # DrawElements from CPU RAM.
- verts = drawing_globals.sphereCElements[detailLevel][1]
- glVertexPointer(3, GL_FLOAT, 0, verts)
- glNormalPointer(GL_FLOAT, 0, verts)
- # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug.
- index = drawing_globals.sphereElements[detailLevel][0]
- glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index)
-
- elif vboLevel is 3: # DrawArrays from graphics RAM VBO.
- vbo = drawing_globals.sphereArrayVBOs[detailLevel]
- vbo.bind()
- glVertexPointer(3, GL_FLOAT, 0, None)
- glNormalPointer(GL_FLOAT, 0, None)
- glDrawArrays(GL_TRIANGLE_STRIP, 0, vbo.size)
- vbo.unbind()
-
- elif vboLevel is 4: # DrawElements from index in CPU RAM, verts in VBO.
- vbo = drawing_globals.sphereElementVBOs[detailLevel][1]
- vbo.bind() # Vertex and normal data comes from the vbo.
- glVertexPointer(3, GL_FLOAT, 0, None)
- glNormalPointer(GL_FLOAT, 0, None)
- # Can't use the C index in sphereCElements yet, fatal PyOpenGL bug.
- index = drawing_globals.sphereElements[detailLevel][0]
- glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, index)
- vbo.unbind()
-
- elif vboLevel is 5: # VBO/IBO buffered DrawElements from graphics RAM.
- (ibo, vbo) = drawing_globals.sphereElementVBOs[detailLevel]
- vbo.bind() # Vertex and normal data comes from the vbo.
- glVertexPointer(3, GL_FLOAT, 0, None)
- glNormalPointer(GL_FLOAT, 0, None)
- ibo.bind() # Index data comes from the ibo.
- glDrawElements(GL_TRIANGLE_STRIP, size, GLIndexType, None)
- vbo.unbind()
- ibo.unbind()
- pass
-
- glDisableClientState(GL_VERTEX_ARRAY)
- glDisableClientState(GL_NORMAL_ARRAY)
- pass
-
- glPopMatrix()
- return
-
-def drawwiresphere_worker(params):
- """
- Draw a wireframe sphere. Receive parameters through a sequence so that this
- function and its parameters can be passed to another function for
- deferment. Right now this is only ColorSorter.schedule (see below)
- """
-
- (color, pos, radius, detailLevel) = params
- ## assert detailLevel == 1 # true, but leave out for speed
- from utilities.debug_prefs import debug_pref, Choice_boolean_True
- newway = debug_pref("new wirespheres?", Choice_boolean_True) #bruce 060415 experiment, re iMac G4 wiresphere bug; fixes it!
- oldway = not newway
- # These objects want a constant line color even if they are selected or highlighted.
- glColor3fv(color)
- glDisable(GL_LIGHTING)
- if oldway:
- glPolygonMode(GL_FRONT, GL_LINE)
- glPushMatrix()
- glTranslatef(pos[0], pos[1], pos[2])
- glScale(radius,radius,radius)
- if oldway:
- glCallList(drawing_globals.sphereList[detailLevel])
- else:
- glCallList(drawing_globals.wiresphere1list)
- glEnable(GL_LIGHTING)
- glPopMatrix()
- if oldway:
- glPolygonMode(GL_FRONT, GL_FILL)
- return
-
-def drawcylinder_worker(params):
- """
- Draw a cylinder. Receive parameters through a sequence so that this
- function and its parameters can be passed to another function for
- deferment. Right now this is only ColorSorter.schedule (see below)
-
- WARNING: our circular cross-section is approximated by a 13-gon
- whose alignment around the axis is chosen arbitrary, in a way
- which depends on the direction of the axis; negating the axis usually
- causes a different alignment of that 13-gon. This effect can cause
- visual bugs when drawing one cylinder over an identical or slightly
- smaller one (e.g. when highlighting a bond), unless the axes are kept
- parallel as opposed to antiparallel.
- """
-
- (pos1, pos2, radius, capped) = params
-
- glPushMatrix()
- vec = pos2-pos1
- axis = norm(vec)
- glTranslatef(pos1[0], pos1[1], pos1[2])
-
- ##Huaicai 1/17/05: To avoid rotate around (0, 0, 0), which causes
- ## display problem on some platforms
- angle = -acos(axis[2])*180.0/pi
- if (axis[2]*axis[2] >= 1.0):
- glRotate(angle, 0.0, 1.0, 0.0)
- else:
- glRotate(angle, axis[1], -axis[0], 0.0)
-
- glScale(radius,radius,Numeric.dot(vec,vec)**.5)
- glCallList(drawing_globals.CylList)
- if capped: glCallList(drawing_globals.CapList)
-
- glPopMatrix()
-
- return
-
-def drawpolycone_worker(params):
- """
- Draw a polycone. Receive parameters through a sequence so that this
- function and its parameters can be passed to another function for
- deferment. Right now this is only ColorSorter.schedule (see below)
- """
- (pos_array, rad_array) = params
- glePolyCone(pos_array, None, rad_array)
- return
-
-def drawpolycone_multicolor_worker(params):
- """
- Draw a polycone. Receive parameters through a sequence so that this
- function and its parameters can be passed to another function for
- deferment. Right now this is only ColorSorter.schedule (see below)
- piotr 080311: this variant accepts a color array as an additional parameter
- """
- (pos_array, color_array, rad_array) = params
- glEnable(GL_COLOR_MATERIAL) # have to enable GL_COLOR_MATERIAL for
- # the GLE function
- glPushAttrib(GL_CURRENT_BIT) # store current attributes in case glePolyCone
- # modifies the (e.g. current color)
- # piotr 080411
- glePolyCone(pos_array, color_array, rad_array)
- glPopAttrib() # This fixes the 'disappearing cylinder' bug
- # glPopAttrib doesn't take any arguments
- # piotr 080415
- glDisable(GL_COLOR_MATERIAL)
- return
-
-def drawsurface_worker(params):
- """Draw a surface. Receive parameters through a sequence so that this
- function and its parameters can be passed to another function for
- deferment. Right now this is only ColorSorter.schedule (see below)"""
-
- (pos, radius, tm, nm) = params
- glPushMatrix()
- glTranslatef(pos[0], pos[1], pos[2])
- glScale(radius,radius,radius)
- renderSurface(tm, nm)
- glPopMatrix()
- return
-
-def drawline_worker(params):
- """
- Draw a line. Receive parameters through a sequence so that this
- function and its parameters can be passed to another function for
- deferment. Right now this is only ColorSorter.schedule (see below)
- """
- (endpt1, endpt2, dashEnabled, stipleFactor, width, isSmooth) = params
-
- ###glDisable(GL_LIGHTING)
- ###glColor3fv(color)
- if dashEnabled:
- glLineStipple(stipleFactor, 0xAAAA)
- glEnable(GL_LINE_STIPPLE)
- if width != 1:
- glLineWidth(width)
- if isSmooth:
- glEnable(GL_LINE_SMOOTH)
- glBegin(GL_LINES)
- glVertex(endpt1[0], endpt1[1], endpt1[2])
- glVertex(endpt2[0], endpt2[1], endpt2[2])
- glEnd()
- if isSmooth:
- glDisable(GL_LINE_SMOOTH)
- if width != 1:
- glLineWidth(1.0) # restore default state
- if dashEnabled:
- glDisable(GL_LINE_STIPPLE)
- ###glEnable(GL_LIGHTING)
- return
-
-#================================================================ CS_ShapeList.py
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-CS_ShapeList.py - The C++ ColorSorter's arrays of primitives to draw.
-
-Does some memoization as a speedup.
-
-@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-
-
-class ShapeList_inplace:
-
- """
- Records sphere and cylinder data and invokes it through the native C++
- rendering system.
-
- This has the benefit over ShapeList that shapes aren't first stored in
- lots of Python lists, and then turned into lots of Numeric arrays.
- Instead, it stores directly in a list of fixed-size Numeric arrays.
- It shows some speedup, but not a lot. And tons of memory is being
- used. I'm not sure where. -grantham
-
- """
-
- __author__ = "grantham@plunk.org"
-
- _blocking = 512 # balance between memory zeroing and drawing efficiency
-
- def __init__(self):
-
- #
- # Lists of lists, each list containing a Numeric array and the
- # number of objects in that array. E.g. Each element in
- # sphere is [l, n], where l is array((m, 9), 'f'), n is the
- # number of valid 9 element slices in l that represent
- # spheres, and m is equal to or more than n+1.
- #
- self.spheres = []
- self.cylinders = []
-
- # If this is true, disallow future adds.
- self.petrified = False
-
-
- def draw(self):
-
- """
- Draw all the objects represented in this shape list.
- """
-
- for (spheres, count) in self.spheres:
- quux.shapeRendererDrawSpheresIlvd(count, spheres)
- for (cylinders, count) in self.cylinders:
- quux.shapeRendererDrawCylindersIlvd(count, cylinders)
-
-
- def add_sphere(self, color4, pos, radius, name = 0):
- """
- Add a sphere to this shape list.
-
- "color4" must have 4 elements. "name" is the GL selection name.
- """
-
- if self.petrified:
- raise ValueError, "Tried to add a sphere to a petrified ShapeList_inplace"
-
- # struct Sphere {
- # float m_color[4];
- # float m_nameUInt;
- # float m_center[3];
- # float m_radius;
- # };
-
- if len(self.spheres) == 0 or self.spheres[-1][1] == ShapeList_inplace._blocking:
- # size of struct Sphere in floats is 9
- block = Numeric.zeros((ShapeList_inplace._blocking, 9), 'f')
- self.spheres.append([block, 0])
-
- (block, count) = self.spheres[-1]
-
- block[count] = (\
- color4[0], color4[1], color4[2], color4[3],
- float(name),
- pos[0], pos[1], pos[2],
- radius)
-
- self.spheres[-1][1] += 1
-
-
- def add_cylinder(self, color4, pos1, pos2, radius, name = 0, capped=0):
- """
- Add a cylinder to this shape list.
-
- "color4" must have 4 elements. "name" is the GL selection name.
- """
-
- if self.petrified:
- raise ValueError, "Tried to add a cylinder to a petrified ShapeList_inplace"
-
- # struct Cylinder {
- # float m_color[4];
- # float m_nameUInt;
- # float m_cappedBool;
- # float m_pos1[3];
- # float m_pos2[3];
- # float m_radius;
- # };
-
- if len(self.cylinders) == 0 or self.cylinders[-1][1] == ShapeList_inplace._blocking:
- # size of struct Cylinder in floats is 13
- block = Numeric.zeros((ShapeList_inplace._blocking, 13), 'f')
- self.cylinders.append([block, 0])
-
- (block, count) = self.cylinders[-1]
-
- block[count] = (\
- color4[0], color4[1], color4[2], color4[3],
- float(name),
- float(capped),
- pos1[0], pos1[1], pos1[2],
- pos2[0], pos2[1], pos2[2],
- radius)
-
- self.cylinders[-1][1] += 1
-
-
- def petrify(self):
- """
- Make this object
-
- Since the last block of shapes might not be full, this
- function copies them to a new block exactly big enough to hold
- the shapes in that block. The gc has a chance to release the
- old block and reduce memory use. After this point, shapes
- must not be added to this ShapeList.
- """
-
- self.petrified = True
-
- if len(self.spheres) > 0:
- count = self.spheres[-1][1]
- if count < ShapeList_inplace._blocking:
- block = self.spheres[-1][0]
- newblock = Numeric.array(block[0:count], 'f')
- self.spheres[-1][0] = newblock
-
- if len(self.cylinders) > 0:
- count = self.cylinders[-1][1]
- if count < ShapeList_inplace._blocking:
- block = self.cylinders[-1][0]
- newblock = Numeric.array(block[0:count], 'f')
- self.cylinders[-1][0] = newblock
-
-
-class ShapeList:
-
- """
- Records sphere and cylinder data and invokes it through the native C++
- rendering system.
-
- Probably better to use "ShapeList_inplace".
- """
-
- __author__ = "grantham@plunk.org"
-
- def __init__(self):
-
- self.memoized = False
-
- self.sphere_colors = []
- self.sphere_radii = []
- self.sphere_centers = []
- self.sphere_names = []
-
- self.cylinder_colors = []
- self.cylinder_radii = []
- self.cylinder_pos1 = []
- self.cylinder_pos2 = []
- self.cylinder_cappings = []
- self.cylinder_names = []
-
-
- def _memoize(self):
-
- """
- Internal function that creates Numeric arrays from the data stored
- in add_sphere and add-cylinder.
- """
-
- self.memoized = True
-
- # GL Names are uint32. Numeric.array appears to have only
- # int32. Winging it...
-
- self.sphere_colors_array = Numeric.array(self.sphere_colors, 'f')
- self.sphere_radii_array = Numeric.array(self.sphere_radii, 'f')
- self.sphere_centers_array = Numeric.array(self.sphere_centers, 'f')
- self.sphere_names_array = Numeric.array(self.sphere_names, 'i')
-
- self.cylinder_colors_array = Numeric.array(self.cylinder_colors, 'f')
- self.cylinder_radii_array = Numeric.array(self.cylinder_radii, 'f')
- self.cylinder_pos1_array = Numeric.array(self.cylinder_pos1, 'f')
- self.cylinder_pos2_array = Numeric.array(self.cylinder_pos2, 'f')
- self.cylinder_cappings_array = Numeric.array(self.cylinder_cappings, 'f')
- self.cylinder_names_array = Numeric.array(self.cylinder_names, 'i')
-
-
- def draw(self):
-
- """
- Draw all the objects represented in this shape list.
- """
-
- # ICK - SLOW - Probably no big deal in a display list.
-
- if len(self.sphere_radii) > 0:
- if not self.memoized:
- self._memoize()
- quux.shapeRendererDrawSpheres(len(self.sphere_radii),
- self.sphere_centers_array,
- self.sphere_radii_array,
- self.sphere_colors_array,
- self.sphere_names_array)
-
- if len(self.cylinder_radii) > 0:
- if not self.memoized:
- self._memoize()
- quux.shapeRendererDrawCylinders(len(self.cylinder_radii),
- self.cylinder_pos1_array,
- self.cylinder_pos2_array,
- self.cylinder_radii_array,
- self.cylinder_cappings_array,
- self.cylinder_colors_array,
- self.cylinder_names_array)
-
-
- def add_sphere(self, color4, pos, radius, name = 0):
- """
- Add a sphere to this shape list.
-
- "color4" must have 4 elements. "name" is the GL selection name.
- """
-
- self.sphere_colors.append(color4)
- self.sphere_centers.append(list(pos))
- self.sphere_radii.append(radius)
- self.sphere_names.append(name)
- self.memoized = False
-
-
- def add_cylinder(self, color4, pos1, pos2, radius, name = 0, capped=0):
- """
- Add a cylinder to this shape list.
-
- "color4" must have 4 elements. "name" is the GL selection name.
- """
-
- self.cylinder_colors.append(color4)
- self.cylinder_radii.append(radius)
- self.cylinder_pos1.append(list(pos1))
- self.cylinder_pos2.append(list(pos2))
- self.cylinder_cappings.append(capped)
- self.cylinder_names.append(name)
- self.memoized = False
-
-
- def petrify(self):
- """
- Delete all but the cached Numeric arrays.
-
- Call this when you're sure you don't have any more shapes to store
- in the shape list and you want to release the python lists of data
- back to the heap. Additional shapes must not be added to this shape
- list.
- """
- if not self.memoized:
- self._memoize()
-
- del self.sphere_colors
- del self.sphere_radii
- del self.sphere_centers
- del self.sphere_names
-
- del self.cylinder_colors
- del self.cylinder_radii
- del self.cylinder_pos1
- del self.cylinder_pos2
- del self.cylinder_cappings
- del self.cylinder_names
-
-#================================================================ ColorSortedDisplayList.py
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-ColorSortedDisplayList.py - A class to remember display list id's for
-objects that draw their instances through the ColorSorter.
-
-@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-
-import graphics.drawing.drawing_globals as drawing_globals
-
-class ColorSortedDisplayList: #Russ 080225: Added.
- """
- The ColorSorter's parent uses one of these to store color-sorted display list
- state. It's passed in to ColorSorter.start() .
- """
- def __init__(self):
- self.clear()
- self.selected = False # Whether to draw in the selection over-ride color.
- return
-
- #russ 080320 Experiment with VBO drawing from cached ColorSorter lists.
- cache_ColorSorter = False ## True
-
- def clear(self):
- """
- Empty state.
- """
- self.dl = 0 # Current display list (color or selected.)
- self.color_dl = 0 # DL to set colors, call each lower level list.
- self.selected_dl = 0 # DL with a single (selected) over-ride color.
- self.nocolor_dl = 0 # DL of lower-level calls for color over-rides.
- self.per_color_dls = [] # Lower level, per-color primitive sublists.
- return
-
- def not_clear(self):
- """
- Check for empty state.
- """
- return self.dl or self.color_dl or self.nocolor_dl or self.selected_dl or \
- self.per_color_dls and len(self.per_color_dls)
-
- def activate(self):
- """
- Make a top-level display list id ready, but don't fill it in.
- """
- # Display list id for the current appearance.
- if not self.selected:
- self.color_dl = glGenLists(1)
- else:
- self.selected_dl = glGenLists(1)
- pass
- self.selectDl()
- assert type(self.dl) in (type(1), type(1L)) #bruce 070521 added these two asserts
- assert self.dl != 0 # This failed on Linux, keep checking. (bug 2042)
- return
-
- def draw_dl(self): #russ 080320 Added.
- """
- Draw the displist (cached display procedure.)
- """
- #russ 080320: Experiment with VBO drawing from cached ColorSorter lists.
- if (ColorSortedDisplayList.cache_ColorSorter and
- drawing_globals.allow_color_sorting and
- drawing_globals.use_color_sorted_vbos):
- ColorSorter.draw_sorted(self.sorted_by_color)
- else:
- # Call a normal OpenGL display list.
- glCallList(self.dl)
- return
-
- def selectPick(self, boolVal):
- """
- Remember whether we're selected or not.
- """
- self.selected = boolVal
- self.selectDl()
- return
-
- def selectDl(self):
- """
- Change to either the normal-color display list or the selected one.
- """
- self.dl = self.selected and self.selected_dl or self.color_dl
- return
-
- def reset(self):
- """
- Return to initialized state.
- """
- if self.not_clear():
- # deallocate leaves it clear.
- self.deallocate_displists()
- pass
- return
-
- def deallocate_displists(self):
- """
- Free any allocated display lists.
- """
- # With CSDL active, self.dl duplicates either selected_dl or color_dl.
- if (self.dl is not self.color_dl and
- self.dl is not self.selected_dl):
- glDeleteLists(self.dl, 1)
- for dl in [self.color_dl, self.nocolor_dl, self.selected_dl]:
- if dl != 0:
- glDeleteLists(dl, 1)
- pass
- continue
- # piotr 080420: The second level dl's are 2-element lists of DL ids
- # rather than just a list of ids. The secod DL is used in case
- # of multi-color objects and is required for highlighting
- # and selection (not in rc1)
- for clr, dls in self.per_color_dls: # Second-level dl's.
- for dl in dls: # iterate over DL pairs.
- if dl != 0:
- glDeleteLists(dl, 1)
- pass
- continue
- self.clear()
- return
-
- pass # End of ColorSortedDisplayList.
-
-#================================================================ ColorSorter.py
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-ColorSorter.py - A class to group primitive drawing by colors.
-
-This was originally done as a GL optimization to minimize calls on
-apply_material.
-
-Later, it was extended to handle multiple display lists per Chunk object as an
-optimization to avoid rebuilding a single display list when the appearance of
-the object changes for hover-highlighting and selection.
-
-@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-
-import graphics.drawing.drawing_globals as drawing_globals
-
-class ColorSorter:
-
- """
- State Sorter specializing in color (Really any object that can be
- passed to apply_material, which on 20051204 is only color 4-tuples)
-
- Invoke start() to begin sorting.
- Call finish() to complete sorting and draw all sorted objects.
-
- Call schedule() with any function and parameters to be sorted by color.
- If not sorting, schedule() will invoke the function immediately. If
- sorting, then the function will not be called until "finish()".
-
- In any function which will take part in sorting which previously did
- not, create a worker function from the old function except the call to
- apply_material. Then create a wrapper which calls
- ColorSorter.schedule with the worker function and its params.
-
- Also an app can call schedule_sphere and schedule_cylinder to
- schedule a sphere or a cylinder. Right now this is the only way
- to directly access the native C++ rendering engine.
- """
- __author__ = "grantham@plunk.org"
-
- # For now, these are class globals. As long as OpenGL drawing is
- # serialized and Sorting isn't nested, this is okay. When/if
- # OpenGL drawing becomes multi-threaded, sorters will have to
- # become instances. This is probably okay because objects and
- # materials will probably become objects of their own about that
- # time so the whole system will get a redesign and
- # reimplementation.
-
- sorting = False # Guard against nested sorting
- _sorted = 0 # Number of calls to _add_to_sorter since last
- # _printstats
- _immediate = 0 # Number of calls to _invoke_immediately since last
- # _printstats
- _gl_name_stack = [0] # internal record of GL name stack; 0 is a sentinel
-
- def pushName(glname):
- """
- Record the current pushed GL name, which must not be 0.
- """
- assert glname, "glname of 0 is illegal (used as sentinel)" #bruce 060217 added this assert
- ColorSorter._gl_name_stack.append(glname)
-
- pushName = staticmethod(pushName)
-
-
- def popName():
- """
- Record a pop of the GL name.
- """
- del ColorSorter._gl_name_stack[-1]
-
- popName = staticmethod(popName)
-
-
- def _printstats():
- """
- Internal function for developers to call to print stats on number of
- sorted and immediately-called objects.
- """
- print "Since previous 'stats', %d sorted, %d immediate: " % (ColorSorter._sorted, ColorSorter._immediate)
- ColorSorter._sorted = 0
- ColorSorter._immediate = 0
-
- _printstats = staticmethod(_printstats)
-
-
- def _add_to_sorter(color, func, params):
- """
- Internal function that stores 'scheduled' operations for a later
- sort, between a start/finish
- """
- ColorSorter._sorted += 1
- color = tuple(color)
- if not ColorSorter.sorted_by_color.has_key(color):
- ColorSorter.sorted_by_color[color] = []
- ColorSorter.sorted_by_color[color].append((func, params,
- ColorSorter._gl_name_stack[-1]))
-
- _add_to_sorter = staticmethod(_add_to_sorter)
-
-
- def schedule(color, func, params):
- if ColorSorter.sorting and drawing_globals.allow_color_sorting:
-
- ColorSorter._add_to_sorter(color, func, params)
-
- else:
-
- ColorSorter._immediate += 1 # for benchmark/debug stats, mostly
-
- # 20060216 We know we can do this here because the stack is
- # only ever one element deep
- name = ColorSorter._gl_name_stack[-1]
- if name:
- glPushName(name)
-
- #Apply appropriate opacity for the object if it is specified
- #in the 'color' param. (Also do necessary things such as
- #call glBlendFunc it. -- Ninad 20071009
-
- if len(color) == 4:
- opacity = color[3]
- else:
- opacity = 1.0
-
- if opacity >= 0.0 and opacity != 1.0:
- glDepthMask(GL_FALSE)
- glEnable(GL_BLEND)
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
- elif opacity == -1:
- # piotr 080429: I replaced the " < 0" condition with " == -1"
- # The opacity flag is now used to signal either "unshaded colors"
- # (opacity == -1) or "multicolor object" (opacity == -2)
- glDisable(GL_LIGHTING) # Don't forget to re-enable it!
- glColor3fv(color[:3])
- pass
-
- apply_material(color)
- func(params)
-
- if opacity > 0.0 and opacity != 1.0:
- glDisable(GL_BLEND)
- glDepthMask(GL_TRUE)
- elif opacity == -1:
- # piotr 080429: See my comment above.
- glEnable(GL_LIGHTING)
-
- if name:
- glPopName()
- return
-
- schedule = staticmethod(schedule)
-
- def schedule_sphere(color, pos, radius, detailLevel, opacity = 1.0):
- """
- Schedule a sphere for rendering whenever ColorSorter thinks is
- appropriate.
- """
- if drawing_globals.use_c_renderer and ColorSorter.sorting:
- if len(color) == 3:
- lcolor = (color[0], color[1], color[2], opacity)
- else:
- lcolor = color
- ColorSorter._cur_shapelist.add_sphere(lcolor, pos, radius,
- ColorSorter._gl_name_stack[-1])
- # 20060208 grantham - I happen to know that one detailLevel
- # is chosen for all spheres, I just record it over and
- # over here, and use the last one for the render
- if ColorSorter.sphereLevel > -1 and ColorSorter.sphereLevel != detailLevel:
- raise ValueError, "unexpected different sphere LOD levels within same frame"
- ColorSorter.sphereLevel = detailLevel
- else: # Older sorted material rendering
- if len(color) == 3:
- lcolor = (color[0], color[1], color[2], opacity)
- else:
- lcolor = color
- ColorSorter.schedule(lcolor, drawsphere_worker, ### drawsphere_worker_loop ### Testing.
- (pos, radius, detailLevel))
-
- schedule_sphere = staticmethod(schedule_sphere)
-
-
- def schedule_wiresphere(color, pos, radius, detailLevel = 1):
- """
- Schedule a wiresphere for rendering whenever ColorSorter thinks is
- appropriate.
- """
- if drawing_globals.use_c_renderer and ColorSorter.sorting:
- if len(color) == 3:
- lcolor = (color[0], color[1], color[2], 1.0)
- else:
- lcolor = color
- assert 0, "Need to implement a C add_wiresphere function."
- ColorSorter._cur_shapelist.add_wiresphere(lcolor, pos, radius,
- ColorSorter._gl_name_stack[-1])
- else:
- if len(color) == 3:
- lcolor = (color[0], color[1], color[2], 1.0)
- else:
- lcolor = color
-
- ColorSorter.schedule(lcolor, drawwiresphere_worker,
- # Use constant-color line drawing.
- (color, pos, radius, detailLevel))
-
- schedule_wiresphere = staticmethod(schedule_wiresphere)
-
- def schedule_cylinder(color, pos1, pos2, radius, capped = 0, opacity = 1.0 ):
- """
- Schedule a cylinder for rendering whenever ColorSorter thinks is
- appropriate.
- """
- if drawing_globals.use_c_renderer and ColorSorter.sorting:
- if len(color) == 3:
- lcolor = (color[0], color[1], color[2], 1.0)
- else:
- lcolor = color
- ColorSorter._cur_shapelist.add_cylinder(lcolor, pos1, pos2, radius,
- ColorSorter._gl_name_stack[-1], capped)
- else:
- if len(color) == 3:
- lcolor = (color[0], color[1], color[2], opacity)
- else:
- lcolor = color
-
- ColorSorter.schedule(lcolor, drawcylinder_worker, (pos1, pos2, radius, capped))
-
- schedule_cylinder = staticmethod(schedule_cylinder)
-
- def schedule_polycone(color, pos_array, rad_array, capped = 0, opacity = 1.0):
- """
- Schedule a polycone for rendering whenever ColorSorter thinks is
- appropriate.
- """
- if drawing_globals.use_c_renderer and ColorSorter.sorting:
- if len(color) == 3:
- lcolor = (color[0], color[1], color[2], 1.0)
- else:
- lcolor = color
- assert 0, "Need to implement a C add_polycone_multicolor function."
- ColorSorter._cur_shapelist.add_polycone(lcolor, pos_array, rad_array,
- ColorSorter._gl_name_stack[-1], capped)
- else:
- if len(color) == 3:
- lcolor = (color[0], color[1], color[2], opacity)
- else:
- lcolor = color
-
- ColorSorter.schedule(lcolor, drawpolycone_worker, (pos_array, rad_array))
-
- schedule_polycone = staticmethod(schedule_polycone)
-
- def schedule_polycone_multicolor(color, pos_array, color_array, rad_array, capped = 0, opacity = 1.0):
- """
- Schedule a polycone for rendering whenever ColorSorter thinks is
- appropriate.
- piotr 080311: this variant accepts a color array as an additional parameter
- """
- if drawing_globals.use_c_renderer and ColorSorter.sorting:
- if len(color) == 3:
- lcolor = (color[0], color[1], color[2], 1.0)
- else:
- lcolor = color
- assert 0, "Need to implement a C add_polycone function."
- ColorSorter._cur_shapelist.add_polycone_multicolor(lcolor, pos_array, color_array, rad_array,
- ColorSorter._gl_name_stack[-1], capped)
- else:
- if len(color) == 3:
- lcolor = (color[0], color[1], color[2], opacity)
- else:
- lcolor = color
-
- ColorSorter.schedule(lcolor, drawpolycone_multicolor_worker, (pos_array, color_array, rad_array))
-
- schedule_polycone_multicolor = staticmethod(schedule_polycone_multicolor)
-
- def schedule_surface(color, pos, radius, tm, nm):
- """
- Schedule a surface for rendering whenever ColorSorter thinks is
- appropriate.
- """
- ColorSorter.schedule(color, drawsurface_worker, (pos, radius, tm, nm))
-
- schedule_surface = staticmethod(schedule_surface)
-
- def schedule_line(color, endpt1, endpt2, dashEnabled,
- stipleFactor, width, isSmooth):
- """
- Schedule a line for rendering whenever ColorSorter thinks is
- appropriate.
- """
- #russ 080306: Signal "unshaded colors" for lines by a negative alpha. (Hack!)
- color = tuple(color) + (-1,)
- ColorSorter.schedule(color, drawline_worker,
- (endpt1, endpt2, dashEnabled,
- stipleFactor, width, isSmooth))
-
- schedule_line = staticmethod(schedule_line)
-
- def start(csdl, pickstate=None):
- """
- Start sorting - objects provided to "schedule", "schedule_sphere", and
- "schedule_cylinder" will be stored for a sort at the time "finish" is called.
- csdl is a ColorSortedDisplayList or None, in which case immediate drawing is done.
- pickstate (optional) indicates whether the parent is currently selected.
- """
-
- #russ 080225: Moved glNewList here for displist re-org.
- ColorSorter.parent_csdl = csdl # Remember, used by finish().
- if pickstate is not None:
- csdl.selectPick(pickstate)
- pass
-
- if csdl != None:
- if not (drawing_globals.allow_color_sorting and
- (drawing_globals.use_color_sorted_dls
- or drawing_globals.use_color_sorted_vbos)): #russ 080320
- # This is the beginning of the single display list created when color
- # sorting is turned off. It is ended in ColorSorter.finish . In
- # between, the calls to draw{sphere,cylinder,polycone} methods pass
- # through ColorSorter.schedule_* but are immediately sent to *_worker
- # where they do OpenGL drawing that is captured into the display list.
- try:
- if csdl.dl is 0:
- csdl.activate() # Allocate a display list for our use.
- pass
- glNewList(csdl.dl, GL_COMPILE_AND_EXECUTE) # Start a single-level list.
- except:
- print "data related to following exception: csdl.dl = %r" % (csdl.dl,) #bruce 070521
- raise
-
- assert not ColorSorter.sorting, "Called ColorSorter.start but already sorting?!"
- ColorSorter.sorting = True
- if drawing_globals.use_c_renderer and ColorSorter.sorting:
- ColorSorter._cur_shapelist = ShapeList_inplace()
- ColorSorter.sphereLevel = -1
- else:
- ColorSorter.sorted_by_color = {}
-
- start = staticmethod(start)
-
- def finish():
- """
- Finish sorting - objects recorded since "start" will
- be sorted and invoked now.
- """
- from utilities.debug_prefs import debug_pref, Choice_boolean_False
- debug_which_renderer = debug_pref("debug print which renderer", Choice_boolean_False) #bruce 060314, imperfect but tolerable
-
- parent_csdl = ColorSorter.parent_csdl
- if drawing_globals.use_c_renderer:
- quux.shapeRendererInit()
- if debug_which_renderer:
- #bruce 060314 uncommented/revised the next line; it might have to come after shapeRendererInit (not sure);
- # it definitely has to come after a graphics context is created and initialized.
- # 20060314 grantham - yes, has to come after quux.shapeRendererInit
- print "using C renderer: VBO %s enabled" % (('is NOT', 'is')[quux.shapeRendererGetInteger(quux.IS_VBO_ENABLED)])
- quux.shapeRendererSetUseDynamicLOD(0)
- if ColorSorter.sphereLevel != -1:
- quux.shapeRendererSetStaticLODLevels(ColorSorter.sphereLevel, 1)
- quux.shapeRendererStartDrawing()
- ColorSorter._cur_shapelist.draw()
- quux.shapeRendererFinishDrawing()
- ColorSorter.sorting = False
-
- # So chunks can actually record their shapelist
- # at some point if they want to
- # ColorSorter._cur_shapelist.petrify()
- # return ColorSorter._cur_shapelist
-
- else:
- if debug_which_renderer:
- print "using Python renderer: use_color_sorted_dls %s enabled" \
- % (drawing_globals.use_color_sorted_dls and 'IS'
- or 'is NOT')
- print "using Python renderer: use_color_sorted_vbos %s enabled" \
- % (drawing_globals.use_color_sorted_vbos and 'IS'
- or 'is NOT')
- color_groups = len(ColorSorter.sorted_by_color)
- objects_drawn = 0
-
- if (not (drawing_globals.allow_color_sorting and
- drawing_globals.use_color_sorted_dls)
- or (ColorSortedDisplayList.cache_ColorSorter and
- drawing_globals.allow_color_sorting and
- drawing_globals.use_color_sorted_vbos)
- or parent_csdl is None): #russ 080225 Added, 080320 VBO experiment.
-
- # Either all in one display list, or immediate-mode drawing.
- objects_drawn += ColorSorter.draw_sorted(ColorSorter.sorted_by_color)
-
- #russ 080225: Moved glEndList here for displist re-org.
- if parent_csdl is not None:
- #russ 080320: Experiment with VBO drawing from cached ColorSorter lists.
- if (ColorSortedDisplayList.cache_ColorSorter and
- drawing_globals.allow_color_sorting and
- drawing_globals.use_color_sorted_vbos):
- # Remember the ColorSorter lists for use as a pseudo-display-list.
- parent_csdl.sorted_by_color = ColorSorter.sorted_by_color
- else:
- # Terminate a single display list, created when color sorting
- # is turned off. It was started in ColorSorter.start .
- glEndList()
- pass
- pass
-
- else: #russ 080225
-
- parent_csdl.reset()
-
- # First build the lower level per-color sublists of primitives.
- for color, funcs in ColorSorter.sorted_by_color.iteritems():
- sublists = [glGenLists(1), 0]
-
- # Remember the display list ID for this color.
- parent_csdl.per_color_dls.append([color, sublists])
-
- glNewList(sublists[0], GL_COMPILE)
- opacity = color[3]
-
- if opacity == -1:
- #russ 080306: "Unshaded colors" for lines are signaled
- # by an opacity of -1 (4th component of the color.)
- glDisable(GL_LIGHTING) # Don't forget to re-enable it!
- pass
-
- for func, params, name in funcs:
- objects_drawn += 1
- if name != 0:
- glPushName(name)
- func(params)
- if name != 0:
- glPopName()
- pass
- continue
-
- if opacity == -1:
- # Enable lighting after drawing "unshaded" objects.
- glEnable(GL_LIGHTING)
- pass
- glEndList()
-
- if opacity == -2:
- # piotr 080419: Special case for drawpolycone_multicolor
- # create another display list that ignores
- # the contents of color_array.
- # Remember the display list ID for this color.
-
- sublists[1] = glGenLists(1)
-
- glNewList(sublists[1], GL_COMPILE)
-
- for func, params, name in funcs:
- objects_drawn += 1
- if name != 0:
- glPushName(name)
- pos_array, color_array, rad_array = params
- if func == drawpolycone_multicolor_worker:
- # Just to be sure, check if the func
- # is drawpolycone_multicolor_worker
- # and call drawpolycone_worker instead.
- # I think in the future we can figure out
- # a more general way of handling the
- # GL_COLOR_MATERIAL objects. piotr 080420
- drawpolycone_worker((pos_array, rad_array))
- if name != 0:
- glPopName()
- pass
- continue
- glEndList()
-
- continue
-
- # Now the upper-level lists call all of the per-color sublists.
- # One with colors.
- color_dl = parent_csdl.color_dl = glGenLists(1)
- glNewList(color_dl, GL_COMPILE)
-
- for color, dls in parent_csdl.per_color_dls:
-
- opacity = color[3]
- if opacity < 0:
- #russ 080306: "Unshaded colors" for lines are signaled
- # by a negative alpha.
- glColor3fv(color[:3])
- # piotr 080417: for opacity == -2, i.e. if
- # GL_COLOR_MATERIAL is enabled, the color is going
- # to be ignored, anyway, so it is not necessary
- # to be tested here
- else:
- apply_material(color)
-
- glCallList(dls[0])
-
- continue
- glEndList()
-
- # A second one without any colors.
- nocolor_dl = parent_csdl.nocolor_dl = glGenLists(1)
- glNewList(nocolor_dl, GL_COMPILE)
- for color, dls in parent_csdl.per_color_dls:
- opacity = color[3]
-
- if opacity == -2 \
- and dls[1] > 0:
- # piotr 080420: If GL_COLOR_MATERIAL is enabled,
- # use a regular, single color dl rather than the
- # multicolor one. Btw, dls[1] == 0 should never
- # happen.
- glCallList(dls[1])
- else:
- glCallList(dls[0])
-
- glEndList()
-
- # A third overlays the second with a single color for selection.
- selected_dl = parent_csdl.selected_dl = glGenLists(1)
- glNewList(selected_dl, GL_COMPILE)
- apply_material(darkgreen)
- glCallList(nocolor_dl)
- glEndList()
-
- # Use either the normal-color display list or the selected one.
- parent_csdl.selectDl()
-
- # Draw the newly-built display list.
- parent_csdl.draw_dl()
- pass
-
- ColorSorter.sorted_by_color = None
- pass
- ColorSorter.sorting = False
- return
-
- finish = staticmethod(finish)
-
- def draw_sorted(sorted_by_color): #russ 080320: factored out of finish().
- """
- Traverse color-sorted lists, invoking worker procedures.
- """
- objects_drawn = 0 # Keep track and return.
- glEnable(GL_LIGHTING)
-
- for color, funcs in sorted_by_color.iteritems():
-
- opacity = color[3]
- if opacity == -1:
- #piotr 080429: Opacity == -1 signals the "unshaded color".
- # Also, see my comment in "schedule".
- glDisable(GL_LIGHTING) # Don't forget to re-enable it!
- glColor3fv(color[:3])
- else:
- apply_material(color)
- pass
-
- for func, params, name in funcs:
- objects_drawn += 1
- if name != 0:
- glPushName(name)
- func(params)
- if name != 0:
- glPopName()
- pass
- continue
-
- if opacity == -1:
- glEnable(GL_LIGHTING)
-
- continue
- return objects_drawn
-
- draw_sorted = staticmethod(draw_sorted)
-
- pass # End of class ColorSorter.
-
-#================================================================ CS_draw_primitives.py
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-CS_draw_primitives.py - Public entry points for ColorSorter drawing primitives.
-
-These functions all call ColorSorter.schedule_* methods, which record object
-data for sorting, including the object color and an eventual call on the
-appropriate drawing worker function.
-
-@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-
-import foundation.env as env #bruce 051126
-
-def drawsphere(color, pos, radius, detailLevel, opacity = 1.0):
- """
- Schedule a sphere for rendering whenever ColorSorter thinks is appropriate.
- """
- ColorSorter.schedule_sphere(color,
- pos,
- radius,
- detailLevel,
- opacity = opacity)
-
-def drawwiresphere(color, pos, radius, detailLevel = 1):
- """
- Schedule a wireframe sphere for rendering whenever ColorSorter thinks is appropriate.
- """
- ColorSorter.schedule_wiresphere(color, pos, radius, detailLevel = detailLevel)
-
-def drawcylinder(color, pos1, pos2, radius, capped = 0, opacity = 1.0):
- """Schedule a cylinder for rendering whenever ColorSorter thinks is
- appropriate."""
- if 1:
- #bruce 060304 optimization: don't draw zero-length or almost-zero-length cylinders.
- # (This happens a lot, apparently for both long-bond indicators and for open bonds.
- # The callers hitting this should be fixed directly! That might provide a further
- # optim by making a lot more single bonds draw as single cylinders.)
- # The reason the threshhold depends on capped is in case someone draws a very thin
- # cylinder as a way of drawing a disk. But they have to use some positive length
- # (or the direction would be undefined), so we still won't permit zero-length then.
- cyllen = vlen(pos1 - pos2)
- if cyllen < (capped and 0.000000000001 or 0.0001):
- # uncomment this to find the callers that ought to be optimized
-## if env.debug(): #e optim or remove this test; until then it's commented out
-## print "skipping drawcylinder since length is only %5g" % (cyllen,), \
-## " (color is (%0.2f, %0.2f, %0.2f))" % (color[0], color[1], color[2])
- return
- ColorSorter.schedule_cylinder(color, pos1, pos2, radius,
- capped = capped, opacity = opacity)
-
-def drawpolycone(color, pos_array, rad_array, opacity = 1.0):
- """Schedule a polycone for rendering whenever ColorSorter thinks is
- appropriate."""
- ColorSorter.schedule_polycone(color, pos_array, rad_array, opacity = opacity)
-
-def drawpolycone_multicolor(color, pos_array, color_array, rad_array, opacity = 1.0):
- """Schedule a polycone for rendering whenever ColorSorter thinks is
- appropriate. Accepts color_array for per-vertex coloring. """
- ColorSorter.schedule_polycone_multicolor(color, pos_array, color_array, rad_array, opacity = opacity)
-
-def drawsurface(color, pos, radius, tm, nm):
- """
- Schedule a surface for rendering whenever ColorSorter thinks is
- appropriate.
- """
- ColorSorter.schedule_surface(color, pos, radius, tm, nm)
-
-def drawline(color,
- endpt1,
- endpt2,
- dashEnabled = False,
- stipleFactor = 1,
- width = 1,
- isSmooth = False):
- """
- Draw a line from endpt1 to endpt2 in the given color. Actually, schedule
- it for rendering whenever ColorSorter thinks is appropriate.
-
- @param endpt1: First endpoint.
- @type endpt1: point
-
- @param endpt2: Second endpoint.
- @type endpt2: point
-
- @param dashEnabled: If dashEnabled is True, it will be dashed.
- @type dashEnabled: boolean
-
- @param stipleFactor: The stiple factor.
- @param stipleFactor: int
-
- @param width: The line width in pixels. The default is 1.
- @type width: int or float
-
- @param isSmooth: Enables GL_LINE_SMOOTH. The default is False.
- @type isSmooth: boolean
-
- @note: Whether the line is antialiased is determined by GL state variables
- which are not set in this function.
-
- @warning: Some callers pass dashEnabled as a positional argument rather
- than a named argument.
- """
- ColorSorter.schedule_line(color, endpt1, endpt2, dashEnabled,
- stipleFactor, width, isSmooth)
-
-
-#================================================================ setup_draw.py
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-setup_draw.py - The function to allocate and compile our standard display lists
-into the current GL context, and initialize the globals that hold their opengl
-names.
-
-@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-
-import graphics.drawing.drawing_globals as drawing_globals
-####from graphics.drawing.shape_vertices import getSphereTriStrips
-
-numSphereSizes = 3
-
-def setup_drawer():
- """
- Set up the usual constant display lists in the current OpenGL context.
-
- WARNING: THIS IS ONLY CORRECT IF ONLY ONE GL CONTEXT CONTAINS DISPLAY LISTS --
- or more precisely, only the GL context this has last been called in
- (or one which shares its display lists) will work properly with the routines in drawer.py,
- since the allocated display list names are stored in globals set by this function,
- but in general those names might differ if this was called in different GL contexts.
- """
- #bruce 060613 added docstring, cleaned up display list name allocation
- # bruce 071030 renamed from setup to setup_drawer
-
- spherelistbase = glGenLists(numSphereSizes)
- sphereList = []
- for i in range(numSphereSizes):
- sphereList += [spherelistbase+i]
- glNewList(sphereList[i], GL_COMPILE)
- glBegin(GL_TRIANGLE_STRIP) # GL_LINE_LOOP to see edges.
- stripVerts = getSphereTriStrips(i)
- for vertNorm in stripVerts:
- glNormal3fv(vertNorm)
- glVertex3fv(vertNorm)
- continue
- glEnd()
- glEndList()
- continue
- drawing_globals.sphereList = sphereList
-
- # Sphere triangle-strip vertices for each level of detail.
- # (Cache and re-use the work of making them.)
- # Can use in converter-wrappered calls like glVertexPointerfv,
- # but the python arrays are re-copied to C each time.
- sphereArrays = []
- for i in range(numSphereSizes):
- sphereArrays += [getSphereTriStrips(i)]
- continue
- drawing_globals.sphereArrays = sphereArrays
-
- # Sphere glDrawArrays triangle-strip vertices for C calls.
- # (Cache and re-use the work of converting a C version.)
- # Used in thinly-wrappered calls like glVertexPointer.
- sphereCArrays = []
- for i in range(numSphereSizes):
- CArray = numpy.array(sphereArrays[i], dtype=numpy.float32)
- sphereCArrays += [CArray]
- continue
- drawing_globals.sphereCArrays = sphereCArrays
-
- # Sphere indexed vertices.
- # (Cache and re-use the work of making the indexes.)
- # Can use in converter-wrappered calls like glDrawElementsui,
- # but the python arrays are re-copied to C each time.
- sphereElements = [] # Pairs of lists (index, verts) .
- for i in range(numSphereSizes):
- sphereElements += [indexVerts(sphereArrays[i], .0001)]
- continue
- drawing_globals.sphereElements = sphereElements
-
- # Sphere glDrawElements index and vertex arrays for C calls.
- sphereCIndexTypes = [] # numpy index unsigned types.
- sphereGLIndexTypes = [] # GL index types for drawElements.
- sphereCElements = [] # Pairs of numpy arrays (Cindex, Cverts) .
- for i in range(numSphereSizes):
- (index, verts) = sphereElements[i]
- if len(index) < 256:
- Ctype = numpy.uint8
- GLtype = GL_UNSIGNED_BYTE
- else:
- Ctype = numpy.uint16
- GLtype = GL_UNSIGNED_SHORT
- pass
- sphereCIndexTypes += [Ctype]
- sphereGLIndexTypes += [GLtype]
- sphereCIndex = numpy.array(index, dtype=Ctype)
- sphereCVerts = numpy.array(verts, dtype=numpy.float32)
- sphereCElements += [(sphereCIndex, sphereCVerts)]
- continue
- drawing_globals.sphereCIndexTypes = sphereCIndexTypes
- drawing_globals.sphereGLIndexTypes = sphereGLIndexTypes
- drawing_globals.sphereCElements = sphereCElements
-
- if glGetString(GL_EXTENSIONS).find("GL_ARB_vertex_buffer_object") >= 0:
-
- # A GLBufferObject version for glDrawArrays.
- sphereArrayVBOs = []
- for i in range(numSphereSizes):
- vbo = GLBufferObject(GL_ARRAY_BUFFER_ARB,
- sphereCArrays[i], GL_STATIC_DRAW)
- sphereArrayVBOs += [vbo]
- continue
- drawing_globals.sphereArrayVBOs = sphereArrayVBOs
-
- # A GLBufferObject version for glDrawElements indexed verts.
- sphereElementVBOs = [] # Pairs of (IBO, VBO)
- for i in range(numSphereSizes):
- ibo = GLBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB,
- sphereCElements[i][0], GL_STATIC_DRAW)
- vbo = GLBufferObject(GL_ARRAY_BUFFER_ARB,
- sphereCElements[i][1], GL_STATIC_DRAW)
- sphereElementVBOs += [(ibo, vbo)]
- continue
- drawing_globals.sphereElementVBOs = sphereElementVBOs
-
- ibo.unbind()
- vbo.unbind()
- pass
-
- #bruce 060415
- drawing_globals.wiresphere1list = wiresphere1list = glGenLists(1)
- glNewList(wiresphere1list, GL_COMPILE)
- didlines = {} # don't draw each triangle edge more than once
- def shoulddoline(v1,v2):
- v1 = tuple(v1) # make sure not list (unhashable) or Numeric array (bug in __eq__)
- v2 = tuple(v2)
- if (v1,v2) not in didlines:
- didlines[(v1,v2)] = didlines[(v2,v1)] = None
- return True
- return False
- def doline(v1,v2):
- if shoulddoline(v1,v2):
- glVertex3fv(v1)
- glVertex3fv(v2)
- return
- glBegin(GL_LINES)
- ocdec = getSphereTriangles(1)
- for tri in ocdec:
- #e could probably optim this more, e.g. using a vertex array or VBO or maybe GL_LINE_STRIP
- doline(tri[0], tri[1])
- doline(tri[1], tri[2])
- doline(tri[2], tri[0])
- glEnd()
- glEndList()
-
- drawing_globals.CylList = CylList = glGenLists(1)
- glNewList(CylList, GL_COMPILE)
- glBegin(GL_TRIANGLE_STRIP)
- for (vtop, ntop, vbot, nbot) in drawing_globals.cylinderEdges:
- glNormal3fv(nbot)
- glVertex3fv(vbot)
- glNormal3fv(ntop)
- glVertex3fv(vtop)
- glEnd()
- glEndList()
-
- drawing_globals.CapList = CapList = glGenLists(1)
- glNewList(CapList, GL_COMPILE)
- glNormal3fv(drawing_globals.cap0n)
- glBegin(GL_POLYGON)
- for p in drawing_globals.drum0:
- glVertex3fv(p)
- glEnd()
- glNormal3fv(drawing_globals.cap1n)
- glBegin(GL_POLYGON)
- #bruce 060609 fix "ragged edge" bug in this endcap: drum1 -> drum2
- for p in drawing_globals.drum2:
- glVertex3fv(p)
- glEnd()
- glEndList()
-
- drawing_globals.diamondGridList = diamondGridList = glGenLists(1)
- glNewList(diamondGridList, GL_COMPILE)
- glBegin(GL_LINES)
- for p in drawing_globals.digrid:
- glVertex(p[0])
- glVertex(p[1])
- glEnd()
- glEndList()
-
- drawing_globals.lonsGridList = lonsGridList = glGenLists(1)
- glNewList(lonsGridList, GL_COMPILE)
- glBegin(GL_LINES)
- for p in drawing_globals.lonsEdges:
- glVertex(p[0])
- glVertex(p[1])
- glEnd()
- glEndList()
-
- drawing_globals.CubeList = CubeList = glGenLists(1)
- glNewList(CubeList, GL_COMPILE)
- glBegin(GL_QUAD_STRIP)
- # note: CubeList has only 4 faces of the cube; only suitable for use in wireframes;
- # see also solidCubeList [bruce 051215 comment reporting grantham 20051213 observation]
- glVertex((-1,-1,-1))
- glVertex(( 1,-1,-1))
- glVertex((-1, 1,-1))
- glVertex(( 1, 1,-1))
- glVertex((-1, 1, 1))
- glVertex(( 1, 1, 1))
- glVertex((-1,-1, 1))
- glVertex(( 1,-1, 1))
- glVertex((-1,-1,-1))
- glVertex(( 1,-1,-1))
- glEnd()
- glEndList()
-
- drawing_globals.solidCubeList = solidCubeList = glGenLists(1)
- glNewList(solidCubeList, GL_COMPILE)
- glBegin(GL_QUADS)
- for i in xrange(len(drawing_globals.cubeIndices)):
- avenormals = V(0,0,0) #bruce 060302 fixed normals for flat shading
- for j in xrange(4) :
- nTuple = tuple(
- drawing_globals.cubeNormals[drawing_globals.cubeIndices[i][j]])
- avenormals += A(nTuple)
- avenormals = norm(avenormals)
- for j in xrange(4) :
- vTuple = tuple(
- drawing_globals.cubeVertices[drawing_globals.cubeIndices[i][j]])
- #bruce 060302 made size compatible with glut.glutSolidCube(1.0)
- vTuple = A(vTuple) * 0.5
- glNormal3fv(avenormals)
- glVertex3fv(vTuple)
- glEnd()
- glEndList()
-
- drawing_globals.rotSignList = rotSignList = glGenLists(1)
- glNewList(rotSignList, GL_COMPILE)
- glBegin(GL_LINE_STRIP)
- for ii in xrange(len(drawing_globals.rotS0n)):
- glVertex3fv(tuple(drawing_globals.rotS0n[ii]))
- glEnd()
- glBegin(GL_LINE_STRIP)
- for ii in xrange(len(drawing_globals.rotS1n)):
- glVertex3fv(tuple(drawing_globals.rotS1n[ii]))
- glEnd()
- glBegin(GL_TRIANGLES)
- for v in drawing_globals.arrow0Vertices + drawing_globals.arrow1Vertices:
- glVertex3f(v[0], v[1], v[2])
- glEnd()
- glEndList()
-
- drawing_globals.linearArrowList = linearArrowList = glGenLists(1)
- glNewList(linearArrowList, GL_COMPILE)
- glBegin(GL_TRIANGLES)
- for v in drawing_globals.linearArrowVertices:
- glVertex3f(v[0], v[1], v[2])
- glEnd()
- glEndList()
-
- drawing_globals.linearLineList = linearLineList = glGenLists(1)
- glNewList(linearLineList, GL_COMPILE)
- glEnable(GL_LINE_SMOOTH)
- glBegin(GL_LINES)
- glVertex3f(0.0, 0.0, -drawing_globals.halfHeight)
- glVertex3f(0.0, 0.0, drawing_globals.halfHeight)
- glEnd()
- glDisable(GL_LINE_SMOOTH)
- glEndList()
-
- drawing_globals.circleList = circleList = glGenLists(1)
- glNewList(circleList, GL_COMPILE)
- glBegin(GL_LINE_LOOP)
- for ii in range(60):
- x = cos(ii*2.0*pi/60)
- y = sin(ii*2.0*pi/60)
- glVertex3f(x, y, 0.0)
- glEnd()
- glEndList()
-
- # piotr 080405
- drawing_globals.filledCircleList = filledCircleList = glGenLists(1)
- glNewList(filledCircleList, GL_COMPILE)
- glBegin(GL_POLYGON)
- for ii in range(60):
- x = cos(ii*2.0*pi/60)
- y = sin(ii*2.0*pi/60)
- glVertex3f(x, y, 0.0)
- glEnd()
- glEndList()
-
- drawing_globals.lineCubeList = lineCubeList = glGenLists(1)
- glNewList(lineCubeList, GL_COMPILE)
- glBegin(GL_LINES)
- cvIndices = [0,1, 2,3, 4,5, 6,7, 0,3, 1,2, 5,6, 4,7, 0,4, 1,5, 2,6, 3,7]
- for i in cvIndices:
- glVertex3fv(tuple(drawing_globals.cubeVertices[i]))
- glEnd()
- glEndList()
-
- # Debug Preferences
- from utilities.debug_prefs import debug_pref, Choice_boolean_True
- from utilities.debug_prefs import Choice_boolean_False
- choices = [Choice_boolean_False, Choice_boolean_True]
-
- # 20060314 grantham
- initial_choice = choices[drawing_globals.allow_color_sorting_default]
- drawing_globals.allow_color_sorting_pref = debug_pref(
- "Use Color Sorting?", initial_choice,
- prefs_key = drawing_globals.allow_color_sorting_prefs_key)
- #bruce 060323 removed non_debug = True for A7 release, changed default
- #value to False (far above), and changed its prefs_key so developers
- #start with the new default value.
- #russ 080225: Added.
- initial_choice = choices[drawing_globals.use_color_sorted_dls_default]
- drawing_globals.use_color_sorted_dls_pref = debug_pref(
- "Use Color-sorted Display Lists?", initial_choice,
- prefs_key = drawing_globals.use_color_sorted_dls_prefs_key)
- #russ 080225: Added.
- initial_choice = choices[drawing_globals.use_color_sorted_vbos_default]
- drawing_globals.use_color_sorted_vbos_pref = debug_pref(
- "Use Color-sorted Vertex Buffer Objects?", initial_choice,
- prefs_key = drawing_globals.use_color_sorted_vbos_prefs_key)
-
- #russ 080403: Added drawing variant selection
- variants = [
- "0. OpenGL 1.0 - glBegin/glEnd tri-strips vertex-by-vertex.",
- "1. OpenGL 1.1 - glDrawArrays from CPU RAM.",
- "2. OpenGL 1.1 - glDrawElements indexed arrays from CPU RAM.",
- "3. OpenGL 1.5 - glDrawArrays from graphics RAM VBO.",
- "4. OpenGL 1.5 - glDrawElements, verts in VBO, index in CPU.",
- "5. OpenGL 1.5 - VBO/IBO buffered glDrawElements."]
- drawing_globals.use_drawing_variant = debug_pref(
- "GLPane: drawing method",
- Choice(names = variants, values = range(len(variants)),
- defaultValue = drawing_globals.use_drawing_variant_default),
- prefs_key = drawing_globals.use_drawing_variant_prefs_key)
-
- # temporarily always print this, while default setting might be in flux,
- # and to avoid confusion if the two necessary prefs are set differently
- # [bruce 080305]
- if (drawing_globals.allow_color_sorting_pref and
- drawing_globals.use_color_sorted_dls_pref):
- print "\nnote: this session WILL use color sorted display lists"
- else:
- print "\nnote: this session will NOT use color sorted display lists"
- if (drawing_globals.allow_color_sorting_pref and
- drawing_globals.use_color_sorted_vbos_pref):
- print "note: this session WILL use color sorted Vertex Buffer Objects\n"
- else:
- print "note: this session will NOT use color sorted Vertex Buffer Objects\n"
-
- # 20060313 grantham Added use_c_renderer debug pref, can
- # take out when C renderer used by default.
- if drawing_globals.quux_module_import_succeeded:
- initial_choice = choices[drawing_globals.use_c_renderer_default]
- drawing_globals.use_c_renderer = (
- debug_pref("Use native C renderer?",
- initial_choice,
- prefs_key = drawing_globals.use_c_renderer_prefs_key))
- #bruce 060323 removed non_debug = True for A7 release,
- # and changed its prefs_key so developers start over with the default value.
-
- #initTexture('C:\\Huaicai\\atom\\temp\\newSample.png', 128,128)
- return # from setup_drawer
-
-#================================================================ drawers.py
-# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-drawers.py - Miscellaneous drawing functions that are not used as primitives.
-
-@version: $Id$
-@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
-"""
-
-import graphics.drawing.drawing_globals as drawing_globals
-
-try:
- from OpenGL.GLE import glePolyCone, gleGetNumSides, gleSetNumSides
-except:
- print "GLE module can't be imported. Now trying _GLE"
- from OpenGL._GLE import glePolyCone, gleGetNumSides, gleSetNumSides
-
-# Check if the gleGet/SetNumSides function is working on this install, and if
-# not, alias it to an effective no-op. Checking method is as recommended in
-# an OpenGL exception reported by Brian [070622]:
-# OpenGL.error.NullFunctionError: Attempt to call an
-# undefined function gleGetNumSides, check for
-# bool(gleGetNumSides) before calling
-# The underlying cause of this (described by Brian) is that the computer's OpenGL
-# has the older gleGetNumSlices (so it supports the functionality), but PyOpenGL
-# binds (only) to the newer gleGetNumSides. Given the PyOpenGL we're using,
-# there's no way to access gleGetNumSlices, but in the future we might patch it
-# to let us do that when this happens. I [bruce 070629] think Brian said this is
-# only an issue on Macs.
-if not bool(gleGetNumSides):
- print "fyi: gleGetNumSides is not supported by the OpenGL pre-installed on this computer."
- gleGetNumSides = int
- gleSetNumSides = int
-
-# ==
-
-def drawCircle(color, center, radius, normal):
- """Scale, rotate/translate the unit circle properly """
- glMatrixMode(GL_MODELVIEW)
- glPushMatrix()
- glColor3fv(color)
- glDisable(GL_LIGHTING)
-
- glTranslatef(center[0], center[1], center[2])
- rQ = Q(V(0, 0, 1), normal)
- rotAngle = rQ.angle*180.0/pi
-
- #This may cause problems as proved before in Linear motor display.
- #rotation around (0, 0, 0)
- #if vlen(V(rQ.x, rQ.y, rQ.z)) < 0.00005:
- # rQ.x = 1.0
-
- glRotatef(rotAngle, rQ.x, rQ.y, rQ.z)
- glScalef(radius, radius, 1.0)
- glCallList(drawing_globals.circleList)
- glEnable(GL_LIGHTING)
- glPopMatrix()
- return
-
-def drawFilledCircle(color, center, radius, normal):
- """
- Scale, rotate/translate the unit circle properly.
- Added a filled circle variant, piotr 080405
- """
- glMatrixMode(GL_MODELVIEW)
- glPushMatrix()
- glColor3fv(color)
- glDisable(GL_LIGHTING)
-
- glTranslatef(center[0], center[1], center[2])
- rQ = Q(V(0, 0, 1), normal)
- rotAngle = rQ.angle*180.0/pi
-
- #This may cause problems as proved before in Linear motor display.
- #rotation around (0, 0, 0)
- #if vlen(V(rQ.x, rQ.y, rQ.z)) < 0.00005:
- # rQ.x = 1.0
-
- glRotatef(rotAngle, rQ.x, rQ.y, rQ.z)
- glScalef(radius, radius, 1.0)
- glCallList(drawing_globals.filledCircleList)
- glEnable(GL_LIGHTING)
- glPopMatrix()
- return
-
-def drawLinearArrows(longScale):
- glCallList(drawing_globals.linearArrowList)
- newPos = drawing_globals.halfHeight*longScale
- glPushMatrix()
- glTranslate(0.0, 0.0, -newPos)
- glCallList(drawing_globals.linearArrowList)
- glPopMatrix()
- glPushMatrix()
- glTranslate(0.0, 0.0, newPos -2.0*drawing_globals.halfEdge)
- glCallList(drawing_globals.linearArrowList)
- glPopMatrix()
- return
-
-def drawLinearSign(color, center, axis, l, h, w):
- """Linear motion sign on the side of squa-linder """
- depthOffset = 0.005
- glPushMatrix()
- glColor3fv(color)
- glDisable(GL_LIGHTING)
- glTranslatef(center[0], center[1], center[2])
-
- ##Huaicai 1/17/05: To avoid rotate around (0, 0, 0), which causes
- ## display problem on some platforms
- angle = -acos(axis[2])*180.0/pi
- if (axis[2]*axis[2] >= 1.0):
- glRotate(angle, 0.0, 1.0, 0.0)
- else:
- glRotate(angle, axis[1], -axis[0], 0.0)
-
- glPushMatrix()
- glTranslate(h/2.0 + depthOffset, 0.0, 0.0)
- glPushMatrix()
- glScale(1.0, 1.0, l)
- glCallList(drawing_globals.linearLineList)
- glPopMatrix()
- if l < 2.6:
- sl = l/2.7
- glScale(1.0, sl, sl)
- if w < 1.0:
- glScale(1.0, w, w)
- drawLinearArrows(l)
- glPopMatrix()
-
- glPushMatrix()
- glTranslate(-h/2.0 - depthOffset, 0.0, 0.0)
- glRotate(180.0, 0.0, 0.0, 1.0)
- glPushMatrix()
- glScale(1.0, 1.0, l)
- glCallList(drawing_globals.linearLineList)
- glPopMatrix()
- if l < 2.6:
- glScale(1.0, sl, sl)
- if w < 1.0:
- glScale(1.0, w, w)
- drawLinearArrows(l)
- glPopMatrix()
-
- glPushMatrix()
- glTranslate(0.0, w/2.0 + depthOffset, 0.0)
- glRotate(90.0, 0.0, 0.0, 1.0)
- glPushMatrix()
- glScale(1.0, 1.0, l)
- glCallList(drawing_globals.linearLineList)
- glPopMatrix()
- if l < 2.6:
- glScale(1.0, sl, sl)
- if w < 1.0:
- glScale(1.0, w, w)
- drawLinearArrows(l)
- glPopMatrix()
-
- glPushMatrix()
- glTranslate(0.0, -w/2.0 - depthOffset, 0.0 )
- glRotate(-90.0, 0.0, 0.0, 1.0)
- glPushMatrix()
- glScale(1.0, 1.0, l)
- glCallList(drawing_globals.linearLineList)
- glPopMatrix()
- if l < 2.6:
- glScale(1.0, sl, sl)
- if w < 1.0:
- glScale(1.0, w, w)
- drawLinearArrows(l)
- glPopMatrix()
-
- glEnable(GL_LIGHTING)
- glPopMatrix()
- return
-
-def drawRotateSign(color, pos1, pos2, radius, rotation = 0.0):
- """Rotate sign on top of the caps of the cylinder """
- glPushMatrix()
- glColor3fv(color)
- vec = pos2-pos1
- axis = norm(vec)
- glTranslatef(pos1[0], pos1[1], pos1[2])
-
- ##Huaicai 1/17/05: To avoid rotate around (0, 0, 0), which causes
- ## display problem on some platforms
- angle = -acos(axis[2])*180.0/pi
- if (axis[2]*axis[2] >= 1.0):
- glRotate(angle, 0.0, 1.0, 0.0)
- else:
- glRotate(angle, axis[1], -axis[0], 0.0)
- glRotate(rotation, 0.0, 0.0, 1.0) #bruce 050518
- glScale(radius,radius,Numeric.dot(vec,vec)**.5)
-
- glLineWidth(2.0)
- glDisable(GL_LIGHTING)
- glCallList(drawing_globals.rotSignList)
- glEnable(GL_LIGHTING)
- glLineWidth(1.0)
-
- glPopMatrix()
- return
-
-def drawArrowHead(color,
- basePoint,
- drawingScale,
- unitBaseVector,
- unitHeightVector):
-
-
-
- arrowBase = drawingScale * 0.08
- arrowHeight = drawingScale * 0.12
- glDisable(GL_LIGHTING)
- glPushMatrix()
- glTranslatef(basePoint[0],basePoint[1],basePoint[2])
- point1 = V(0, 0, 0)
- point1 = point1 + unitHeightVector * arrowHeight
- point2 = unitBaseVector * arrowBase
- point3 = - unitBaseVector * arrowBase
- #Draw the arrowheads as filled triangles
- glColor3fv(color)
- glBegin(GL_POLYGON)
- glVertex3fv(point1)
- glVertex3fv(point2)
- glVertex3fv(point3)
- glEnd()
- glPopMatrix()
- glEnable(GL_LIGHTING)
-
-def drawSineWave(color, startPoint, endPoint, numberOfPoints, phaseAngle):
- """
- """
- pass
-
-def drawPolyLine(color, points):
- '''Draws a poly line passing through the given list of points'''
- glDisable(GL_LIGHTING)
- glColor3fv(color)
- glBegin(GL_LINE_STRIP)
- for v in points:
- glVertex3fv(v)
- glEnd()
-
- glEnable(GL_LIGHTING)
- return
-
-def drawPoint(color,
- point,
- pointSize = 3.0,
- isRound = True):
- """
- Draw a point using GL_POINTS.
- @param point: The x,y,z coordinate array/ vector of the point
- @type point: A or V
- @param pointSize: The point size to be used by glPointSize
- @type pointSize: float
- @param isRound: If True, the point will be drawn round otherwise square
- @type isRound: boolean
- """
- glDisable(GL_LIGHTING)
- glColor3fv(color)
- glPointSize(float(pointSize))
- if isRound:
- glEnable(GL_POINT_SMOOTH)
- glBegin(GL_POINTS)
- glVertex3fv(point)
- glEnd()
- if isRound:
- glDisable(GL_POINT_SMOOTH)
-
- glEnable(GL_LIGHTING)
- if pointSize != 1.0:
- glPointSize(1.0)
- return
-
-def drawTag(color, basePoint, endPoint, pointSize = 20.0):
- """
- Draw a tag (or a 'flag') as a line ending with a circle (like a balloon
- with a string). Note: The word 'Flag' is intentionally not used in the
- method nameto avoid potential confusion with a boolean flag.
-
- @param color: color of the tag
- @type color: A
- @param basePoint: The base point of the tag
- @type basePoint: V
- @param endPoint: The end point of the tag
- @type endPoint: V
- @param pointSize: The pointSize of the point to be drawin at the <endPoint>
- @type pointSize: float
-
- @see: GraphicsMode._drawTags where it is called (an example)
-
- """
- drawline(color, basePoint, endPoint)
- drawPoint(color, endPoint, pointSize = 20.0)
-
-def drawLineCube(color, pos, radius):
- vtIndices = [0,1,2,3, 0,4,5,1, 5,4,7,6, 6,7,3,2]
- glEnableClientState(GL_VERTEX_ARRAY)
- #bruce 051117 revised this
- glVertexPointer(3, GL_FLOAT, 0, drawing_globals.flatCubeVertices)
- #grantham 20051213 observations, reported/paraphrased by bruce 051215:
- # - should verify PyOpenGL turns Python float (i.e. C double) into C float
- # for OpenGL's GL_FLOAT array element type.
- # - note that GPUs are optimized for DrawElements types GL_UNSIGNED_INT and GL_UNSIGNED_SHORT.
- glDisable(GL_LIGHTING)
- glColor3fv(color)
- glPushMatrix()
- glTranslatef(pos[0], pos[1], pos[2])
- glScale(radius,radius,radius)
- glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices)
- #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[4])
- #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[8])
- #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[12])
- glPopMatrix()
- glEnable(GL_LIGHTING)
- glDisableClientState(GL_VERTEX_ARRAY)
- return
-
-def drawwirecube(color, pos, radius, lineWidth=3.0):
- glPolygonMode(GL_FRONT, GL_LINE)
- glPolygonMode(GL_BACK, GL_LINE)
- glDisable(GL_LIGHTING)
- glDisable(GL_CULL_FACE)
- glColor3fv(color)
- glPushMatrix()
- glTranslatef(pos[0], pos[1], pos[2])
- if type(radius) == type(1.0):
- glScale(radius,radius,radius)
- else:
- glScale(radius[0], radius[1], radius[2])
- glLineWidth(lineWidth)
- glCallList(drawing_globals.lineCubeList)
- glLineWidth(1.0) ## restore its state
- glPopMatrix()
- glEnable(GL_CULL_FACE)
- glEnable(GL_LIGHTING)
- glPolygonMode(GL_FRONT, GL_FILL)
- glPolygonMode(GL_BACK, GL_FILL) #bruce 050729 to help fix bug 835 or related bugs
- return
-
-def drawwirebox(color, pos, len):
- glPolygonMode(GL_FRONT, GL_LINE)
- glPolygonMode(GL_BACK, GL_LINE)
- glDisable(GL_LIGHTING)
- glDisable(GL_CULL_FACE)
- glColor3fv(color)
- glPushMatrix()
- glTranslatef(pos[0], pos[1], pos[2])
- glScale(len[0], len[1], len[2])
- glCallList(drawing_globals.CubeList)
- glPopMatrix()
- glEnable(GL_CULL_FACE)
- glEnable(GL_LIGHTING)
- glPolygonMode(GL_FRONT, GL_FILL)
- glPolygonMode(GL_BACK, GL_FILL) #bruce 050729 to help fix bug 835 or related bugs
- return
-
-def segstart(color):
- glDisable(GL_LIGHTING)
- glColor3fv(color)
- glBegin(GL_LINES)
- return
-
-def drawsegment(pos1,pos2):
- glVertex3fv(pos1)
- glVertex3fv(pos2)
- return
-
-def segend():
- glEnd()
- glEnable(GL_LIGHTING)
- return
-
-def drawAxis(color, pos1, pos2, width = 2): #Ninad 060907
- '''Draw chunk or jig axis'''
- #ninad060907 Note that this is different than draw
- #I may need this function to draw axis line. see its current implementation in
- #branch "ninad_060908_drawAxis_notAsAPropOfObject"
- glDisable(GL_LIGHTING)
- glColor3fv(color)
- glLineStipple(3, 0x1C47) # dash-dot-dash line
- glEnable(GL_LINE_STIPPLE)
- if width != 1:
- glLineWidth(width)
- glBegin(GL_LINES)
- glVertex(pos1[0], pos1[1], pos1[2])
- glVertex(pos2[0], pos2[1], pos2[2])
- glEnd()
- if width != 1:
- glLineWidth(1.0) # restore default state
- glDisable(GL_LINE_STIPPLE)
- glEnable(GL_LIGHTING)
- return
-
-def drawaxes(n,point,coloraxes=False, dashEnabled = False):
-
- n *= 0.5
- glPushMatrix()
- glTranslate(point[0], point[1], point[2])
- glDisable(GL_LIGHTING)
-
- if coloraxes:
- glColor3f(red[0], red[1], red[2])
- if dashEnabled:
- #ninad060921 Note that we will only support dotted origin axis
- #(hidden lines)but not POV axis. (as it could be annoying)
- glLineStipple(5, 0xAAAA)
- glEnable(GL_LINE_STIPPLE)
- glDisable(GL_DEPTH_TEST)
- else:
- glColor3f(darkgreen[0], darkgreen[1], darkgreen[2])
-
- glBegin(GL_LINES)
- glVertex(n,0,0)
- glVertex(-n,0,0)
- glColor3f(darkgreen[0], darkgreen[1], darkgreen[2])
- glVertex(0,n,0)
- glVertex(0,-n,0)
- if coloraxes: glColor3f(blue[0], blue[1], blue[2])
- else: glColor3f(darkgreen[0], darkgreen[1], darkgreen[2])
- glVertex(0,0,n)
- glVertex(0,0,-n)
- glEnd()
-
- if coloraxes:
- if dashEnabled:
- glDisable(GL_LINE_STIPPLE)
- glEnable(GL_DEPTH_TEST)
-
- glEnable(GL_LIGHTING)
- glPopMatrix()
- return
-
-def drawOriginAsSmallAxis(scale, origin, dashEnabled = False):
- """
- Draws a small wireframe version of the origin. It is rendered as a
- 3D point at (0, 0, 0) with 3 small axes extending from it in the positive
- X, Y, Z directions.
- """
- #Perhaps we should split this method into smaller methods? ninad060920
- #Notes:
- #1. drawing arrowheads implemented on 060918
- #2. ninad060921 Show the origin axes as dotted if behind the mode.
- #3. ninad060922 The arrow heads are drawn as wireframe cones if behind the object
- # the arrowhead size is slightly smaller (otherwise some portion of the
- # the wireframe arrow shows up!
- #3.Making origin non-zoomable is acheived by replacing
- #hardcoded 'n' with glpane's scale - ninad060922
-
- #ninad060922 in future , the following could be user preferences.
- if (dashEnabled):
- dashShrinkage = 0.9
- else:
- dashShrinkage=1
- x1, y1, z1 = scale * 0.01, scale * 0.01, scale * 0.01
- xEnd, yEnd, zEnd = scale * 0.04, scale * 0.09, scale * 0.025
- arrowBase = scale * 0.0075 * dashShrinkage
- arrowHeight = scale * 0.035 * dashShrinkage
- lineWidth = 1.0
-
- glPushMatrix()
-
- glTranslate(origin[0], origin[1], origin[2])
- glDisable(GL_LIGHTING)
- glLineWidth(lineWidth)
-
- gleNumSides = gleGetNumSides()
- #Code to show hidden lines of the origin if some model obscures it ninad060921
- if dashEnabled:
- glLineStipple(2, 0xAAAA)
- glEnable(GL_LINE_STIPPLE)
- glDisable(GL_DEPTH_TEST)
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
- gleSetNumSides(5)
- else:
- gleSetNumSides(10)
-
- glBegin(GL_LINES)
-
- #glColor3f(black)
- glColor3fv(lightblue)
-
- #start draw a point at origin .
- #ninad060922 is thinking about using GL_POINTS here
-
- glVertex(-x1, 0.0, 0.0)
- glVertex( x1, 0.0, 0.0)
- glVertex(0.0, -y1, 0.0)
- glVertex(0.0, y1, 0.0)
- glVertex(-x1, y1, z1)
- glVertex( x1, -y1, -z1)
- glVertex(x1, y1, z1)
- glVertex(-x1, -y1, -z1)
- glVertex(x1, y1, -z1)
- glVertex(-x1, -y1, z1)
- glVertex(-x1, y1, -z1)
- glVertex(x1, -y1, z1)
- #end draw a point at origin
-
- #start draw small origin axes
- #glColor3fv(darkred)
- glColor3fv(lightblue)
- glVertex(xEnd, 0.0, 0.0)
- glVertex( 0.0, 0.0, 0.0)
- #glColor3f(darkgreen[0], darkgreen[1], darkgreen[2])
- glColor3fv(lightblue)
- glVertex(0.0, yEnd, 0.0)
- glVertex(0.0, 0.0, 0.0)
- #glColor3f(blue[0], blue[1], blue[2])
- glColor3fv(lightblue)
- glVertex(0.0, 0.0, zEnd)
- glVertex(0.0, 0.0, 0.0)
- glEnd() #end draw lines
- glLineWidth(1.0)
-
- glPopMatrix() # end push matrix for drawing various lines in the origin and axes
-
- #start draw solid arrow heads for X , Y and Z axes
- glPushMatrix()
- glDisable(GL_CULL_FACE)
- #glColor3fv(darkred)
- glColor3fv(lightblue)
- glTranslatef(xEnd, 0.0, 0.0)
- glRotatef(90, 0.0, 1.0, 0.0)
-
- glePolyCone([[0, 0, -1], [0, 0, 0], [0, 0, arrowHeight], [0, 0, arrowHeight+1]], None, [arrowBase, arrowBase, 0, 0])
-
- glPopMatrix()
-
- glPushMatrix()
- #glColor3f(darkgreen)
- glColor3fv(lightblue)
- glTranslatef(0.0, yEnd, 0.0)
- glRotatef(-90, 1.0, 0.0, 0.0)
-
- glePolyCone([[0, 0, -1], [0, 0, 0], [0, 0, arrowHeight], [0, 0, arrowHeight+1]], None, [arrowBase, arrowBase, 0, 0])
-
- glPopMatrix()
-
- glPushMatrix()
- glColor3fv(lightblue)
- glTranslatef(0.0,0.0,zEnd)
-
- glePolyCone([[0, 0, -1], [0, 0, 0], [0, 0, arrowHeight], [0, 0, arrowHeight+1]], None, [arrowBase, arrowBase, 0, 0])
-
- #Disable line stipple and Enable Depth test
- if dashEnabled:
- glLineStipple(1, 0xAAAA)
- glDisable(GL_LINE_STIPPLE)
- glEnable(GL_DEPTH_TEST)
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
- gleSetNumSides(gleNumSides)
- glEnable(GL_CULL_FACE)
- glEnable(GL_LIGHTING)
- glPopMatrix()
- #end draw solid arrow heads for X , Y and Z axes
- return
-
-def drawDirectionArrow(color,
- tailPoint,
- arrowBasePoint,
- tailRadius,
- scale,
- flipDirection = False,
- opacity = 1.0,
- numberOfSides = 20
- ):
- """
- Draw a directional arrow staring at <tailPoint> with an endpoint decided
- by the vector between <arrowBasePoint> and <tailPoint>
- and the glpane scale <scale>
- @param color : The arrow color
- @type color: Array
- @param tailPoint: The point on the arrow tail where the arrow begins.
- @type tailPoint: V
- @param arrowBasePoint: A point on the arrow where the arrow head begins(??
- @type arrowBasePoint: V
- @param tailRadius: The radius of the arrow tail (cylinder radius
- representing the arrow tail)
- @type tailRaius: float
- @param opacity: The opacity decides the opacity (or transparent display)
- of the rendered arrow. By default it is rendered as a solid
- arrow. It varies between 0.0 to 1.0 ... 1.0 represents the
- solid arrow renderring style
- @type opacity: float
- @param numberOfSides: The total number of sides for the arrow head
- (a glePolycone) The default value if 20 (20 sided
- polycone)
- @type numberOfSides: int
- """
-
- vec = arrowBasePoint - tailPoint
- vec = scale*0.07*vec
- arrowBase = tailRadius*3.0
- arrowHeight = arrowBase*1.5
- axis = norm(vec)
-
- #as of 2008-03-03 scaledBasePoint is not used so commenting out.
- #(will be removed after more testing)
- ##scaledBasePoint = tailPoint + vlen(vec)*axis
- drawcylinder(color, tailPoint, arrowBasePoint, tailRadius, capped = True,
- opacity = opacity)
-
- ##pos = scaledBasePoint
- pos = arrowBasePoint
- arrowRadius = arrowBase
- gleSetNumSides(numberOfSides)
- drawpolycone(color, [[pos[0] - 1 * axis[0],
- pos[1] - 1 * axis[1],
- pos[2] - 1 * axis[2]],
- [pos[0],# - axis[0],
- pos[1], #- axis[1],
- pos[2]], #- axis[2]],
- [pos[0] + arrowHeight * axis[0],
- pos[1] + arrowHeight * axis[1],
- pos[2] + arrowHeight * axis[2]],
- [pos[0] + (arrowHeight + 1) * axis[0],
- pos[1] + (arrowHeight + 1) * axis[1],
- pos[2] + (arrowHeight + 1) * axis[2]]], # Point array (the two end
- # points not drawn)
- [arrowRadius, arrowRadius, 0, 0], # Radius array
- opacity = opacity
- )
- #reset the gle number of sides to the gle default of '20'
- gleSetNumSides(20)
-
-
-def findCell(pt, latticeType):
- """Return the cell which contains the point <pt> """
- if latticeType == 'DIAMOND':
- a = 0; cellX = cellY = cellZ = drawing_globals.DiGridSp
- elif latticeType == 'LONSDALEITE':
- a = 1
- cellX = drawing_globals.XLen
- cellY = drawing_globals.YLen
- cellZ = drawing_globals.ZLen
-
- i = int(floor(pt[0]/cellX))
- j = int(floor(pt[1]/cellY))
- k = int(floor(pt[2]/cellZ))
-
- orig = V(i*cellX, j*cellY, k*cellZ)
-
- return orig, sp1
-
-def genDiam(bblo, bbhi, latticeType):
- """Generate a list of possible atom positions within the area enclosed by (bblo, bbhi).
- <Return>: A list of unit cells"""
- if latticeType == 'DIAMOND':
- a = 0; cellX = cellY = cellZ = drawing_globals.DiGridSp
- elif latticeType == 'LONSDALEITE':
- a = 1
- cellX = drawing_globals.XLen
- cellY = drawing_globals.YLen
- cellZ = drawing_globals.ZLen
-
- allCells = []
- for i in range(int(floor(bblo[0]/cellX)),
- int(ceil(bbhi[0]/cellX))):
- for j in range(int(floor(bblo[1]/cellY)),
- int(ceil(bbhi[1]/cellY))):
- for k in range(int(floor(bblo[2]/cellZ)),
- int(ceil(bbhi[2]/cellZ))):
- off = V(i*cellX, j*cellY, k*cellZ)
- if a == 0: allCells += [drawing_globals.digrid + off]
- elif a ==1: allCells += [drawing_globals.lonsEdges + off]
- return allCells
-
-
-def drawGrid(scale, center, latticeType):
- """
- Construct the grid model and show as position references for cookies.
- The model is build around "pov" and has size of 2*"scale" on each of
- the (x, y, z) directions.
-
- @note: This should be optimized later.
- For "scale = 200", it takes about 1479623 loops. ---Huaicai
- """
- glDisable(GL_LIGHTING)
-
- # bruce 041201:
- # Quick fix to prevent "hang" from drawing too large a cookieMode grid
- # with our current cubic algorithm (bug 8). The constant 120.0 is still on
- # the large side in terms of responsiveness -- on a 1.8GHz iMac G5 it can
- # take many seconds to redraw the largest grid, or to update a selection
- # rectangle during a drag. I also tried 200.0 but that was way too large.
- # Since some users have slower machines, I'll be gentle and put 90.0 here.
- # Someday we need to fix the alg to be quadratic by teaching this code
- # (and the cookie baker code too) about the eyespace clipping planes.
- # Once we support user prefs, this should be one of them (if the alg is
- # not fixed by then).
-
- MAX_GRID_SCALE = 90.0
- if scale > MAX_GRID_SCALE:
- scale = MAX_GRID_SCALE
-
- if latticeType == 'DIAMOND':
- cellX = cellY = cellZ = drawing_globals.DiGridSp
- elif latticeType == 'LONSDALEITE':
- cellX = drawing_globals.XLen
- cellY = drawing_globals.YLen
- cellZ = drawing_globals.ZLen
-
- bblo = center - scale
- bbhi = center + scale
- i1 = int(floor(bblo[0]/cellX))
- i2 = int(ceil(bbhi[0]/cellX))
- j1 = int(floor(bblo[1]/cellY))
- j2 = int(ceil(bbhi[1]/cellY))
- k1 = int(floor(bblo[2]/cellZ))
- k2 = int(ceil(bbhi[2]/cellZ))
- glPushMatrix()
- glTranslate(i1*cellX, j1*cellY, k1*cellZ)
- for i in range(i1, i2):
- glPushMatrix()
- for j in range(j1, j2):
- glPushMatrix()
- for k in range(k1, k2):
- if latticeType == 'DIAMOND':
- glCallList(drawing_globals.diamondGridList)
- else:
- glCallList(drawing_globals.lonsGridList)
- glTranslate(0.0, 0.0, cellZ)
- glPopMatrix()
- glTranslate(0.0, cellY, 0.0)
- glPopMatrix()
- glTranslate(cellX, 0.0, 0.0)
- glPopMatrix()
- glEnable(GL_LIGHTING)
-
- #drawCubeCell(V(1, 0, 0))
- return
-
-
-def drawrectangle(pt1, pt2, rt, up, color):
- """
- Draws a (hollow) rectangle outline of the given I{color}.
-
- @param pt1: First corner of the rectangle.
- @type pt1: Point
-
- @param pt1: Opposite corner of the rectangle.
- @type pt1: Point
-
- @param rt: Right vector of the glpane.
- @type rt: Unit vector
-
- @param up: Right vector of the glpane.
- @type up: Unit vector
-
- @param color: Color
- @type color: color
- """
- glColor3f(color[0], color[1], color[2])
- glDisable(GL_LIGHTING)
- c2 = pt1 + rt * Numeric.dot(rt, pt2 - pt1)
- c3 = pt1 + up * Numeric.dot(up, pt2 - pt1)
- glBegin(GL_LINE_LOOP)
- glVertex(pt1[0], pt1[1], pt1[2])
- glVertex(c2[0], c2[1], c2[2])
- glVertex(pt2[0], pt2[1], pt2[2])
- glVertex(c3[0], c3[1], c3[2])
- glEnd()
- glEnable(GL_LIGHTING)
-
-#bruce & wware 060404: drawRubberBand apparently caused bug 1814 (Zoom Tool hanging some Macs, requiring power toggle)
-# so it should not be used until debugged. Use drawrectangle instead. (For an example of how to translate between them,
-# see ZoomMode.py rev 1.32 vs 1.31 in ViewCVS.) That bug was only repeatable on Bruce's & Will's iMacs G5.
-#
-# Bruce's speculations (not very definite; no evidence for them at all) about possible causes of the bug in drawRubberBand:
-# - use of glVertex instead of glVertex3f or so??? This seems unlikely, since we have other uses of it,
-# but perhaps they work due to different arg types.
-# - use of GL_LINE_LOOP within OpenGL xor mode, and bugs in some OpenGL drivers?? I didn't check whether cookieMode does this too.
-##def drawRubberBand(pt1, pt2, c2, c3, color):
-## """Huaicai: depth test should be disabled to make the xor work """
-## glBegin(GL_LINE_LOOP)
-## glVertex(pt1[0],pt1[1],pt1[2])
-## glVertex(c2[0],c2[1],c2[2])
-## glVertex(pt2[0],pt2[1],pt2[2])
-## glVertex(c3[0],c3[1],c3[2])
-## glEnd()
-## return
-
-
-# Wrote drawbrick for the Linear Motor. Mark [2004-10-10]
-def drawbrick(color, center, axis, l, h, w, opacity = 1.0):
-
- if len(color) == 3:
- color = (color[0], color[1], color[2], opacity)
-
- if opacity != 1.0:
- glDepthMask(GL_FALSE)
- glEnable(GL_BLEND)
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
-
-
- apply_material(color)
- glPushMatrix()
- glTranslatef(center[0], center[1], center[2])
-
- ##Huaicai 1/17/05: To avoid rotate around (0, 0, 0), which causes
- ## display problem on some platforms
- angle = -acos(axis[2])*180.0/pi
- if (axis[2]*axis[2] >= 1.0):
- glRotate(angle, 0.0, 1.0, 0.0)
- else:
- glRotate(angle, axis[1], -axis[0], 0.0)
-
-
-
- glScale(h, w, l)
- #bruce 060302 revised the contents of solidCubeList while fixing bug 1595
- glCallList(drawing_globals.solidCubeList)
-
- if opacity != 1.0:
- glDisable(GL_BLEND)
- glDepthMask(GL_TRUE)
-
- glPopMatrix()
- return
-
-def drawLineLoop(color,lines, width = 1):
- glDisable(GL_LIGHTING)
- glColor3fv(color)
- glLineWidth(width)
- glBegin(GL_LINE_LOOP)
- for v in lines:
- glVertex3fv(v)
- glEnd()
- glEnable(GL_LIGHTING)
- #reset the glLineWidth to 1
- if width!=1:
- glLineWidth(1)
- return
-
-
-def drawlinelist(color,lines):
- glDisable(GL_LIGHTING)
- glColor3fv(color)
- glBegin(GL_LINES)
- for v in lines:
- glVertex3fv(v)
- glEnd()
- glEnable(GL_LIGHTING)
- return
-
-cubeLines = A([[-1,-1,-1], [-1,-1, 1],
- [-1, 1,-1], [-1, 1, 1],
- [ 1,-1,-1], [ 1,-1, 1],
- [ 1, 1,-1], [ 1, 1, 1],
-
- [-1,-1,-1], [-1, 1,-1],
- [-1,-1, 1], [-1, 1, 1],
- [ 1,-1,-1], [ 1, 1,-1],
- [ 1,-1, 1], [ 1, 1, 1],
-
- [-1,-1,-1], [ 1,-1,-1],
- [-1,-1, 1], [ 1,-1, 1],
- [-1, 1,-1], [ 1, 1,-1],
- [-1, 1, 1], [ 1, 1, 1]])
-
-def drawCubeCell(color):
- vs = [[sp0, sp0, sp0], [sp4, sp0, sp0], [sp4, sp4, sp0], [sp0, sp4, sp0],
- [sp0, sp0, sp4], [sp4, sp0, sp4], [sp4, sp4, sp4], [sp0, sp4, sp4]]
-
- glDisable(GL_LIGHTING)
- glColor3fv(color)
- glBegin(GL_LINE_LOOP)
- for ii in range(4):
- glVertex3fv(vs[ii])
- glEnd()
-
- glBegin(GL_LINE_LOOP)
- for ii in range(4, 8):
- glVertex3fv(vs[ii])
- glEnd()
-
- glBegin(GL_LINES)
- for ii in range(4):
- glVertex3fv(vs[ii])
- glVertex3fv(vs[ii+4])
- glEnd()
-
- glEnable(GL_LIGHTING)
- return
-
-def drawPlane(color, w, h, textureReady, opacity, SOLID=False, pickCheckOnly=False):
- '''Draw polygon with size of <w>*<h> and with color <color>. Optionally, it could be texuture mapped, translucent.
- @pickCheckOnly This is used to draw the geometry only, used for OpenGL pick selection purpose.'''
- vs = [[-0.5, 0.5, 0.0], [-0.5, -0.5, 0.0], [0.5, -0.5, 0.0], [0.5, 0.5, 0.0]]
- vt = [[0.0, 1.0], [0.0, 0.0], [1.0, 0.0], [1.0, 1.0]]
-
- glDisable(GL_LIGHTING)
- glColor4fv(list(color) + [opacity])
-
- glPushMatrix()
- glScalef(w, h, 1.0)
-
- if SOLID:
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
- else:
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
- glDisable(GL_CULL_FACE)
-
- if not pickCheckOnly:
- glDepthMask(GL_FALSE) # This makes sure translucent object will not occlude another translucent object
- glEnable(GL_BLEND)
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
-
- if textureReady:
- glEnable(GL_TEXTURE_2D)
-
- glBegin(GL_QUADS)
- for ii in range(len(vs)):
- t = vt[ii]; v = vs[ii]
- if textureReady:
- glTexCoord2fv(t)
- glVertex3fv(v)
- glEnd()
-
- if not pickCheckOnly:
- if textureReady:
- glDisable(GL_TEXTURE_2D)
-
- glDisable(GL_BLEND)
- glDepthMask(GL_TRUE)
-
- glEnable(GL_CULL_FACE)
- if not SOLID:
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
-
- glPopMatrix()
- glEnable(GL_LIGHTING)
- return
-
-def drawFullWindow(vtColors):
- """Draw gradient background color.
- <vtColors> is a 4 element list specifying colors for the
- left-down, right-down, right-up, left-up window corners.
- To draw the full window, the modelview and projection should be set in identity.
- """
- from utilities.constants import GL_FAR_Z
- glDisable(GL_LIGHTING)
-
- glBegin(GL_QUADS)
- glColor3fv(vtColors[0])
- glVertex3f(-1, -1, GL_FAR_Z)
- glColor3fv(vtColors[1])
- glVertex3f(1, -1, GL_FAR_Z)
- glColor3fv(vtColors[2])
- glVertex3f(1, 1, GL_FAR_Z)
- glColor3fv(vtColors[3])
- glVertex3f(-1, 1, GL_FAR_Z)
- glEnd()
-
- glEnable(GL_LIGHTING)
- return
-
-def drawtext(text, color, origin, point_size, glpane):
- """
- """
- # see also: _old_code_for_drawing_text()
-
- if not text:
- return
-
- glDisable(GL_LIGHTING)
- glDisable(GL_DEPTH_TEST)
-
- from PyQt4.Qt import QFont, QString, QColor
- font = QFont( QString("Helvetica"), point_size)
- #glpane.qglColor(QColor(75, 75, 75))
- from widgets.widget_helpers import RGBf_to_QColor
- glpane.qglColor(RGBf_to_QColor(color))
- glpane.renderText(origin[0], origin[1], origin[2], QString(text), font)
-
- glEnable(GL_DEPTH_TEST)
- glEnable(GL_LIGHTING)
- return
-
-##Junk code###
-## The following code used to be for drawing text on a QGLWidget --
-# some of it might still be useful if integrated into drawtext() above
-# [moved here from elementColors.py and slightly cleaned up by bruce 080223]
-def _old_code_for_drawing_text(glpane):
- self = glpane
- glDisable(GL_LIGHTING)
- glDisable(GL_DEPTH_TEST)
- self.qglColor(QColor(0, 0, 0))
- font = QFont( QString("Times"), 10)
- text = QString('Rvdw = ' + str(self.rad))
- fontMecs = QFontMetrics(font)
- strWd = fontMecs.width(text)
- strHt = fontMecs.height()
- w = self.width/2 - strWd/2
- h = self.height - strHt/2
- self.renderText(w, h, text, font)
- glEnable(GL_DEPTH_TEST)
- glEnable(GL_LIGHTING)
-
-def drawcylinder_wireframe(color, end1, end2, radius): #bruce 060608
- "draw a wireframe cylinder (not too pretty, definitely could look nicer, but it works)"
- # display polys as their edges (see drawer.py's drawwirecube or Jig.draw for related code)
- # (probably we should instead create a suitable lines display list,
- # or even use a wire-frame-like texture so various lengths work well)
- glPolygonMode(GL_FRONT, GL_LINE)
- glPolygonMode(GL_BACK, GL_LINE)
- glDisable(GL_LIGHTING)
- glDisable(GL_CULL_FACE) # this makes motors look too busy, but without it, they look too weird (which seems worse)
- try:
- drawcylinder(color, end1, end2, radius) ##k not sure if this color will end up controlling the edge color; we hope it will
- except:
- debug.print_compact_traceback("bug, ignored: ")
- # the following assumes that we are never called as part of a jig's drawing method,
- # or it will mess up drawing of the rest of the jig if it's disabled
- glEnable(GL_CULL_FACE)
- glEnable(GL_LIGHTING)
- glPolygonMode(GL_FRONT, GL_FILL)
- glPolygonMode(GL_BACK, GL_FILL) # could probably use GL_FRONT_AND_BACK
- return
-
-def drawsurface_wireframe(color, pos, radius, tm, nm):
- glPolygonMode(GL_FRONT, GL_LINE)
- glPolygonMode(GL_BACK, GL_LINE)
- glDisable(GL_LIGHTING)
- glDisable(GL_CULL_FACE)
- try:
- drawsurface(color, pos, radius, tm, nm)
- except:
- debug.print_compact_traceback("bug, ignored: ")
- glEnable(GL_CULL_FACE)
- glEnable(GL_LIGHTING)
- glPolygonMode(GL_FRONT, GL_FILL)
- glPolygonMode(GL_BACK, GL_FILL)
- return
-
-def renderSurface(surfaceEntities, surfaceNormals):
- ####@@@@ bruce 060927 comments:
- # - The color needs to come before the vertex. I fixed that, but left a debug_pref that can change it
- # so you can see the effect of that bug before it was fixed. (Same for the normal, but it already did come before.)
- # - I suspect normals are not used (when nc > 0) due to lighting being off. But if it's on, colors are not used.
- # I saw that problem before, and we had to use apply_material instead, to set color; I'm not sure why,
- # it might just be due to specific OpenGL settings we make for other purposes. So I'll use drawer.apply_material(color)
- # (again with a debug pref to control that).
- # The effect of the default debug_pref settings is that it now works properly with color -- but only for the 2nd chunk,
- # if you create two, and not at all if you create only one. I don't know why it doesn't work for the first chunk.
- (entityIndex, surfacePoints, surfaceColors) = surfaceEntities
- e0 = entityIndex[0]
- n = len(e0)
- nc = len(surfaceColors)
- if 1:
- ### bruce 060927 debug code; when done debugging, we can change them to constants & simplify the code that uses them.
- from utilities.debug_prefs import debug_pref, Choice_boolean_True, Choice_boolean_False
- disable_lighting = debug_pref("surface: disable lighting?", Choice_boolean_False)
- if nc:
- color_first = debug_pref("surface: color before vertex?", Choice_boolean_True)
- use_apply_material = debug_pref("surface: use apply_material?", Choice_boolean_True)
- ## old code was equivalent to disable_lighting = (nc > 0)
- def use_color(color): #bruce 060927 split this out, so we can change how we apply color in a single place in the code
- if use_apply_material:
- apply_material(color) # This makes the colors visible even when lighting is enabled.
- else:
- glColor3fv(color) # Old code did this. These colors are only visible when lighting is not enabled.
- return
- def onevert(vertex_index): #bruce 060927 split this out, for code clarity, and so debug prefs are used in only one place
- glNormal3fv(surfaceNormals[vertex_index])
- if nc > 0 and color_first: use_color(surfaceColors[vertex_index]) # this needs to be done before glVertex3fv
- glVertex3fv(surfacePoints[vertex_index])
- if nc > 0 and not color_first: use_color(surfaceColors[vertex_index]) # old code did it here -- used wrong colors sometimes
- return
- ## if nc > 0 : glDisable(GL_LIGHTING)
- if disable_lighting: glDisable(GL_LIGHTING)
- if n == 3:
- glBegin(GL_TRIANGLES)
- for entity in entityIndex:
- onevert(entity[0])
- onevert(entity[1])
- onevert(entity[2])
- glEnd()
- else:
- glBegin(GL_QUADS)
- for entity in entityIndex:
- onevert(entity[0])
- onevert(entity[1])
- onevert(entity[2])
- onevert(entity[3])
- glEnd()
- if disable_lighting: glEnable(GL_LIGHTING)
- return
-
-# end
diff --git a/cad/src/graphics/drawing/drawers.py b/cad/src/graphics/drawing/drawers.py
new file mode 100755
index 000000000..e3cf5460f
--- /dev/null
+++ b/cad/src/graphics/drawing/drawers.py
@@ -0,0 +1,1158 @@
+# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
+"""
+drawers.py - Miscellaneous drawing functions that are not used as primitives.
+
+@version: $Id$
+@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
+
+History:
+
+Originated by Josh as drawer.py .
+
+Various developers extended it since then.
+
+Brad G. added ColorSorter features.
+
+At some point Bruce partly cleaned up the use of display lists.
+
+071030 bruce split some functions and globals into draw_grid_lines.py
+and removed some obsolete functions.
+
+080210 russ Split the single display-list into two second-level lists (with and
+without color) and a set of per-color sublists so selection and hover-highlight
+can over-ride Chunk base colors. ColorSortedDisplayList is now a class in the
+parent's displist attr to keep track of all that stuff.
+
+080311 piotr Added a "drawpolycone_multicolor" function for drawing polycone
+tubes with per-vertex colors (necessary for DNA display style)
+
+080313 russ Added triangle-strip icosa-sphere constructor, "getSphereTriStrips".
+
+080420 piotr Solved highlighting and selection problems for multi-colored
+objects (e.g. rainbow colored DNA structures).
+
+080519 russ pulled the globals into a drawing_globals module and broke drawer.py
+into 10 smaller chunks: glprefs.py setup_draw.py shape_vertices.py
+ColorSorter.py CS_workers.py CS_ShapeList.py CS_draw_primitives.py drawers.py
+gl_lighting.py gl_buffers.py
+"""
+
+import os
+import sys
+
+# the imports from math vs. Numeric are as discovered in existing code
+# as of 2007/06/25. It's not clear why acos is coming from math...
+from math import floor, ceil, acos, atan2
+import Numeric
+from Numeric import sin, cos, sqrt, pi
+degreesPerRadian = 180.0 / pi
+
+# russ 080519 No doubt many of the following imports are unused.
+# When the dust settles, the unnecessary ones will be removed.
+from OpenGL.GL import GL_AMBIENT
+from OpenGL.GL import GL_AMBIENT_AND_DIFFUSE
+from OpenGL.GL import glAreTexturesResident
+from OpenGL.GL import GL_ARRAY_BUFFER_ARB
+from OpenGL.GL import GL_BACK
+from OpenGL.GL import glBegin
+from OpenGL.GL import glBindTexture
+from OpenGL.GL import GL_BLEND
+from OpenGL.GL import glBlendFunc
+from OpenGL.GL import glCallList
+from OpenGL.GL import glColor3f
+from OpenGL.GL import glColor3fv
+from OpenGL.GL import glColor4fv
+from OpenGL.GL import GL_COLOR_MATERIAL
+from OpenGL.GL import GL_COMPILE
+from OpenGL.GL import GL_COMPILE_AND_EXECUTE
+from OpenGL.GL import GL_CONSTANT_ATTENUATION
+from OpenGL.GL import GL_CULL_FACE
+from OpenGL.GL import GL_CURRENT_BIT
+from OpenGL.GL import glDeleteLists
+from OpenGL.GL import glDeleteTextures
+from OpenGL.GL import glDepthMask
+from OpenGL.GL import GL_DEPTH_TEST
+from OpenGL.GL import GL_DIFFUSE
+from OpenGL.GL import glDisable
+from OpenGL.GL import glDisableClientState
+from OpenGL.GL import glDrawArrays
+from OpenGL.GL import glDrawElements
+from OpenGL.GL import glDrawElementsub
+from OpenGL.GL import glDrawElementsui
+from OpenGL.GL import glDrawElementsus
+from OpenGL.GL import GL_ELEMENT_ARRAY_BUFFER_ARB
+from OpenGL.GL import glEnable
+from OpenGL.GL import glEnableClientState
+from OpenGL.GL import glEnd
+from OpenGL.GL import glEndList
+from OpenGL.GL import GL_EXTENSIONS
+from OpenGL.GL import GL_FALSE
+from OpenGL.GL import GL_FILL
+from OpenGL.GL import glFinish
+from OpenGL.GL import GL_FLOAT
+from OpenGL.GL import GL_FOG
+from OpenGL.GL import GL_FOG_COLOR
+from OpenGL.GL import GL_FOG_END
+from OpenGL.GL import GL_FOG_MODE
+from OpenGL.GL import GL_FOG_START
+from OpenGL.GL import GL_FRONT
+from OpenGL.GL import GL_FRONT_AND_BACK
+from OpenGL.GL import glGenLists
+from OpenGL.GL import glGenTextures
+from OpenGL.GL import glGetString
+from OpenGL.GL import GL_LIGHT0
+from OpenGL.GL import GL_LIGHT1
+from OpenGL.GL import GL_LIGHT2
+from OpenGL.GL import glLightf
+from OpenGL.GL import glLightfv
+from OpenGL.GL import GL_LIGHTING
+from OpenGL.GL import GL_LINE
+from OpenGL.GL import GL_LINEAR
+from OpenGL.GL import GL_LINE_LOOP
+from OpenGL.GL import GL_LINES
+from OpenGL.GL import GL_LINE_SMOOTH
+from OpenGL.GL import glLineStipple
+from OpenGL.GL import GL_LINE_STIPPLE
+from OpenGL.GL import GL_LINE_STRIP
+from OpenGL.GL import glLineWidth
+from OpenGL.GL import glLoadIdentity
+from OpenGL.GL import glMaterialf
+from OpenGL.GL import glMaterialfv
+from OpenGL.GL import glMatrixMode
+from OpenGL.GL import GL_MODELVIEW
+from OpenGL.GL import glNewList
+from OpenGL.GL import glNormal3fv
+from OpenGL.GL import glNormalPointer
+from OpenGL.GL import glNormalPointerf
+from OpenGL.GL import GL_NORMAL_ARRAY
+from OpenGL.GL import GL_ONE_MINUS_SRC_ALPHA
+from OpenGL.GL import glPointSize
+from OpenGL.GL import GL_POINTS
+from OpenGL.GL import GL_POINT_SMOOTH
+from OpenGL.GL import GL_POLYGON
+from OpenGL.GL import glPolygonMode
+from OpenGL.GL import glPopAttrib
+from OpenGL.GL import glPopMatrix
+from OpenGL.GL import glPopName
+from OpenGL.GL import GL_POSITION
+from OpenGL.GL import glPushAttrib
+from OpenGL.GL import glPushMatrix
+from OpenGL.GL import glPushName
+from OpenGL.GL import GL_QUADS
+from OpenGL.GL import GL_QUAD_STRIP
+from OpenGL.GL import GL_RENDERER
+from OpenGL.GL import GL_RGBA
+from OpenGL.GL import glRotate
+from OpenGL.GL import glRotatef
+from OpenGL.GL import GL_SHININESS
+from OpenGL.GL import GL_SPECULAR
+from OpenGL.GL import GL_SRC_ALPHA
+from OpenGL.GL import GL_STATIC_DRAW
+from OpenGL.GL import glTexCoord2f
+from OpenGL.GL import glTexCoord2fv
+from OpenGL.GL import GL_TEXTURE_2D
+from OpenGL.GL import glTranslate
+from OpenGL.GL import glTranslatef
+from OpenGL.GL import GL_TRIANGLES
+from OpenGL.GL import GL_TRIANGLE_STRIP
+from OpenGL.GL import GL_TRUE
+from OpenGL.GL import GL_UNSIGNED_BYTE
+from OpenGL.GL import GL_UNSIGNED_SHORT
+from OpenGL.GL import GL_VENDOR
+from OpenGL.GL import GL_VERSION
+from OpenGL.GL import glVertex
+from OpenGL.GL import glVertex2f
+from OpenGL.GL import glVertex3f
+from OpenGL.GL import glVertex3fv
+from OpenGL.GL import GL_VERTEX_ARRAY
+from OpenGL.GL import glVertexPointer
+from OpenGL.GL import glVertexPointerf
+
+from OpenGL.GLU import gluBuild2DMipmaps
+
+from geometry.VQT import norm, vlen, V, Q, A
+
+from utilities.constants import white, blue, red
+from utilities.constants import darkgreen, lightblue
+from utilities.constants import DIAMOND_BOND_LENGTH
+from utilities.prefs_constants import material_specular_highlights_prefs_key
+from utilities.prefs_constants import material_specular_shininess_prefs_key
+from utilities.prefs_constants import material_specular_finish_prefs_key
+from utilities.prefs_constants import material_specular_brightness_prefs_key
+
+from utilities.debug_prefs import Choice
+import utilities.debug as debug # for debug.print_compact_traceback
+
+#=
+
+import graphics.drawing.drawing_globals as drawing_globals
+from graphics.drawing.gl_lighting import apply_material
+
+try:
+ from OpenGL.GLE import glePolyCone, gleGetNumSides, gleSetNumSides
+except:
+ print "GLE module can't be imported. Now trying _GLE"
+ from OpenGL._GLE import glePolyCone, gleGetNumSides, gleSetNumSides
+
+# Check if the gleGet/SetNumSides function is working on this install, and if
+# not, alias it to an effective no-op. Checking method is as recommended in
+# an OpenGL exception reported by Brian [070622]:
+# OpenGL.error.NullFunctionError: Attempt to call an
+# undefined function gleGetNumSides, check for
+# bool(gleGetNumSides) before calling
+# The underlying cause of this (described by Brian) is that the computer's OpenGL
+# has the older gleGetNumSlices (so it supports the functionality), but PyOpenGL
+# binds (only) to the newer gleGetNumSides. Given the PyOpenGL we're using,
+# there's no way to access gleGetNumSlices, but in the future we might patch it
+# to let us do that when this happens. I [bruce 070629] think Brian said this is
+# only an issue on Macs.
+if not bool(gleGetNumSides):
+ print "fyi: gleGetNumSides is not supported by the OpenGL pre-installed on this computer."
+ gleGetNumSides = int
+ gleSetNumSides = int
+
+try:
+ from OpenGL.GL import glScale
+except:
+ # The installed version of OpenGL requires argument-typed glScale calls.
+ from OpenGL.GL import glScalef as glScale
+
+from OpenGL.GL import glScalef
+ # Note: this is NOT redundant with the above import of glScale --
+ # without it, displaying an ESP Image gives a NameError traceback
+ # and doesn't work. [Fixed by bruce 070703; bug caught by Eric M using
+ # PyChecker; bug introduced sometime after A9.1 went out.]
+
+# ==
+
+def drawCircle(color, center, radius, normal):
+ """Scale, rotate/translate the unit circle properly """
+ glMatrixMode(GL_MODELVIEW)
+ glPushMatrix()
+ glColor3fv(color)
+ glDisable(GL_LIGHTING)
+
+ glTranslatef(center[0], center[1], center[2])
+ rQ = Q(V(0, 0, 1), normal)
+ rotAngle = rQ.angle*180.0/pi
+
+ #This may cause problems as proved before in Linear motor display.
+ #rotation around (0, 0, 0)
+ #if vlen(V(rQ.x, rQ.y, rQ.z)) < 0.00005:
+ # rQ.x = 1.0
+
+ glRotatef(rotAngle, rQ.x, rQ.y, rQ.z)
+ glScalef(radius, radius, 1.0)
+ glCallList(drawing_globals.circleList)
+ glEnable(GL_LIGHTING)
+ glPopMatrix()
+ return
+
+def drawFilledCircle(color, center, radius, normal):
+ """
+ Scale, rotate/translate the unit circle properly.
+ Added a filled circle variant, piotr 080405
+ """
+ glMatrixMode(GL_MODELVIEW)
+ glPushMatrix()
+ glColor3fv(color)
+ glDisable(GL_LIGHTING)
+
+ glTranslatef(center[0], center[1], center[2])
+ rQ = Q(V(0, 0, 1), normal)
+ rotAngle = rQ.angle*180.0/pi
+
+ #This may cause problems as proved before in Linear motor display.
+ #rotation around (0, 0, 0)
+ #if vlen(V(rQ.x, rQ.y, rQ.z)) < 0.00005:
+ # rQ.x = 1.0
+
+ glRotatef(rotAngle, rQ.x, rQ.y, rQ.z)
+ glScalef(radius, radius, 1.0)
+ glCallList(drawing_globals.filledCircleList)
+ glEnable(GL_LIGHTING)
+ glPopMatrix()
+ return
+
+def drawLinearArrows(longScale):
+ glCallList(drawing_globals.linearArrowList)
+ newPos = drawing_globals.halfHeight*longScale
+ glPushMatrix()
+ glTranslate(0.0, 0.0, -newPos)
+ glCallList(drawing_globals.linearArrowList)
+ glPopMatrix()
+ glPushMatrix()
+ glTranslate(0.0, 0.0, newPos -2.0*drawing_globals.halfEdge)
+ glCallList(drawing_globals.linearArrowList)
+ glPopMatrix()
+ return
+
+def drawLinearSign(color, center, axis, l, h, w):
+ """Linear motion sign on the side of squa-linder """
+ depthOffset = 0.005
+ glPushMatrix()
+ glColor3fv(color)
+ glDisable(GL_LIGHTING)
+ glTranslatef(center[0], center[1], center[2])
+
+ ##Huaicai 1/17/05: To avoid rotate around (0, 0, 0), which causes
+ ## display problem on some platforms
+ angle = -acos(axis[2])*180.0/pi
+ if (axis[2]*axis[2] >= 1.0):
+ glRotate(angle, 0.0, 1.0, 0.0)
+ else:
+ glRotate(angle, axis[1], -axis[0], 0.0)
+
+ glPushMatrix()
+ glTranslate(h/2.0 + depthOffset, 0.0, 0.0)
+ glPushMatrix()
+ glScale(1.0, 1.0, l)
+ glCallList(drawing_globals.linearLineList)
+ glPopMatrix()
+ if l < 2.6:
+ sl = l/2.7
+ glScale(1.0, sl, sl)
+ if w < 1.0:
+ glScale(1.0, w, w)
+ drawLinearArrows(l)
+ glPopMatrix()
+
+ glPushMatrix()
+ glTranslate(-h/2.0 - depthOffset, 0.0, 0.0)
+ glRotate(180.0, 0.0, 0.0, 1.0)
+ glPushMatrix()
+ glScale(1.0, 1.0, l)
+ glCallList(drawing_globals.linearLineList)
+ glPopMatrix()
+ if l < 2.6:
+ glScale(1.0, sl, sl)
+ if w < 1.0:
+ glScale(1.0, w, w)
+ drawLinearArrows(l)
+ glPopMatrix()
+
+ glPushMatrix()
+ glTranslate(0.0, w/2.0 + depthOffset, 0.0)
+ glRotate(90.0, 0.0, 0.0, 1.0)
+ glPushMatrix()
+ glScale(1.0, 1.0, l)
+ glCallList(drawing_globals.linearLineList)
+ glPopMatrix()
+ if l < 2.6:
+ glScale(1.0, sl, sl)
+ if w < 1.0:
+ glScale(1.0, w, w)
+ drawLinearArrows(l)
+ glPopMatrix()
+
+ glPushMatrix()
+ glTranslate(0.0, -w/2.0 - depthOffset, 0.0 )
+ glRotate(-90.0, 0.0, 0.0, 1.0)
+ glPushMatrix()
+ glScale(1.0, 1.0, l)
+ glCallList(drawing_globals.linearLineList)
+ glPopMatrix()
+ if l < 2.6:
+ glScale(1.0, sl, sl)
+ if w < 1.0:
+ glScale(1.0, w, w)
+ drawLinearArrows(l)
+ glPopMatrix()
+
+ glEnable(GL_LIGHTING)
+ glPopMatrix()
+ return
+
+def drawRotateSign(color, pos1, pos2, radius, rotation = 0.0):
+ """Rotate sign on top of the caps of the cylinder """
+ glPushMatrix()
+ glColor3fv(color)
+ vec = pos2-pos1
+ axis = norm(vec)
+ glTranslatef(pos1[0], pos1[1], pos1[2])
+
+ ##Huaicai 1/17/05: To avoid rotate around (0, 0, 0), which causes
+ ## display problem on some platforms
+ angle = -acos(axis[2])*180.0/pi
+ if (axis[2]*axis[2] >= 1.0):
+ glRotate(angle, 0.0, 1.0, 0.0)
+ else:
+ glRotate(angle, axis[1], -axis[0], 0.0)
+ glRotate(rotation, 0.0, 0.0, 1.0) #bruce 050518
+ glScale(radius,radius,Numeric.dot(vec,vec)**.5)
+
+ glLineWidth(2.0)
+ glDisable(GL_LIGHTING)
+ glCallList(drawing_globals.rotSignList)
+ glEnable(GL_LIGHTING)
+ glLineWidth(1.0)
+
+ glPopMatrix()
+ return
+
+def drawArrowHead(color,
+ basePoint,
+ drawingScale,
+ unitBaseVector,
+ unitHeightVector):
+
+
+
+ arrowBase = drawingScale * 0.08
+ arrowHeight = drawingScale * 0.12
+ glDisable(GL_LIGHTING)
+ glPushMatrix()
+ glTranslatef(basePoint[0],basePoint[1],basePoint[2])
+ point1 = V(0, 0, 0)
+ point1 = point1 + unitHeightVector * arrowHeight
+ point2 = unitBaseVector * arrowBase
+ point3 = - unitBaseVector * arrowBase
+ #Draw the arrowheads as filled triangles
+ glColor3fv(color)
+ glBegin(GL_POLYGON)
+ glVertex3fv(point1)
+ glVertex3fv(point2)
+ glVertex3fv(point3)
+ glEnd()
+ glPopMatrix()
+ glEnable(GL_LIGHTING)
+
+def drawSineWave(color, startPoint, endPoint, numberOfPoints, phaseAngle):
+ """
+ """
+ pass
+
+def drawPolyLine(color, points):
+ '''Draws a poly line passing through the given list of points'''
+ glDisable(GL_LIGHTING)
+ glColor3fv(color)
+ glBegin(GL_LINE_STRIP)
+ for v in points:
+ glVertex3fv(v)
+ glEnd()
+
+ glEnable(GL_LIGHTING)
+ return
+
+def drawPoint(color,
+ point,
+ pointSize = 3.0,
+ isRound = True):
+ """
+ Draw a point using GL_POINTS.
+ @param point: The x,y,z coordinate array/ vector of the point
+ @type point: A or V
+ @param pointSize: The point size to be used by glPointSize
+ @type pointSize: float
+ @param isRound: If True, the point will be drawn round otherwise square
+ @type isRound: boolean
+ """
+ glDisable(GL_LIGHTING)
+ glColor3fv(color)
+ glPointSize(float(pointSize))
+ if isRound:
+ glEnable(GL_POINT_SMOOTH)
+ glBegin(GL_POINTS)
+ glVertex3fv(point)
+ glEnd()
+ if isRound:
+ glDisable(GL_POINT_SMOOTH)
+
+ glEnable(GL_LIGHTING)
+ if pointSize != 1.0:
+ glPointSize(1.0)
+ return
+
+def drawLineCube(color, pos, radius):
+ vtIndices = [0,1,2,3, 0,4,5,1, 5,4,7,6, 6,7,3,2]
+ glEnableClientState(GL_VERTEX_ARRAY)
+ #bruce 051117 revised this
+ glVertexPointer(3, GL_FLOAT, 0, drawing_globals.flatCubeVertices)
+ #grantham 20051213 observations, reported/paraphrased by bruce 051215:
+ # - should verify PyOpenGL turns Python float (i.e. C double) into C float
+ # for OpenGL's GL_FLOAT array element type.
+ # - note that GPUs are optimized for DrawElements types GL_UNSIGNED_INT and GL_UNSIGNED_SHORT.
+ glDisable(GL_LIGHTING)
+ glColor3fv(color)
+ glPushMatrix()
+ glTranslatef(pos[0], pos[1], pos[2])
+ glScale(radius,radius,radius)
+ glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices)
+ #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[4])
+ #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[8])
+ #glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_BYTE, vtIndices[12])
+ glPopMatrix()
+ glEnable(GL_LIGHTING)
+ glDisableClientState(GL_VERTEX_ARRAY)
+ return
+
+def drawwirecube(color, pos, radius, lineWidth=3.0):
+ glPolygonMode(GL_FRONT, GL_LINE)
+ glPolygonMode(GL_BACK, GL_LINE)
+ glDisable(GL_LIGHTING)
+ glDisable(GL_CULL_FACE)
+ glColor3fv(color)
+ glPushMatrix()
+ glTranslatef(pos[0], pos[1], pos[2])
+ if type(radius) == type(1.0):
+ glScale(radius,radius,radius)
+ else:
+ glScale(radius[0], radius[1], radius[2])
+ glLineWidth(lineWidth)
+ glCallList(drawing_globals.lineCubeList)
+ glLineWidth(1.0) ## restore its state
+ glPopMatrix()
+ glEnable(GL_CULL_FACE)
+ glEnable(GL_LIGHTING)
+ glPolygonMode(GL_FRONT, GL_FILL)
+ glPolygonMode(GL_BACK, GL_FILL) #bruce 050729 to help fix bug 835 or related bugs
+ return
+
+def drawwirebox(color, pos, len):
+ glPolygonMode(GL_FRONT, GL_LINE)
+ glPolygonMode(GL_BACK, GL_LINE)
+ glDisable(GL_LIGHTING)
+ glDisable(GL_CULL_FACE)
+ glColor3fv(color)
+ glPushMatrix()
+ glTranslatef(pos[0], pos[1], pos[2])
+ glScale(len[0], len[1], len[2])
+ glCallList(drawing_globals.CubeList)
+ glPopMatrix()
+ glEnable(GL_CULL_FACE)
+ glEnable(GL_LIGHTING)
+ glPolygonMode(GL_FRONT, GL_FILL)
+ glPolygonMode(GL_BACK, GL_FILL) #bruce 050729 to help fix bug 835 or related bugs
+ return
+
+def segstart(color):
+ glDisable(GL_LIGHTING)
+ glColor3fv(color)
+ glBegin(GL_LINES)
+ return
+
+def drawsegment(pos1,pos2):
+ glVertex3fv(pos1)
+ glVertex3fv(pos2)
+ return
+
+def segend():
+ glEnd()
+ glEnable(GL_LIGHTING)
+ return
+
+def drawAxis(color, pos1, pos2, width = 2): #Ninad 060907
+ '''Draw chunk or jig axis'''
+ #ninad060907 Note that this is different than draw
+ #I may need this function to draw axis line. see its current implementation in
+ #branch "ninad_060908_drawAxis_notAsAPropOfObject"
+ glDisable(GL_LIGHTING)
+ glColor3fv(color)
+ glLineStipple(3, 0x1C47) # dash-dot-dash line
+ glEnable(GL_LINE_STIPPLE)
+ if width != 1:
+ glLineWidth(width)
+ glBegin(GL_LINES)
+ glVertex(pos1[0], pos1[1], pos1[2])
+ glVertex(pos2[0], pos2[1], pos2[2])
+ glEnd()
+ if width != 1:
+ glLineWidth(1.0) # restore default state
+ glDisable(GL_LINE_STIPPLE)
+ glEnable(GL_LIGHTING)
+ return
+
+def drawaxes(n,point,coloraxes=False, dashEnabled = False):
+
+ n *= 0.5
+ glPushMatrix()
+ glTranslate(point[0], point[1], point[2])
+ glDisable(GL_LIGHTING)
+
+ if coloraxes:
+ glColor3f(red[0], red[1], red[2])
+ if dashEnabled:
+ #ninad060921 Note that we will only support dotted origin axis
+ #(hidden lines)but not POV axis. (as it could be annoying)
+ glLineStipple(5, 0xAAAA)
+ glEnable(GL_LINE_STIPPLE)
+ glDisable(GL_DEPTH_TEST)
+ else:
+ glColor3f(darkgreen[0], darkgreen[1], darkgreen[2])
+
+ glBegin(GL_LINES)
+ glVertex(n,0,0)
+ glVertex(-n,0,0)
+ glColor3f(darkgreen[0], darkgreen[1], darkgreen[2])
+ glVertex(0,n,0)
+ glVertex(0,-n,0)
+ if coloraxes: glColor3f(blue[0], blue[1], blue[2])
+ else: glColor3f(darkgreen[0], darkgreen[1], darkgreen[2])
+ glVertex(0,0,n)
+ glVertex(0,0,-n)
+ glEnd()
+
+ if coloraxes:
+ if dashEnabled:
+ glDisable(GL_LINE_STIPPLE)
+ glEnable(GL_DEPTH_TEST)
+
+ glEnable(GL_LIGHTING)
+ glPopMatrix()
+ return
+
+def drawOriginAsSmallAxis(scale, origin, dashEnabled = False):
+ """
+ Draws a small wireframe version of the origin. It is rendered as a
+ 3D point at (0, 0, 0) with 3 small axes extending from it in the positive
+ X, Y, Z directions.
+ """
+ #Perhaps we should split this method into smaller methods? ninad060920
+ #Notes:
+ #1. drawing arrowheads implemented on 060918
+ #2. ninad060921 Show the origin axes as dotted if behind the mode.
+ #3. ninad060922 The arrow heads are drawn as wireframe cones if behind the object
+ # the arrowhead size is slightly smaller (otherwise some portion of the
+ # the wireframe arrow shows up!
+ #3.Making origin non-zoomable is acheived by replacing
+ #hardcoded 'n' with glpane's scale - ninad060922
+
+ #ninad060922 in future , the following could be user preferences.
+ if (dashEnabled):
+ dashShrinkage = 0.9
+ else:
+ dashShrinkage=1
+ x1, y1, z1 = scale * 0.01, scale * 0.01, scale * 0.01
+ xEnd, yEnd, zEnd = scale * 0.04, scale * 0.09, scale * 0.025
+ arrowBase = scale * 0.0075 * dashShrinkage
+ arrowHeight = scale * 0.035 * dashShrinkage
+ lineWidth = 1.0
+
+ glPushMatrix()
+
+ glTranslate(origin[0], origin[1], origin[2])
+ glDisable(GL_LIGHTING)
+ glLineWidth(lineWidth)
+
+ gleNumSides = gleGetNumSides()
+ #Code to show hidden lines of the origin if some model obscures it ninad060921
+ if dashEnabled:
+ glLineStipple(2, 0xAAAA)
+ glEnable(GL_LINE_STIPPLE)
+ glDisable(GL_DEPTH_TEST)
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
+ gleSetNumSides(5)
+ else:
+ gleSetNumSides(10)
+
+ glBegin(GL_LINES)
+
+ #glColor3f(black)
+ glColor3fv(lightblue)
+
+ #start draw a point at origin .
+ #ninad060922 is thinking about using GL_POINTS here
+
+ glVertex(-x1, 0.0, 0.0)
+ glVertex( x1, 0.0, 0.0)
+ glVertex(0.0, -y1, 0.0)
+ glVertex(0.0, y1, 0.0)
+ glVertex(-x1, y1, z1)
+ glVertex( x1, -y1, -z1)
+ glVertex(x1, y1, z1)
+ glVertex(-x1, -y1, -z1)
+ glVertex(x1, y1, -z1)
+ glVertex(-x1, -y1, z1)
+ glVertex(-x1, y1, -z1)
+ glVertex(x1, -y1, z1)
+ #end draw a point at origin
+
+ #start draw small origin axes
+ #glColor3fv(darkred)
+ glColor3fv(lightblue)
+ glVertex(xEnd, 0.0, 0.0)
+ glVertex( 0.0, 0.0, 0.0)
+ #glColor3f(darkgreen[0], darkgreen[1], darkgreen[2])
+ glColor3fv(lightblue)
+ glVertex(0.0, yEnd, 0.0)
+ glVertex(0.0, 0.0, 0.0)
+ #glColor3f(blue[0], blue[1], blue[2])
+ glColor3fv(lightblue)
+ glVertex(0.0, 0.0, zEnd)
+ glVertex(0.0, 0.0, 0.0)
+ glEnd() #end draw lines
+ glLineWidth(1.0)
+
+ glPopMatrix() # end push matrix for drawing various lines in the origin and axes
+
+ #start draw solid arrow heads for X , Y and Z axes
+ glPushMatrix()
+ glDisable(GL_CULL_FACE)
+ #glColor3fv(darkred)
+ glColor3fv(lightblue)
+ glTranslatef(xEnd, 0.0, 0.0)
+ glRotatef(90, 0.0, 1.0, 0.0)
+
+ glePolyCone([[0, 0, -1], [0, 0, 0], [0, 0, arrowHeight], [0, 0, arrowHeight+1]], None, [arrowBase, arrowBase, 0, 0])
+
+ glPopMatrix()
+
+ glPushMatrix()
+ #glColor3f(darkgreen)
+ glColor3fv(lightblue)
+ glTranslatef(0.0, yEnd, 0.0)
+ glRotatef(-90, 1.0, 0.0, 0.0)
+
+ glePolyCone([[0, 0, -1], [0, 0, 0], [0, 0, arrowHeight], [0, 0, arrowHeight+1]], None, [arrowBase, arrowBase, 0, 0])
+
+ glPopMatrix()
+
+ glPushMatrix()
+ glColor3fv(lightblue)
+ glTranslatef(0.0,0.0,zEnd)
+
+ glePolyCone([[0, 0, -1], [0, 0, 0], [0, 0, arrowHeight], [0, 0, arrowHeight+1]], None, [arrowBase, arrowBase, 0, 0])
+
+ #Disable line stipple and Enable Depth test
+ if dashEnabled:
+ glLineStipple(1, 0xAAAA)
+ glDisable(GL_LINE_STIPPLE)
+ glEnable(GL_DEPTH_TEST)
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
+ gleSetNumSides(gleNumSides)
+ glEnable(GL_CULL_FACE)
+ glEnable(GL_LIGHTING)
+ glPopMatrix()
+ #end draw solid arrow heads for X , Y and Z axes
+ return
+
+def findCell(pt, latticeType):
+ """Return the cell which contains the point <pt> """
+ if latticeType == 'DIAMOND':
+ a = 0; cellX = cellY = cellZ = drawing_globals.DiGridSp
+ elif latticeType == 'LONSDALEITE':
+ a = 1
+ cellX = drawing_globals.XLen
+ cellY = drawing_globals.YLen
+ cellZ = drawing_globals.ZLen
+
+ i = int(floor(pt[0]/cellX))
+ j = int(floor(pt[1]/cellY))
+ k = int(floor(pt[2]/cellZ))
+
+ orig = V(i*cellX, j*cellY, k*cellZ)
+
+ return orig, drawing_globals.sp1
+
+def genDiam(bblo, bbhi, latticeType):
+ """Generate a list of possible atom positions within the area enclosed by (bblo, bbhi).
+ <Return>: A list of unit cells"""
+ if latticeType == 'DIAMOND':
+ a = 0; cellX = cellY = cellZ = drawing_globals.DiGridSp
+ elif latticeType == 'LONSDALEITE':
+ a = 1
+ cellX = drawing_globals.XLen
+ cellY = drawing_globals.YLen
+ cellZ = drawing_globals.ZLen
+
+ allCells = []
+ for i in range(int(floor(bblo[0]/cellX)),
+ int(ceil(bbhi[0]/cellX))):
+ for j in range(int(floor(bblo[1]/cellY)),
+ int(ceil(bbhi[1]/cellY))):
+ for k in range(int(floor(bblo[2]/cellZ)),
+ int(ceil(bbhi[2]/cellZ))):
+ off = V(i*cellX, j*cellY, k*cellZ)
+ if a == 0: allCells += [drawing_globals.digrid + off]
+ elif a ==1: allCells += [drawing_globals.lonsEdges + off]
+ return allCells
+
+
+def drawGrid(scale, center, latticeType):
+ """
+ Construct the grid model and show as position references for cookies.
+ The model is build around "pov" and has size of 2*"scale" on each of
+ the (x, y, z) directions.
+
+ @note: This should be optimized later.
+ For "scale = 200", it takes about 1479623 loops. ---Huaicai
+ """
+ glDisable(GL_LIGHTING)
+
+ # bruce 041201:
+ # Quick fix to prevent "hang" from drawing too large a cookieMode grid
+ # with our current cubic algorithm (bug 8). The constant 120.0 is still on
+ # the large side in terms of responsiveness -- on a 1.8GHz iMac G5 it can
+ # take many seconds to redraw the largest grid, or to update a selection
+ # rectangle during a drag. I also tried 200.0 but that was way too large.
+ # Since some users have slower machines, I'll be gentle and put 90.0 here.
+ # Someday we need to fix the alg to be quadratic by teaching this code
+ # (and the cookie baker code too) about the eyespace clipping planes.
+ # Once we support user prefs, this should be one of them (if the alg is
+ # not fixed by then).
+
+ MAX_GRID_SCALE = 90.0
+ if scale > MAX_GRID_SCALE:
+ scale = MAX_GRID_SCALE
+
+ if latticeType == 'DIAMOND':
+ cellX = cellY = cellZ = drawing_globals.DiGridSp
+ elif latticeType == 'LONSDALEITE':
+ cellX = drawing_globals.XLen
+ cellY = drawing_globals.YLen
+ cellZ = drawing_globals.ZLen
+
+ bblo = center - scale
+ bbhi = center + scale
+ i1 = int(floor(bblo[0]/cellX))
+ i2 = int(ceil(bbhi[0]/cellX))
+ j1 = int(floor(bblo[1]/cellY))
+ j2 = int(ceil(bbhi[1]/cellY))
+ k1 = int(floor(bblo[2]/cellZ))
+ k2 = int(ceil(bbhi[2]/cellZ))
+ glPushMatrix()
+ glTranslate(i1*cellX, j1*cellY, k1*cellZ)
+ for i in range(i1, i2):
+ glPushMatrix()
+ for j in range(j1, j2):
+ glPushMatrix()
+ for k in range(k1, k2):
+ if latticeType == 'DIAMOND':
+ glCallList(drawing_globals.diamondGridList)
+ else:
+ glCallList(drawing_globals.lonsGridList)
+ glTranslate(0.0, 0.0, cellZ)
+ glPopMatrix()
+ glTranslate(0.0, cellY, 0.0)
+ glPopMatrix()
+ glTranslate(cellX, 0.0, 0.0)
+ glPopMatrix()
+ glEnable(GL_LIGHTING)
+
+ #drawCubeCell(V(1, 0, 0))
+ return
+
+
+def drawrectangle(pt1, pt2, rt, up, color):
+ """
+ Draws a (hollow) rectangle outline of the given I{color}.
+
+ @param pt1: First corner of the rectangle.
+ @type pt1: Point
+
+ @param pt1: Opposite corner of the rectangle.
+ @type pt1: Point
+
+ @param rt: Right vector of the glpane.
+ @type rt: Unit vector
+
+ @param up: Right vector of the glpane.
+ @type up: Unit vector
+
+ @param color: Color
+ @type color: color
+ """
+ glColor3f(color[0], color[1], color[2])
+ glDisable(GL_LIGHTING)
+ c2 = pt1 + rt * Numeric.dot(rt, pt2 - pt1)
+ c3 = pt1 + up * Numeric.dot(up, pt2 - pt1)
+ glBegin(GL_LINE_LOOP)
+ glVertex(pt1[0], pt1[1], pt1[2])
+ glVertex(c2[0], c2[1], c2[2])
+ glVertex(pt2[0], pt2[1], pt2[2])
+ glVertex(c3[0], c3[1], c3[2])
+ glEnd()
+ glEnable(GL_LIGHTING)
+
+#bruce & wware 060404: drawRubberBand apparently caused bug 1814 (Zoom Tool hanging some Macs, requiring power toggle)
+# so it should not be used until debugged. Use drawrectangle instead. (For an example of how to translate between them,
+# see ZoomMode.py rev 1.32 vs 1.31 in ViewCVS.) That bug was only repeatable on Bruce's & Will's iMacs G5.
+#
+# Bruce's speculations (not very definite; no evidence for them at all) about possible causes of the bug in drawRubberBand:
+# - use of glVertex instead of glVertex3f or so??? This seems unlikely, since we have other uses of it,
+# but perhaps they work due to different arg types.
+# - use of GL_LINE_LOOP within OpenGL xor mode, and bugs in some OpenGL drivers?? I didn't check whether cookieMode does this too.
+##def drawRubberBand(pt1, pt2, c2, c3, color):
+## """Huaicai: depth test should be disabled to make the xor work """
+## glBegin(GL_LINE_LOOP)
+## glVertex(pt1[0],pt1[1],pt1[2])
+## glVertex(c2[0],c2[1],c2[2])
+## glVertex(pt2[0],pt2[1],pt2[2])
+## glVertex(c3[0],c3[1],c3[2])
+## glEnd()
+## return
+
+
+# Wrote drawbrick for the Linear Motor. Mark [2004-10-10]
+def drawbrick(color, center, axis, l, h, w, opacity = 1.0):
+
+ if len(color) == 3:
+ color = (color[0], color[1], color[2], opacity)
+
+ if opacity != 1.0:
+ glDepthMask(GL_FALSE)
+ glEnable(GL_BLEND)
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+
+
+ apply_material(color)
+ glPushMatrix()
+ glTranslatef(center[0], center[1], center[2])
+
+ ##Huaicai 1/17/05: To avoid rotate around (0, 0, 0), which causes
+ ## display problem on some platforms
+ angle = -acos(axis[2])*180.0/pi
+ if (axis[2]*axis[2] >= 1.0):
+ glRotate(angle, 0.0, 1.0, 0.0)
+ else:
+ glRotate(angle, axis[1], -axis[0], 0.0)
+
+
+
+ glScale(h, w, l)
+ #bruce 060302 revised the contents of solidCubeList while fixing bug 1595
+ glCallList(drawing_globals.solidCubeList)
+
+ if opacity != 1.0:
+ glDisable(GL_BLEND)
+ glDepthMask(GL_TRUE)
+
+ glPopMatrix()
+ return
+
+def drawLineLoop(color,lines, width = 1):
+ glDisable(GL_LIGHTING)
+ glColor3fv(color)
+ glLineWidth(width)
+ glBegin(GL_LINE_LOOP)
+ for v in lines:
+ glVertex3fv(v)
+ glEnd()
+ glEnable(GL_LIGHTING)
+ #reset the glLineWidth to 1
+ if width!=1:
+ glLineWidth(1)
+ return
+
+
+def drawlinelist(color,lines):
+ glDisable(GL_LIGHTING)
+ glColor3fv(color)
+ glBegin(GL_LINES)
+ for v in lines:
+ glVertex3fv(v)
+ glEnd()
+ glEnable(GL_LIGHTING)
+ return
+
+cubeLines = A([[-1,-1,-1], [-1,-1, 1],
+ [-1, 1,-1], [-1, 1, 1],
+ [ 1,-1,-1], [ 1,-1, 1],
+ [ 1, 1,-1], [ 1, 1, 1],
+
+ [-1,-1,-1], [-1, 1,-1],
+ [-1,-1, 1], [-1, 1, 1],
+ [ 1,-1,-1], [ 1, 1,-1],
+ [ 1,-1, 1], [ 1, 1, 1],
+
+ [-1,-1,-1], [ 1,-1,-1],
+ [-1,-1, 1], [ 1,-1, 1],
+ [-1, 1,-1], [ 1, 1,-1],
+ [-1, 1, 1], [ 1, 1, 1]])
+
+def drawCubeCell(color):
+ sp0 = drawing_globals.sp0
+ sp4 = drawing_globals.sp4
+ vs = [[sp0, sp0, sp0], [sp4, sp0, sp0], [sp4, sp4, sp0], [sp0, sp4, sp0],
+ [sp0, sp0, sp4], [sp4, sp0, sp4], [sp4, sp4, sp4], [sp0, sp4, sp4]]
+
+ glDisable(GL_LIGHTING)
+ glColor3fv(color)
+ glBegin(GL_LINE_LOOP)
+ for ii in range(4):
+ glVertex3fv(vs[ii])
+ glEnd()
+
+ glBegin(GL_LINE_LOOP)
+ for ii in range(4, 8):
+ glVertex3fv(vs[ii])
+ glEnd()
+
+ glBegin(GL_LINES)
+ for ii in range(4):
+ glVertex3fv(vs[ii])
+ glVertex3fv(vs[ii+4])
+ glEnd()
+
+ glEnable(GL_LIGHTING)
+ return
+
+def drawPlane(color, w, h, textureReady, opacity, SOLID=False, pickCheckOnly=False):
+ '''Draw polygon with size of <w>*<h> and with color <color>. Optionally, it could be texuture mapped, translucent.
+ @pickCheckOnly This is used to draw the geometry only, used for OpenGL pick selection purpose.'''
+ vs = [[-0.5, 0.5, 0.0], [-0.5, -0.5, 0.0], [0.5, -0.5, 0.0], [0.5, 0.5, 0.0]]
+ vt = [[0.0, 1.0], [0.0, 0.0], [1.0, 0.0], [1.0, 1.0]]
+
+ glDisable(GL_LIGHTING)
+ glColor4fv(list(color) + [opacity])
+
+ glPushMatrix()
+ glScalef(w, h, 1.0)
+
+ if SOLID:
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
+ else:
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
+ glDisable(GL_CULL_FACE)
+
+ if not pickCheckOnly:
+ glDepthMask(GL_FALSE) # This makes sure translucent object will not occlude another translucent object
+ glEnable(GL_BLEND)
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+
+ if textureReady:
+ glEnable(GL_TEXTURE_2D)
+
+ glBegin(GL_QUADS)
+ for ii in range(len(vs)):
+ t = vt[ii]; v = vs[ii]
+ if textureReady:
+ glTexCoord2fv(t)
+ glVertex3fv(v)
+ glEnd()
+
+ if not pickCheckOnly:
+ if textureReady:
+ glDisable(GL_TEXTURE_2D)
+
+ glDisable(GL_BLEND)
+ glDepthMask(GL_TRUE)
+
+ glEnable(GL_CULL_FACE)
+ if not SOLID:
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
+
+ glPopMatrix()
+ glEnable(GL_LIGHTING)
+ return
+
+def drawFullWindow(vtColors):
+ """Draw gradient background color.
+ <vtColors> is a 4 element list specifying colors for the
+ left-down, right-down, right-up, left-up window corners.
+ To draw the full window, the modelview and projection should be set in identity.
+ """
+ from utilities.constants import GL_FAR_Z
+ glDisable(GL_LIGHTING)
+
+ glBegin(GL_QUADS)
+ glColor3fv(vtColors[0])
+ glVertex3f(-1, -1, GL_FAR_Z)
+ glColor3fv(vtColors[1])
+ glVertex3f(1, -1, GL_FAR_Z)
+ glColor3fv(vtColors[2])
+ glVertex3f(1, 1, GL_FAR_Z)
+ glColor3fv(vtColors[3])
+ glVertex3f(-1, 1, GL_FAR_Z)
+ glEnd()
+
+ glEnable(GL_LIGHTING)
+ return
+
+def drawtext(text, color, origin, point_size, glpane):
+ """
+ """
+ # see also: _old_code_for_drawing_text()
+
+ if not text:
+ return
+
+ glDisable(GL_LIGHTING)
+ glDisable(GL_DEPTH_TEST)
+
+ from PyQt4.Qt import QFont, QString, QColor
+ font = QFont( QString("Helvetica"), point_size)
+ #glpane.qglColor(QColor(75, 75, 75))
+ from widgets.widget_helpers import RGBf_to_QColor
+ glpane.qglColor(RGBf_to_QColor(color))
+ glpane.renderText(origin[0], origin[1], origin[2], QString(text), font)
+
+ glEnable(GL_DEPTH_TEST)
+ glEnable(GL_LIGHTING)
+ return
+
+##Junk code###
+## The following code used to be for drawing text on a QGLWidget --
+# some of it might still be useful if integrated into drawtext() above
+# [moved here from elementColors.py and slightly cleaned up by bruce 080223]
+def _old_code_for_drawing_text(glpane):
+ self = glpane
+ glDisable(GL_LIGHTING)
+ glDisable(GL_DEPTH_TEST)
+ self.qglColor(QColor(0, 0, 0))
+ font = QFont( QString("Times"), 10)
+ text = QString('Rvdw = ' + str(self.rad))
+ fontMecs = QFontMetrics(font)
+ strWd = fontMecs.width(text)
+ strHt = fontMecs.height()
+ w = self.width/2 - strWd/2
+ h = self.height - strHt/2
+ self.renderText(w, h, text, font)
+ glEnable(GL_DEPTH_TEST)
+ glEnable(GL_LIGHTING)
+
+def renderSurface(surfaceEntities, surfaceNormals):
+ ####@@@@ bruce 060927 comments:
+ # - The color needs to come before the vertex. I fixed that, but left a debug_pref that can change it
+ # so you can see the effect of that bug before it was fixed. (Same for the normal, but it already did come before.)
+ # - I suspect normals are not used (when nc > 0) due to lighting being off. But if it's on, colors are not used.
+ # I saw that problem before, and we had to use apply_material instead, to set color; I'm not sure why,
+ # it might just be due to specific OpenGL settings we make for other purposes. So I'll use drawer.apply_material(color)
+ # (again with a debug pref to control that).
+ # The effect of the default debug_pref settings is that it now works properly with color -- but only for the 2nd chunk,
+ # if you create two, and not at all if you create only one. I don't know why it doesn't work for the first chunk.
+ (entityIndex, surfacePoints, surfaceColors) = surfaceEntities
+ e0 = entityIndex[0]
+ n = len(e0)
+ nc = len(surfaceColors)
+ if 1:
+ ### bruce 060927 debug code; when done debugging, we can change them to constants & simplify the code that uses them.
+ from utilities.debug_prefs import debug_pref, Choice_boolean_True, Choice_boolean_False
+ disable_lighting = debug_pref("surface: disable lighting?", Choice_boolean_False)
+ if nc:
+ color_first = debug_pref("surface: color before vertex?", Choice_boolean_True)
+ use_apply_material = debug_pref("surface: use apply_material?", Choice_boolean_True)
+ ## old code was equivalent to disable_lighting = (nc > 0)
+ def use_color(color): #bruce 060927 split this out, so we can change how we apply color in a single place in the code
+ if use_apply_material:
+ apply_material(color) # This makes the colors visible even when lighting is enabled.
+ else:
+ glColor3fv(color) # Old code did this. These colors are only visible when lighting is not enabled.
+ return
+ def onevert(vertex_index): #bruce 060927 split this out, for code clarity, and so debug prefs are used in only one place
+ glNormal3fv(surfaceNormals[vertex_index])
+ if nc > 0 and color_first: use_color(surfaceColors[vertex_index]) # this needs to be done before glVertex3fv
+ glVertex3fv(surfacePoints[vertex_index])
+ if nc > 0 and not color_first: use_color(surfaceColors[vertex_index]) # old code did it here -- used wrong colors sometimes
+ return
+ ## if nc > 0 : glDisable(GL_LIGHTING)
+ if disable_lighting: glDisable(GL_LIGHTING)
+ if n == 3:
+ glBegin(GL_TRIANGLES)
+ for entity in entityIndex:
+ onevert(entity[0])
+ onevert(entity[1])
+ onevert(entity[2])
+ glEnd()
+ else:
+ glBegin(GL_QUADS)
+ for entity in entityIndex:
+ onevert(entity[0])
+ onevert(entity[1])
+ onevert(entity[2])
+ onevert(entity[3])
+ glEnd()
+ if disable_lighting: glEnable(GL_LIGHTING)
+ return
+
+# end
diff --git a/cad/src/graphics/drawing/drawing_globals.py b/cad/src/graphics/drawing/drawing_globals.py
index 1f858cb5d..cccdf983b 100644
--- a/cad/src/graphics/drawing/drawing_globals.py
+++ b/cad/src/graphics/drawing/drawing_globals.py
@@ -38,3 +38,33 @@ use_c_renderer = use_c_renderer_default = False
#bruce 060323 changed this to disconnect it from old pref setting
use_c_renderer_prefs_key = "use_c_renderer_rev2"
+#=
+
+import foundation.env as env #bruce 051126
+import utilities.EndUser as EndUser
+import sys
+import os
+
+if EndUser.getAlternateSourcePath() != None:
+ sys.path.append(os.path.join( EndUser.getAlternateSourcePath(), "experimental/pyrex-opengl"))
+else:
+ sys.path.append("./experimental/pyrex-opengl")
+
+binPath = os.path.normpath(os.path.dirname(os.path.abspath(sys.argv[0])) + '/../bin')
+if binPath not in sys.path:
+ sys.path.append(binPath)
+
+global quux_module_import_succeeded
+try:
+ import quux
+ quux_module_import_succeeded = True
+ if "experimental" in os.path.dirname(quux.__file__):
+ # should never happen for end users, but if it does we want to print the warning
+ if env.debug() or not EndUser.enableDeveloperFeatures():
+ print "debug: fyi: Using experimental version of C rendering code:", quux.__file__
+except:
+ use_c_renderer = False
+ quux_module_import_succeeded = False
+ if env.debug(): #bruce 060323 added condition
+ print "WARNING: unable to import C rendering code (quux module). Only Python rendering will be available."
+ pass
diff --git a/cad/src/graphics/drawing/gl_buffers.py b/cad/src/graphics/drawing/gl_buffers.py
new file mode 100755
index 000000000..5f11700d7
--- /dev/null
+++ b/cad/src/graphics/drawing/gl_buffers.py
@@ -0,0 +1,267 @@
+# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
+"""
+gl_buffers.py - OpenGL data buffer objects.
+
+@version: $Id$
+@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
+
+History:
+
+Originated by Josh as drawer.py .
+
+Various developers extended it since then.
+
+Brad G. added ColorSorter features.
+
+At some point Bruce partly cleaned up the use of display lists.
+
+071030 bruce split some functions and globals into draw_grid_lines.py
+and removed some obsolete functions.
+
+080210 russ Split the single display-list into two second-level lists (with and
+without color) and a set of per-color sublists so selection and hover-highlight
+can over-ride Chunk base colors. ColorSortedDisplayList is now a class in the
+parent's displist attr to keep track of all that stuff.
+
+080311 piotr Added a "drawpolycone_multicolor" function for drawing polycone
+tubes with per-vertex colors (necessary for DNA display style)
+
+080313 russ Added triangle-strip icosa-sphere constructor, "getSphereTriStrips".
+
+080420 piotr Solved highlighting and selection problems for multi-colored
+objects (e.g. rainbow colored DNA structures).
+
+080519 russ pulled the globals into a drawing_globals module and broke drawer.py
+into 10 smaller chunks: glprefs.py setup_draw.py shape_vertices.py
+ColorSorter.py CS_workers.py CS_ShapeList.py CS_draw_primitives.py drawers.py
+gl_lighting.py gl_buffers.py
+"""
+
+import os
+import sys
+
+# the imports from math vs. Numeric are as discovered in existing code
+# as of 2007/06/25. It's not clear why acos is coming from math...
+from math import floor, ceil, acos, atan2
+import Numeric
+from Numeric import sin, cos, sqrt, pi
+degreesPerRadian = 180.0 / pi
+
+# russ 080519 No doubt many of the following imports are unused.
+# When the dust settles, the unnecessary ones will be removed.
+from OpenGL.GL import GL_AMBIENT
+from OpenGL.GL import GL_AMBIENT_AND_DIFFUSE
+from OpenGL.GL import glAreTexturesResident
+from OpenGL.GL import GL_ARRAY_BUFFER_ARB
+from OpenGL.GL import GL_BACK
+from OpenGL.GL import glBegin
+from OpenGL.GL import glBindTexture
+from OpenGL.GL import GL_BLEND
+from OpenGL.GL import glBlendFunc
+from OpenGL.GL import glCallList
+from OpenGL.GL import glColor3f
+from OpenGL.GL import glColor3fv
+from OpenGL.GL import glColor4fv
+from OpenGL.GL import GL_COLOR_MATERIAL
+from OpenGL.GL import GL_COMPILE
+from OpenGL.GL import GL_COMPILE_AND_EXECUTE
+from OpenGL.GL import GL_CONSTANT_ATTENUATION
+from OpenGL.GL import GL_CULL_FACE
+from OpenGL.GL import GL_CURRENT_BIT
+from OpenGL.GL import glDeleteLists
+from OpenGL.GL import glDeleteTextures
+from OpenGL.GL import glDepthMask
+from OpenGL.GL import GL_DEPTH_TEST
+from OpenGL.GL import GL_DIFFUSE
+from OpenGL.GL import glDisable
+from OpenGL.GL import glDisableClientState
+from OpenGL.GL import glDrawArrays
+from OpenGL.GL import glDrawElements
+from OpenGL.GL import glDrawElementsub
+from OpenGL.GL import glDrawElementsui
+from OpenGL.GL import glDrawElementsus
+from OpenGL.GL import GL_ELEMENT_ARRAY_BUFFER_ARB
+from OpenGL.GL import glEnable
+from OpenGL.GL import glEnableClientState
+from OpenGL.GL import glEnd
+from OpenGL.GL import glEndList
+from OpenGL.GL import GL_EXTENSIONS
+from OpenGL.GL import GL_FALSE
+from OpenGL.GL import GL_FILL
+from OpenGL.GL import glFinish
+from OpenGL.GL import GL_FLOAT
+from OpenGL.GL import GL_FOG
+from OpenGL.GL import GL_FOG_COLOR
+from OpenGL.GL import GL_FOG_END
+from OpenGL.GL import GL_FOG_MODE
+from OpenGL.GL import GL_FOG_START
+from OpenGL.GL import GL_FRONT
+from OpenGL.GL import GL_FRONT_AND_BACK
+from OpenGL.GL import glGenLists
+from OpenGL.GL import glGenTextures
+from OpenGL.GL import glGetString
+from OpenGL.GL import GL_LIGHT0
+from OpenGL.GL import GL_LIGHT1
+from OpenGL.GL import GL_LIGHT2
+from OpenGL.GL import glLightf
+from OpenGL.GL import glLightfv
+from OpenGL.GL import GL_LIGHTING
+from OpenGL.GL import GL_LINE
+from OpenGL.GL import GL_LINEAR
+from OpenGL.GL import GL_LINE_LOOP
+from OpenGL.GL import GL_LINES
+from OpenGL.GL import GL_LINE_SMOOTH
+from OpenGL.GL import glLineStipple
+from OpenGL.GL import GL_LINE_STIPPLE
+from OpenGL.GL import GL_LINE_STRIP
+from OpenGL.GL import glLineWidth
+from OpenGL.GL import glLoadIdentity
+from OpenGL.GL import glMaterialf
+from OpenGL.GL import glMaterialfv
+from OpenGL.GL import glMatrixMode
+from OpenGL.GL import GL_MODELVIEW
+from OpenGL.GL import glNewList
+from OpenGL.GL import glNormal3fv
+from OpenGL.GL import glNormalPointer
+from OpenGL.GL import glNormalPointerf
+from OpenGL.GL import GL_NORMAL_ARRAY
+from OpenGL.GL import GL_ONE_MINUS_SRC_ALPHA
+from OpenGL.GL import glPointSize
+from OpenGL.GL import GL_POINTS
+from OpenGL.GL import GL_POINT_SMOOTH
+from OpenGL.GL import GL_POLYGON
+from OpenGL.GL import glPolygonMode
+from OpenGL.GL import glPopAttrib
+from OpenGL.GL import glPopMatrix
+from OpenGL.GL import glPopName
+from OpenGL.GL import GL_POSITION
+from OpenGL.GL import glPushAttrib
+from OpenGL.GL import glPushMatrix
+from OpenGL.GL import glPushName
+from OpenGL.GL import GL_QUADS
+from OpenGL.GL import GL_QUAD_STRIP
+from OpenGL.GL import GL_RENDERER
+from OpenGL.GL import GL_RGBA
+from OpenGL.GL import glRotate
+from OpenGL.GL import glRotatef
+from OpenGL.GL import GL_SHININESS
+from OpenGL.GL import GL_SPECULAR
+from OpenGL.GL import GL_SRC_ALPHA
+from OpenGL.GL import GL_STATIC_DRAW
+from OpenGL.GL import glTexCoord2f
+from OpenGL.GL import glTexCoord2fv
+from OpenGL.GL import GL_TEXTURE_2D
+from OpenGL.GL import glTranslate
+from OpenGL.GL import glTranslatef
+from OpenGL.GL import GL_TRIANGLES
+from OpenGL.GL import GL_TRIANGLE_STRIP
+from OpenGL.GL import GL_TRUE
+from OpenGL.GL import GL_UNSIGNED_BYTE
+from OpenGL.GL import GL_UNSIGNED_SHORT
+from OpenGL.GL import GL_VENDOR
+from OpenGL.GL import GL_VERSION
+from OpenGL.GL import glVertex
+from OpenGL.GL import glVertex2f
+from OpenGL.GL import glVertex3f
+from OpenGL.GL import glVertex3fv
+from OpenGL.GL import GL_VERTEX_ARRAY
+from OpenGL.GL import glVertexPointer
+from OpenGL.GL import glVertexPointerf
+
+from OpenGL.GLU import gluBuild2DMipmaps
+
+from geometry.VQT import norm, vlen, V, Q, A
+
+from utilities.constants import white, blue, red
+from utilities.constants import darkgreen, lightblue
+from utilities.constants import DIAMOND_BOND_LENGTH
+from utilities.prefs_constants import material_specular_highlights_prefs_key
+from utilities.prefs_constants import material_specular_shininess_prefs_key
+from utilities.prefs_constants import material_specular_finish_prefs_key
+from utilities.prefs_constants import material_specular_brightness_prefs_key
+
+from utilities.debug_prefs import Choice
+import utilities.debug as debug # for debug.print_compact_traceback
+
+#=
+
+# Vertex Buffer Object (VBO) and Index Buffer Object (IBO) support.
+# For docs see http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml .
+
+# Notice that the ARB-suffixed versions of the OpenGL calls are used here.
+# They're the ones with PyConvert ctypes wrappers, see: (the incomprehensible)
+# http://pyopengl.sourceforge.net/ctypes/pydoc/OpenGL.GL.ARB.vertex_buffer_object.html
+# The sources will do you more good. Also see "Array Handling Routines" here:
+# http://pyopengl.sourceforge.net/documentation/opengl_diffs.html
+#
+from OpenGL.GL.ARB.vertex_buffer_object import glGenBuffersARB
+from OpenGL.GL.ARB.vertex_buffer_object import glDeleteBuffersARB
+# Patched versions.
+from graphics.drawing.vbo_patch import glBufferDataARB, glBufferSubDataARB
+
+from OpenGL.raw.GL.ARB.vertex_buffer_object import glBindBufferARB # Unwrappered.
+
+class GLBufferObject(object):
+ """
+ Buffer data in the graphics card's RAM space.
+
+ Useful man pages for glBind, glBufferData, etc. for OpenGL 2.1 are at:
+ http://www.opengl.org/sdk/docs/man
+ PyOpenGL versions are at:
+ http://pyopengl.sourceforge.net/ctypes/pydoc/OpenGL.html
+
+ 'target' is GL_ARRAY_BUFFER_ARB for vertex/normal buffers (VBO's), and
+ GL_ELEMENT_ARRAY_BUFFER_ARB for index buffers (IBO's.)
+
+ 'data' is a numpy.array, with dtype=numpy.<datatype> .
+
+ 'usage' is one of the hint constants, like GL_STATIC_DRAW.
+ """
+
+ def __init__(self, target, data, usage):
+ self.buffer = glGenBuffersARB(1) # Returns a numpy.ndarray for > 1.
+ self.target = target
+
+ self.bind()
+ self.size = len(data)
+
+ # Push the data over to Graphics card RAM.
+ glBufferDataARB(target, data, usage)
+
+ self.unbind()
+ return
+
+ def __del__(self):
+ """
+ Delete a GLBufferObject. We don't expect that there will be a lot of
+ deleting of GLBufferObjects, but don't want them to sit on a lot of graphics
+ card RAM if we did.
+ """
+
+ # Since may be too late to clean up buffer objects through the Graphics
+ # Context while exiting, we trust that OpenGL or the device driver will
+ # deallocate the graphics card RAM when the Python process exits.
+ try:
+ glDeleteBuffersARB(1, [self.buffer])
+ except:
+ ##print "Exception in glDeleteBuffersARB."
+ pass
+ return
+
+ def bind(self):
+ """
+ Have to bind a particular buffer to its target to fill or draw from it.
+ Don't forget to unbind() it!
+ """
+ glBindBufferARB(self.target, self.buffer)
+ return
+
+ def unbind(self):
+ """
+ Unbind a buffer object from its target after use.
+ Failure to do this can kill Python on some graphics platforms!
+ """
+ glBindBufferARB(self.target, 0)
+ return
+
+ pass # End of class GLBufferObject.
diff --git a/cad/src/graphics/drawing/gl_lighting.py b/cad/src/graphics/drawing/gl_lighting.py
new file mode 100755
index 000000000..10d7d4f94
--- /dev/null
+++ b/cad/src/graphics/drawing/gl_lighting.py
@@ -0,0 +1,451 @@
+# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
+"""
+gl_lighting.py - Lights, materials, and special effects.
+
+@version: $Id$
+@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
+
+History:
+
+Originated by Josh as drawer.py .
+
+Various developers extended it since then.
+
+Brad G. added ColorSorter features.
+
+At some point Bruce partly cleaned up the use of display lists.
+
+071030 bruce split some functions and globals into draw_grid_lines.py
+and removed some obsolete functions.
+
+080210 russ Split the single display-list into two second-level lists (with and
+without color) and a set of per-color sublists so selection and hover-highlight
+can over-ride Chunk base colors. ColorSortedDisplayList is now a class in the
+parent's displist attr to keep track of all that stuff.
+
+080311 piotr Added a "drawpolycone_multicolor" function for drawing polycone
+tubes with per-vertex colors (necessary for DNA display style)
+
+080313 russ Added triangle-strip icosa-sphere constructor, "getSphereTriStrips".
+
+080420 piotr Solved highlighting and selection problems for multi-colored
+objects (e.g. rainbow colored DNA structures).
+
+080519 russ pulled the globals into a drawing_globals module and broke drawer.py
+into 10 smaller chunks: glprefs.py setup_draw.py shape_vertices.py
+ColorSorter.py CS_workers.py CS_ShapeList.py CS_draw_primitives.py drawers.py
+gl_lighting.py gl_buffers.py
+"""
+
+import os
+import sys
+
+# the imports from math vs. Numeric are as discovered in existing code
+# as of 2007/06/25. It's not clear why acos is coming from math...
+from math import floor, ceil, acos, atan2
+import Numeric
+from Numeric import sin, cos, sqrt, pi
+degreesPerRadian = 180.0 / pi
+
+# russ 080519 No doubt many of the following imports are unused.
+# When the dust settles, the unnecessary ones will be removed.
+from OpenGL.GL import GL_AMBIENT
+from OpenGL.GL import GL_AMBIENT_AND_DIFFUSE
+from OpenGL.GL import glAreTexturesResident
+from OpenGL.GL import GL_ARRAY_BUFFER_ARB
+from OpenGL.GL import GL_BACK
+from OpenGL.GL import glBegin
+from OpenGL.GL import glBindTexture
+from OpenGL.GL import GL_BLEND
+from OpenGL.GL import glBlendFunc
+from OpenGL.GL import glCallList
+from OpenGL.GL import glColor3f
+from OpenGL.GL import glColor3fv
+from OpenGL.GL import glColor4fv
+from OpenGL.GL import GL_COLOR_MATERIAL
+from OpenGL.GL import GL_COMPILE
+from OpenGL.GL import GL_COMPILE_AND_EXECUTE
+from OpenGL.GL import GL_CONSTANT_ATTENUATION
+from OpenGL.GL import GL_CULL_FACE
+from OpenGL.GL import GL_CURRENT_BIT
+from OpenGL.GL import glDeleteLists
+from OpenGL.GL import glDeleteTextures
+from OpenGL.GL import glDepthMask
+from OpenGL.GL import GL_DEPTH_TEST
+from OpenGL.GL import GL_DIFFUSE
+from OpenGL.GL import glDisable
+from OpenGL.GL import glDisableClientState
+from OpenGL.GL import glDrawArrays
+from OpenGL.GL import glDrawElements
+from OpenGL.GL import glDrawElementsub
+from OpenGL.GL import glDrawElementsui
+from OpenGL.GL import glDrawElementsus
+from OpenGL.GL import GL_ELEMENT_ARRAY_BUFFER_ARB
+from OpenGL.GL import glEnable
+from OpenGL.GL import glEnableClientState
+from OpenGL.GL import glEnd
+from OpenGL.GL import glEndList
+from OpenGL.GL import GL_EXTENSIONS
+from OpenGL.GL import GL_FALSE
+from OpenGL.GL import GL_FILL
+from OpenGL.GL import glFinish
+from OpenGL.GL import GL_FLOAT
+from OpenGL.GL import GL_FOG
+from OpenGL.GL import GL_FOG_COLOR
+from OpenGL.GL import GL_FOG_END
+from OpenGL.GL import GL_FOG_MODE
+from OpenGL.GL import GL_FOG_START
+from OpenGL.GL import GL_FRONT
+from OpenGL.GL import GL_FRONT_AND_BACK
+from OpenGL.GL import glGenLists
+from OpenGL.GL import glGenTextures
+from OpenGL.GL import glGetString
+from OpenGL.GL import GL_LIGHT0
+from OpenGL.GL import GL_LIGHT1
+from OpenGL.GL import GL_LIGHT2
+from OpenGL.GL import glLightf
+from OpenGL.GL import glLightfv
+from OpenGL.GL import GL_LIGHTING
+from OpenGL.GL import GL_LINE
+from OpenGL.GL import GL_LINEAR
+from OpenGL.GL import GL_LINE_LOOP
+from OpenGL.GL import GL_LINES
+from OpenGL.GL import GL_LINE_SMOOTH
+from OpenGL.GL import glLineStipple
+from OpenGL.GL import GL_LINE_STIPPLE
+from OpenGL.GL import GL_LINE_STRIP
+from OpenGL.GL import glLineWidth
+from OpenGL.GL import glLoadIdentity
+from OpenGL.GL import glMaterialf
+from OpenGL.GL import glMaterialfv
+from OpenGL.GL import glMatrixMode
+from OpenGL.GL import GL_MODELVIEW
+from OpenGL.GL import glNewList
+from OpenGL.GL import glNormal3fv
+from OpenGL.GL import glNormalPointer
+from OpenGL.GL import glNormalPointerf
+from OpenGL.GL import GL_NORMAL_ARRAY
+from OpenGL.GL import GL_ONE_MINUS_SRC_ALPHA
+from OpenGL.GL import glPointSize
+from OpenGL.GL import GL_POINTS
+from OpenGL.GL import GL_POINT_SMOOTH
+from OpenGL.GL import GL_POLYGON
+from OpenGL.GL import glPolygonMode
+from OpenGL.GL import glPopAttrib
+from OpenGL.GL import glPopMatrix
+from OpenGL.GL import glPopName
+from OpenGL.GL import GL_POSITION
+from OpenGL.GL import glPushAttrib
+from OpenGL.GL import glPushMatrix
+from OpenGL.GL import glPushName
+from OpenGL.GL import GL_QUADS
+from OpenGL.GL import GL_QUAD_STRIP
+from OpenGL.GL import GL_RENDERER
+from OpenGL.GL import GL_RGBA
+from OpenGL.GL import glRotate
+from OpenGL.GL import glRotatef
+from OpenGL.GL import GL_SHININESS
+from OpenGL.GL import GL_SPECULAR
+from OpenGL.GL import GL_SRC_ALPHA
+from OpenGL.GL import GL_STATIC_DRAW
+from OpenGL.GL import glTexCoord2f
+from OpenGL.GL import glTexCoord2fv
+from OpenGL.GL import GL_TEXTURE_2D
+from OpenGL.GL import glTranslate
+from OpenGL.GL import glTranslatef
+from OpenGL.GL import GL_TRIANGLES
+from OpenGL.GL import GL_TRIANGLE_STRIP
+from OpenGL.GL import GL_TRUE
+from OpenGL.GL import GL_UNSIGNED_BYTE
+from OpenGL.GL import GL_UNSIGNED_SHORT
+from OpenGL.GL import GL_VENDOR
+from OpenGL.GL import GL_VERSION
+from OpenGL.GL import glVertex
+from OpenGL.GL import glVertex2f
+from OpenGL.GL import glVertex3f
+from OpenGL.GL import glVertex3fv
+from OpenGL.GL import GL_VERTEX_ARRAY
+from OpenGL.GL import glVertexPointer
+from OpenGL.GL import glVertexPointerf
+
+from OpenGL.GLU import gluBuild2DMipmaps
+
+from geometry.VQT import norm, vlen, V, Q, A
+
+from utilities.constants import white, blue, red
+from utilities.constants import darkgreen, lightblue
+from utilities.constants import DIAMOND_BOND_LENGTH
+from utilities.prefs_constants import material_specular_highlights_prefs_key
+from utilities.prefs_constants import material_specular_shininess_prefs_key
+from utilities.prefs_constants import material_specular_finish_prefs_key
+from utilities.prefs_constants import material_specular_brightness_prefs_key
+
+from utilities.debug_prefs import Choice
+import utilities.debug as debug # for debug.print_compact_traceback
+
+#=
+import graphics.drawing.drawing_globals as drawing_globals
+
+try:
+ from OpenGL.GL import glFog
+ from OpenGL.GL import glFogv # piotr 080515
+except:
+ # The installed version of OpenGL requires argument-typed glFog calls.
+ from OpenGL.GL import glFogf as glFog
+ from OpenGL.GL import glFogfv as glFogv
+
+# ==
+
+# Helper functions for use by GL widgets wanting to set up lighting.
+
+#bruce 051212 made these from the code in GLPane which now calls them, so they can also be used in ThumbView
+
+# Default lights tuples (format is as used by setup_standard_lights; perhaps also assumed by other code).
+#grantham 20051121 comment - Light should probably be a class. Right now,
+# changing the behavior of lights requires changing a bunch of
+# ambiguous tuples and tuple packing/unpacking.
+#bruce 051212 moved this here from GLPane; maybe it belongs in prefs_constants instead?
+# Note: I'm not sure whether this is the only place where this data is coded.
+_default_lights = ((white, 0.1, 0.5, 0.5, -50, 70, 30, True),
+ (white, 0.1, 0.5, 0.5, -20, 20, 20, True),
+ (white, 0.1, 0.1, 0.1, 0, 0, 100, False))
+ # for each of 3 lights, this stores ((r,g,b),a,d,s,x,y,z,e)
+ # revised format to include s,x,y,z. Mark 051202.
+ # revised format to include c (r,g,b). Mark 051204.
+ # Be sure to keep the lightColor prefs keys and _lights colors synchronized.
+ # Mark 051204. [a comment from when this was located in GLPane]
+
+def glprefs_data_used_by_setup_standard_lights( glprefs = None): #bruce 051212
+ """
+ Return a summary of the glprefs data used by setup_standard_lights,
+ for use in later deciding whether it needs to be called again due to changes in glprefs.
+ """
+ if glprefs is None:
+ glprefs = drawing_globals.glprefs
+ pass
+ # This must be kept in sync with what's used by setup_standard_lights() .
+ return (glprefs.override_light_specular,)
+
+def setup_standard_lights( lights, glprefs = None):
+ """
+ Set up lighting in the current GL context using the supplied "lights" tuple (in the format used by GLPane's prefs)
+ and the optional glprefs object (which defaults to drawing_globals.glprefs ).
+ Note: the glprefs data used can be summarized by the related function glprefs_data_used_by_setup_standard_lights (which see).
+ Warning: has side effects on GL_MODELVIEW matrix.
+ Note: If GL_NORMALIZE needs to be enabled, callers should do that themselves,
+ since this depends on what they will draw and might slow down drawing.
+ """
+ #e not sure whether projection matrix also needs to be reset here [bruce 051212]
+ glMatrixMode(GL_MODELVIEW)
+ glLoadIdentity()
+
+ if glprefs is None:
+ glprefs = drawing_globals.glprefs
+ # note: whatever glprefs data is used below must also be present
+ # in the return value of glprefs_data_used_by_setup_standard_lights(). [bruce 051212]
+
+ try:
+ # new code
+ (((r0,g0,b0),a0,d0,s0,x0,y0,z0,e0), \
+ ( (r1,g1,b1),a1,d1,s1,x1,y1,z1,e1), \
+ ( (r2,g2,b2),a2,d2,s2,x2,y2,z2,e2)) = lights
+
+ # Great place for a print statement for debugging lights. Keep this. Mark 051204. [revised by bruce 051212]
+ #print "-------------------------------------------------------------"
+ #print "setup_standard_lights: lights[0]=", lights[0]
+ #print "setup_standard_lights: lights[1]=", lights[1]
+ #print "setup_standard_lights: lights[2]=", lights[2]
+
+ glLightfv(GL_LIGHT0, GL_POSITION, (x0, y0, z0, 0))
+ glLightfv(GL_LIGHT0, GL_AMBIENT, (r0*a0, g0*a0, b0*a0, 1.0))
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, (r0*d0, g0*d0, b0*d0, 1.0))
+ if glprefs.override_light_specular is not None:
+ glLightfv(GL_LIGHT0, GL_SPECULAR, glprefs.override_light_specular)
+ else:
+ # grantham 20051121 - this should be a component on its own
+ # not replicating the diffuse color.
+ # Added specular (s0) as its own component. mark 051202.
+ glLightfv(GL_LIGHT0, GL_SPECULAR, (r0*s0, g0*s0, b0*s0, 1.0))
+ glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0)
+
+ glLightfv(GL_LIGHT1, GL_POSITION, (x1, y1, z1, 0))
+ glLightfv(GL_LIGHT1, GL_AMBIENT, (r1*a1, g1*a1, b1*a1, 1.0))
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, (r1*d1, g1*d1, b1*d1, 1.0))
+ if glprefs.override_light_specular is not None:
+ glLightfv(GL_LIGHT1, GL_SPECULAR, glprefs.override_light_specular)
+ else:
+ glLightfv(GL_LIGHT1, GL_SPECULAR, (r1*s1, g1*s1, b1*s1, 1.0))
+ glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0)
+
+ glLightfv(GL_LIGHT2, GL_POSITION, (x2, y2, z2, 0))
+ glLightfv(GL_LIGHT2, GL_AMBIENT, (r2*a2, g2*a2, b2*a2, 1.0))
+ glLightfv(GL_LIGHT2, GL_DIFFUSE, (r2*d2, g2*d2, b2*d2, 1.0))
+ if glprefs.override_light_specular is not None:
+ glLightfv(GL_LIGHT2, GL_SPECULAR, glprefs.override_light_specular)
+ else:
+ glLightfv(GL_LIGHT2, GL_SPECULAR, (r2*s2, g2*s2, b2*s2, 1.0))
+ glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, 1.0)
+
+ glEnable(GL_LIGHTING)
+
+ if e0:
+ glEnable(GL_LIGHT0)
+ else:
+ glDisable(GL_LIGHT0)
+
+ if e1:
+ glEnable(GL_LIGHT1)
+ else:
+ glDisable(GL_LIGHT1)
+
+ if e2:
+ glEnable(GL_LIGHT2)
+ else:
+ glDisable(GL_LIGHT2)
+ except:
+ debug.print_compact_traceback("bug (worked around): setup_standard_lights reverting to old code, because: ")
+ # old code, used only to set up some sort of workable lighting in case of bugs
+ # (this is not necessarily using the same values as _default_lights; doesn't matter since never used unless there are bugs)
+ glLightfv(GL_LIGHT0, GL_POSITION, (-50, 70, 30, 0))
+ glLightfv(GL_LIGHT0, GL_AMBIENT, (0.3, 0.3, 0.3, 1.0))
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, (0.8, 0.8, 0.8, 1.0))
+ glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0)
+
+ glLightfv(GL_LIGHT1, GL_POSITION, (-20, 20, 20, 0))
+ glLightfv(GL_LIGHT1, GL_AMBIENT, (0.4, 0.4, 0.4, 1.0))
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, (0.4, 0.4, 0.4, 1.0))
+ glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0)
+
+ glLightfv(GL_LIGHT2, GL_POSITION, (0, 0, 100, 0))
+ glLightfv(GL_LIGHT2, GL_AMBIENT, (1.0, 1.0, 1.0, 1.0))
+ glLightfv(GL_LIGHT2, GL_DIFFUSE, (1.0, 1.0, 1.0, 1.0))
+ glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, 1.0)
+
+ glEnable(GL_LIGHTING)
+
+ glEnable(GL_LIGHT0)
+ glEnable(GL_LIGHT1)
+ glDisable(GL_LIGHT2)
+ return # from setup_standard_lights
+
+# ==
+
+def setup_fog(fog_start, fog_end, fog_color):
+
+ glFog(GL_FOG_MODE, GL_LINEAR)
+ glFog(GL_FOG_START, fog_start)
+ glFog(GL_FOG_END, fog_end)
+ if len(fog_color) == 3:
+ fog_color = (fog_color[0], fog_color[1], fog_color[2], 1.0)
+ glFogv(GL_FOG_COLOR, fog_color) # piotr 080515
+
+def enable_fog():
+ glEnable(GL_FOG)
+
+def disable_fog():
+ glDisable(GL_FOG)
+
+# ==
+
+def apply_material(color): # grantham 20051121, renamed 20051201; revised by bruce 051126, 051203 (added specular_brightness), 051215
+ """
+ Set OpenGL material parameters based on the given color (length 3 or 4) and
+ the material-related prefs values in drawing_globals.glprefs.
+ """
+
+ #bruce 051215: make sure color is a tuple, and has length exactly 4, for all uses inside this function,
+ # assuming callers pass sequences of length 3 or 4. Needed because glMaterial requires four-component
+ # vector and PyOpenGL doesn't check. [If this is useful elsewhere, we can split it into a separate function.]
+ color = tuple(color)
+ if len(color) == 3:
+ color = color + (1.0,) # usual case
+ elif len(color) != 4:
+ # should never happen; if it does, this assert will always fail
+ assert len(color) in [3,4], "color tuples must have length 3 or 4, unlike %r" % (color,)
+
+ glColor4fv(color) # For drawing lines with lighting disabled.
+
+ if not drawing_globals.glprefs.enable_specular_highlights:
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color)
+ # glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (0,0,0,1))
+ return
+
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color)
+
+ whiteness = drawing_globals.glprefs.specular_whiteness
+ brightness = drawing_globals.glprefs.specular_brightness
+ if whiteness == 1.0:
+ specular = (1.0, 1.0, 1.0, 1.0) # optimization
+ else:
+ if whiteness == 0.0:
+ specular = color # optimization
+ else:
+ # assume color[3] (alpha) is not passed or is always 1.0
+ c1 = 1.0 - whiteness
+ specular = ( c1 * color[0] + whiteness, c1 * color[1] + whiteness, c1 * color[2] + whiteness, 1.0 )
+ if brightness != 1.0:
+ specular = ( specular[0] * brightness, specular[1] * brightness, specular[2] * brightness, 1.0 )
+ #e could optimize by merging this with above 3 cases (or, of course, by doing it in C, which we'll do eventually)
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular)
+
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS,
+ drawing_globals.glprefs.specular_shininess)
+ return
+
+# ==
+
+#russ 080515: We should find a better place for this!
+def get_gl_info_string(glpane): # grantham 20051129
+ """Return a string containing some useful information about the OpenGL implementation.
+ Use the GL context from the given QGLWidget glpane (by calling glpane.makeCurrent()).
+ """
+
+ glpane.makeCurrent() #bruce 070308 added glpane arg and makeCurrent call
+
+ gl_info_string = ''
+
+ gl_info_string += 'GL_VENDOR : "%s"\n' % glGetString(GL_VENDOR)
+ gl_info_string += 'GL_VERSION : "%s"\n' % glGetString(GL_VERSION)
+ gl_info_string += 'GL_RENDERER : "%s"\n' % glGetString(GL_RENDERER)
+ gl_info_string += 'GL_EXTENSIONS : "%s"\n' % glGetString(GL_EXTENSIONS)
+
+ from utilities.debug_prefs import debug_pref, Choice_boolean_False
+ if debug_pref("get_gl_info_string call glAreTexturesResident?", Choice_boolean_False):
+ # Give a practical indication of how much video memory is available.
+ # Should also do this with VBOs.
+
+ # I'm pretty sure this code is right, but PyOpenGL seg faults in
+ # glAreTexturesResident, so it's disabled until I can figure that
+ # out. [grantham] [bruce 070308 added the debug_pref]
+
+ all_tex_in = True
+ tex_bytes = '\0' * (512 * 512 * 4)
+ tex_names = []
+ tex_count = 0
+ tex_names = glGenTextures(1024)
+ glEnable(GL_TEXTURE_2D)
+ while all_tex_in:
+ glBindTexture(GL_TEXTURE_2D, tex_names[tex_count])
+ gluBuild2DMipmaps(GL_TEXTURE_2D, 4, 512, 512, GL_RGBA,
+ GL_UNSIGNED_BYTE, tex_bytes)
+ tex_count += 1
+
+ glTexCoord2f(0.0, 0.0)
+ glBegin(GL_QUADS)
+ glVertex2f(0.0, 0.0)
+ glVertex2f(1.0, 0.0)
+ glVertex2f(1.0, 1.0)
+ glVertex2f(0.0, 1.0)
+ glEnd()
+ glFinish()
+
+ residences = glAreTexturesResident(tex_names[:tex_count])
+ all_tex_in = reduce(lambda a,b: a and b, residences)
+ # bruce 070308 sees this exception from this line:
+ # TypeError: reduce() arg 2 must support iteration
+
+ glDisable(GL_TEXTURE_2D)
+ glDeleteTextures(tex_names)
+
+ gl_info_string += "Could create %d 512x512 RGBA resident textures\n", tex_count
+ return gl_info_string
diff --git a/cad/src/graphics/drawing/glprefs.py b/cad/src/graphics/drawing/glprefs.py
new file mode 100755
index 000000000..f8e3f0d11
--- /dev/null
+++ b/cad/src/graphics/drawing/glprefs.py
@@ -0,0 +1,294 @@
+# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
+"""
+glprefs.py - Attributes from drawing-related prefs stored in the prefs db cache.
+
+@version: $Id$
+@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
+
+History:
+
+Originated by Josh as drawer.py .
+
+Various developers extended it since then.
+
+Brad G. added ColorSorter features.
+
+At some point Bruce partly cleaned up the use of display lists.
+
+071030 bruce split some functions and globals into draw_grid_lines.py
+and removed some obsolete functions.
+
+080210 russ Split the single display-list into two second-level lists (with and
+without color) and a set of per-color sublists so selection and hover-highlight
+can over-ride Chunk base colors. ColorSortedDisplayList is now a class in the
+parent's displist attr to keep track of all that stuff.
+
+080311 piotr Added a "drawpolycone_multicolor" function for drawing polycone
+tubes with per-vertex colors (necessary for DNA display style)
+
+080313 russ Added triangle-strip icosa-sphere constructor, "getSphereTriStrips".
+
+080420 piotr Solved highlighting and selection problems for multi-colored
+objects (e.g. rainbow colored DNA structures).
+
+080519 russ pulled the globals into a drawing_globals module and broke drawer.py
+into 10 smaller chunks: glprefs.py setup_draw.py shape_vertices.py
+ColorSorter.py CS_workers.py CS_ShapeList.py CS_draw_primitives.py drawers.py
+gl_lighting.py gl_buffers.py
+"""
+
+import os
+import sys
+
+# the imports from math vs. Numeric are as discovered in existing code
+# as of 2007/06/25. It's not clear why acos is coming from math...
+from math import floor, ceil, acos, atan2
+import Numeric
+from Numeric import sin, cos, sqrt, pi
+degreesPerRadian = 180.0 / pi
+
+# russ 080519 No doubt many of the following imports are unused.
+# When the dust settles, the unnecessary ones will be removed.
+from OpenGL.GL import GL_AMBIENT
+from OpenGL.GL import GL_AMBIENT_AND_DIFFUSE
+from OpenGL.GL import glAreTexturesResident
+from OpenGL.GL import GL_ARRAY_BUFFER_ARB
+from OpenGL.GL import GL_BACK
+from OpenGL.GL import glBegin
+from OpenGL.GL import glBindTexture
+from OpenGL.GL import GL_BLEND
+from OpenGL.GL import glBlendFunc
+from OpenGL.GL import glCallList
+from OpenGL.GL import glColor3f
+from OpenGL.GL import glColor3fv
+from OpenGL.GL import glColor4fv
+from OpenGL.GL import GL_COLOR_MATERIAL
+from OpenGL.GL import GL_COMPILE
+from OpenGL.GL import GL_COMPILE_AND_EXECUTE
+from OpenGL.GL import GL_CONSTANT_ATTENUATION
+from OpenGL.GL import GL_CULL_FACE
+from OpenGL.GL import GL_CURRENT_BIT
+from OpenGL.GL import glDeleteLists
+from OpenGL.GL import glDeleteTextures
+from OpenGL.GL import glDepthMask
+from OpenGL.GL import GL_DEPTH_TEST
+from OpenGL.GL import GL_DIFFUSE
+from OpenGL.GL import glDisable
+from OpenGL.GL import glDisableClientState
+from OpenGL.GL import glDrawArrays
+from OpenGL.GL import glDrawElements
+from OpenGL.GL import glDrawElementsub
+from OpenGL.GL import glDrawElementsui
+from OpenGL.GL import glDrawElementsus
+from OpenGL.GL import GL_ELEMENT_ARRAY_BUFFER_ARB
+from OpenGL.GL import glEnable
+from OpenGL.GL import glEnableClientState
+from OpenGL.GL import glEnd
+from OpenGL.GL import glEndList
+from OpenGL.GL import GL_EXTENSIONS
+from OpenGL.GL import GL_FALSE
+from OpenGL.GL import GL_FILL
+from OpenGL.GL import glFinish
+from OpenGL.GL import GL_FLOAT
+from OpenGL.GL import GL_FOG
+from OpenGL.GL import GL_FOG_COLOR
+from OpenGL.GL import GL_FOG_END
+from OpenGL.GL import GL_FOG_MODE
+from OpenGL.GL import GL_FOG_START
+from OpenGL.GL import GL_FRONT
+from OpenGL.GL import GL_FRONT_AND_BACK
+from OpenGL.GL import glGenLists
+from OpenGL.GL import glGenTextures
+from OpenGL.GL import glGetString
+from OpenGL.GL import GL_LIGHT0
+from OpenGL.GL import GL_LIGHT1
+from OpenGL.GL import GL_LIGHT2
+from OpenGL.GL import glLightf
+from OpenGL.GL import glLightfv
+from OpenGL.GL import GL_LIGHTING
+from OpenGL.GL import GL_LINE
+from OpenGL.GL import GL_LINEAR
+from OpenGL.GL import GL_LINE_LOOP
+from OpenGL.GL import GL_LINES
+from OpenGL.GL import GL_LINE_SMOOTH
+from OpenGL.GL import glLineStipple
+from OpenGL.GL import GL_LINE_STIPPLE
+from OpenGL.GL import GL_LINE_STRIP
+from OpenGL.GL import glLineWidth
+from OpenGL.GL import glLoadIdentity
+from OpenGL.GL import glMaterialf
+from OpenGL.GL import glMaterialfv
+from OpenGL.GL import glMatrixMode
+from OpenGL.GL import GL_MODELVIEW
+from OpenGL.GL import glNewList
+from OpenGL.GL import glNormal3fv
+from OpenGL.GL import glNormalPointer
+from OpenGL.GL import glNormalPointerf
+from OpenGL.GL import GL_NORMAL_ARRAY
+from OpenGL.GL import GL_ONE_MINUS_SRC_ALPHA
+from OpenGL.GL import glPointSize
+from OpenGL.GL import GL_POINTS
+from OpenGL.GL import GL_POINT_SMOOTH
+from OpenGL.GL import GL_POLYGON
+from OpenGL.GL import glPolygonMode
+from OpenGL.GL import glPopAttrib
+from OpenGL.GL import glPopMatrix
+from OpenGL.GL import glPopName
+from OpenGL.GL import GL_POSITION
+from OpenGL.GL import glPushAttrib
+from OpenGL.GL import glPushMatrix
+from OpenGL.GL import glPushName
+from OpenGL.GL import GL_QUADS
+from OpenGL.GL import GL_QUAD_STRIP
+from OpenGL.GL import GL_RENDERER
+from OpenGL.GL import GL_RGBA
+from OpenGL.GL import glRotate
+from OpenGL.GL import glRotatef
+from OpenGL.GL import GL_SHININESS
+from OpenGL.GL import GL_SPECULAR
+from OpenGL.GL import GL_SRC_ALPHA
+from OpenGL.GL import GL_STATIC_DRAW
+from OpenGL.GL import glTexCoord2f
+from OpenGL.GL import glTexCoord2fv
+from OpenGL.GL import GL_TEXTURE_2D
+from OpenGL.GL import glTranslate
+from OpenGL.GL import glTranslatef
+from OpenGL.GL import GL_TRIANGLES
+from OpenGL.GL import GL_TRIANGLE_STRIP
+from OpenGL.GL import GL_TRUE
+from OpenGL.GL import GL_UNSIGNED_BYTE
+from OpenGL.GL import GL_UNSIGNED_SHORT
+from OpenGL.GL import GL_VENDOR
+from OpenGL.GL import GL_VERSION
+from OpenGL.GL import glVertex
+from OpenGL.GL import glVertex2f
+from OpenGL.GL import glVertex3f
+from OpenGL.GL import glVertex3fv
+from OpenGL.GL import GL_VERTEX_ARRAY
+from OpenGL.GL import glVertexPointer
+from OpenGL.GL import glVertexPointerf
+
+from OpenGL.GLU import gluBuild2DMipmaps
+
+from geometry.VQT import norm, vlen, V, Q, A
+
+from utilities.constants import white, blue, red
+from utilities.constants import darkgreen, lightblue
+from utilities.constants import DIAMOND_BOND_LENGTH
+from utilities.prefs_constants import material_specular_highlights_prefs_key
+from utilities.prefs_constants import material_specular_shininess_prefs_key
+from utilities.prefs_constants import material_specular_finish_prefs_key
+from utilities.prefs_constants import material_specular_brightness_prefs_key
+
+from utilities.debug_prefs import Choice
+import utilities.debug as debug # for debug.print_compact_traceback
+
+import graphics.drawing.drawing_globals as drawing_globals
+if drawing_globals.quux_module_import_succeeded:
+ import quux
+
+#=
+import foundation.env as env #bruce 051126
+
+# grantham 20051118; revised by bruce 051126
+class glprefs:
+
+ def __init__(self):
+## self.override_material_specular = None
+## # set to 4-element sequence to override material specular component
+## self.override_shininess = None
+## # if exists, overrides shininess
+## self.override_light_specular = None
+## # set to 4-element sequence to override light specular component
+ import foundation.preferences as preferences #bruce 051126 KLUGE: make sure env.prefs exists (could use cleanup, but that's not trivial)
+ self.update()
+
+ def update(self): #bruce 051126 added this method
+ """Update attributes from current drawing-related prefs stored in prefs db cache.
+ This should be called at the start of each complete redraw, or whenever the user changes these global prefs values
+ (whichever is more convenient).
+ (Note: When this is called during redraw, its prefs db accesses (like any others)
+ record those prefs as potentially affecting what should be drawn, so that subsequent
+ changes to those prefs values cause an automatic gl_update.)
+ Using these attributes in drawing code (rather than directly accessing prefs db cache)
+ is desirable for efficiency, since direct access to prefs db cache is a bit slow.
+ (Our drawing code still does that in other places -- those might also benefit from this system,
+ though this will soon be moot when low-level drawing code gets rewritten in C.)
+ """
+ self.enable_specular_highlights = not not env.prefs[
+ material_specular_highlights_prefs_key] # boolean
+ if self.enable_specular_highlights:
+ self.override_light_specular = None # used in glpane
+ # self.specular_shininess: float; shininess exponent for all specular highlights
+ self.specular_shininess = float(env.prefs[material_specular_shininess_prefs_key])
+ # self.specular_whiteness: float; whiteness for all material specular colors
+ self.specular_whiteness = float(env.prefs[material_specular_finish_prefs_key])
+ # self.specular_brightness: float; for all material specular colors
+ self.specular_brightness = float(env.prefs[material_specular_brightness_prefs_key])
+ else:
+ self.override_light_specular = (0.0, 0.0, 0.0, 0.0) # used in glpane
+ # Set these to reasonable values, though these attributes are presumably never used in this case.
+ # Don't access the prefs db in this case, since that would cause UI prefs changes to do unnecessary gl_updates.
+ # (If we ever add a scenegraph node which can enable specular highlights but use outside values for these parameters,
+ # then to make it work correctly we'll need to revise this code.)
+ self.specular_shininess = 20.0
+ self.specular_whiteness = 1.0
+ self.specular_brightness = 1.0
+
+ drawing_globals.allow_color_sorting = env.prefs.get(
+ drawing_globals.allow_color_sorting_prefs_key,
+ drawing_globals.allow_color_sorting_default)
+ drawing_globals.use_color_sorted_dls = env.prefs.get(
+ drawing_globals.use_color_sorted_dls_prefs_key,
+ drawing_globals.use_color_sorted_dls_default)
+ drawing_globals.use_color_sorted_vbos = env.prefs.get(
+ drawing_globals.use_color_sorted_vbos_prefs_key,
+ drawing_globals.use_color_sorted_vbos_default)
+ drawing_globals.use_drawing_variant = env.prefs.get(
+ drawing_globals.use_drawing_variant_prefs_key,
+ drawing_globals.use_drawing_variant_default)
+ drawing_globals.use_c_renderer = (
+ drawing_globals.quux_module_import_succeeded and
+ env.prefs.get(drawing_globals.use_c_renderer_prefs_key,
+ drawing_globals.use_c_renderer_default))
+
+ if drawing_globals.use_c_renderer:
+ quux.shapeRendererSetMaterialParameters(self.specular_whiteness,
+ self.specular_brightness,
+ self.specular_shininess);
+ return
+
+ def materialprefs_summary(self): #bruce 051126
+ """
+ Return a Python data object summarizing our prefs which affect chunk display lists,
+ so that memoized display lists should become invalid (due to changes in this object)
+ if and only if this value becomes different.
+ """
+ res = (self.enable_specular_highlights,)
+ if self.enable_specular_highlights:
+ res = res + ( self.specular_shininess,
+ self.specular_whiteness,
+ self.specular_brightness )
+
+ # grantham 20060314
+ res += (drawing_globals.quux_module_import_succeeded and
+ env.prefs.get(drawing_globals.use_c_renderer_prefs_key,
+ drawing_globals.use_c_renderer_default),)
+
+ # grantham 20060314 - Not too sure this next addition is
+ # really necessary, but it seems to me that for testing
+ # purposes it is important to rebuild display lists if the
+ # color sorting pref is changed.
+ res += (env.prefs.get(drawing_globals.allow_color_sorting_prefs_key,
+ drawing_globals.allow_color_sorting_default),)
+ res += (env.prefs.get(drawing_globals.use_color_sorted_dls_prefs_key,
+ drawing_globals.use_color_sorted_dls_default),)
+ res += (env.prefs.get(drawing_globals.use_color_sorted_vbos_prefs_key,
+ drawing_globals.use_color_sorted_vbos_default),)
+ res += (env.prefs.get(drawing_globals.use_drawing_variant_prefs_key,
+ drawing_globals.use_drawing_variant_default),)
+ return res
+
+ pass # end of class glprefs
+
+drawing_globals.glprefs = glprefs()
diff --git a/cad/src/graphics/drawing/setup_draw.py b/cad/src/graphics/drawing/setup_draw.py
new file mode 100755
index 000000000..00aa33527
--- /dev/null
+++ b/cad/src/graphics/drawing/setup_draw.py
@@ -0,0 +1,544 @@
+# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
+"""
+setup_draw.py - The function to allocate and compile our standard display lists
+into the current GL context, and initialize the globals that hold their opengl
+names.
+
+@version: $Id$
+@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
+
+History:
+
+Originated by Josh as drawer.py .
+
+Various developers extended it since then.
+
+Brad G. added ColorSorter features.
+
+At some point Bruce partly cleaned up the use of display lists.
+
+071030 bruce split some functions and globals into draw_grid_lines.py
+and removed some obsolete functions.
+
+080210 russ Split the single display-list into two second-level lists (with and
+without color) and a set of per-color sublists so selection and hover-highlight
+can over-ride Chunk base colors. ColorSortedDisplayList is now a class in the
+parent's displist attr to keep track of all that stuff.
+
+080311 piotr Added a "drawpolycone_multicolor" function for drawing polycone
+tubes with per-vertex colors (necessary for DNA display style)
+
+080313 russ Added triangle-strip icosa-sphere constructor, "getSphereTriStrips".
+
+080420 piotr Solved highlighting and selection problems for multi-colored
+objects (e.g. rainbow colored DNA structures).
+
+080519 russ pulled the globals into a drawing_globals module and broke drawer.py
+into 10 smaller chunks: glprefs.py setup_draw.py shape_vertices.py
+ColorSorter.py CS_workers.py CS_ShapeList.py CS_draw_primitives.py drawers.py
+gl_lighting.py gl_buffers.py
+"""
+
+import os
+import sys
+
+# the imports from math vs. Numeric are as discovered in existing code
+# as of 2007/06/25. It's not clear why acos is coming from math...
+from math import floor, ceil, acos, atan2
+import Numeric
+from Numeric import sin, cos, sqrt, pi
+degreesPerRadian = 180.0 / pi
+
+# russ 080519 No doubt many of the following imports are unused.
+# When the dust settles, the unnecessary ones will be removed.
+from OpenGL.GL import GL_AMBIENT
+from OpenGL.GL import GL_AMBIENT_AND_DIFFUSE
+from OpenGL.GL import glAreTexturesResident
+from OpenGL.GL import GL_ARRAY_BUFFER_ARB
+from OpenGL.GL import GL_BACK
+from OpenGL.GL import glBegin
+from OpenGL.GL import glBindTexture
+from OpenGL.GL import GL_BLEND
+from OpenGL.GL import glBlendFunc
+from OpenGL.GL import glCallList
+from OpenGL.GL import glColor3f
+from OpenGL.GL import glColor3fv
+from OpenGL.GL import glColor4fv
+from OpenGL.GL import GL_COLOR_MATERIAL
+from OpenGL.GL import GL_COMPILE
+from OpenGL.GL import GL_COMPILE_AND_EXECUTE
+from OpenGL.GL import GL_CONSTANT_ATTENUATION
+from OpenGL.GL import GL_CULL_FACE
+from OpenGL.GL import GL_CURRENT_BIT
+from OpenGL.GL import glDeleteLists
+from OpenGL.GL import glDeleteTextures
+from OpenGL.GL import glDepthMask
+from OpenGL.GL import GL_DEPTH_TEST
+from OpenGL.GL import GL_DIFFUSE
+from OpenGL.GL import glDisable
+from OpenGL.GL import glDisableClientState
+from OpenGL.GL import glDrawArrays
+from OpenGL.GL import glDrawElements
+from OpenGL.GL import glDrawElementsub
+from OpenGL.GL import glDrawElementsui
+from OpenGL.GL import glDrawElementsus
+from OpenGL.GL import GL_ELEMENT_ARRAY_BUFFER_ARB
+from OpenGL.GL import glEnable
+from OpenGL.GL import glEnableClientState
+from OpenGL.GL import glEnd
+from OpenGL.GL import glEndList
+from OpenGL.GL import GL_EXTENSIONS
+from OpenGL.GL import GL_FALSE
+from OpenGL.GL import GL_FILL
+from OpenGL.GL import glFinish
+from OpenGL.GL import GL_FLOAT
+from OpenGL.GL import GL_FOG
+from OpenGL.GL import GL_FOG_COLOR
+from OpenGL.GL import GL_FOG_END
+from OpenGL.GL import GL_FOG_MODE
+from OpenGL.GL import GL_FOG_START
+from OpenGL.GL import GL_FRONT
+from OpenGL.GL import GL_FRONT_AND_BACK
+from OpenGL.GL import glGenLists
+from OpenGL.GL import glGenTextures
+from OpenGL.GL import glGetString
+from OpenGL.GL import GL_LIGHT0
+from OpenGL.GL import GL_LIGHT1
+from OpenGL.GL import GL_LIGHT2
+from OpenGL.GL import glLightf
+from OpenGL.GL import glLightfv
+from OpenGL.GL import GL_LIGHTING
+from OpenGL.GL import GL_LINE
+from OpenGL.GL import GL_LINEAR
+from OpenGL.GL import GL_LINE_LOOP
+from OpenGL.GL import GL_LINES
+from OpenGL.GL import GL_LINE_SMOOTH
+from OpenGL.GL import glLineStipple
+from OpenGL.GL import GL_LINE_STIPPLE
+from OpenGL.GL import GL_LINE_STRIP
+from OpenGL.GL import glLineWidth
+from OpenGL.GL import glLoadIdentity
+from OpenGL.GL import glMaterialf
+from OpenGL.GL import glMaterialfv
+from OpenGL.GL import glMatrixMode
+from OpenGL.GL import GL_MODELVIEW
+from OpenGL.GL import glNewList
+from OpenGL.GL import glNormal3fv
+from OpenGL.GL import glNormalPointer
+from OpenGL.GL import glNormalPointerf
+from OpenGL.GL import GL_NORMAL_ARRAY
+from OpenGL.GL import GL_ONE_MINUS_SRC_ALPHA
+from OpenGL.GL import glPointSize
+from OpenGL.GL import GL_POINTS
+from OpenGL.GL import GL_POINT_SMOOTH
+from OpenGL.GL import GL_POLYGON
+from OpenGL.GL import glPolygonMode
+from OpenGL.GL import glPopAttrib
+from OpenGL.GL import glPopMatrix
+from OpenGL.GL import glPopName
+from OpenGL.GL import GL_POSITION
+from OpenGL.GL import glPushAttrib
+from OpenGL.GL import glPushMatrix
+from OpenGL.GL import glPushName
+from OpenGL.GL import GL_QUADS
+from OpenGL.GL import GL_QUAD_STRIP
+from OpenGL.GL import GL_RENDERER
+from OpenGL.GL import GL_RGBA
+from OpenGL.GL import glRotate
+from OpenGL.GL import glRotatef
+from OpenGL.GL import GL_SHININESS
+from OpenGL.GL import GL_SPECULAR
+from OpenGL.GL import GL_SRC_ALPHA
+from OpenGL.GL import GL_STATIC_DRAW
+from OpenGL.GL import glTexCoord2f
+from OpenGL.GL import glTexCoord2fv
+from OpenGL.GL import GL_TEXTURE_2D
+from OpenGL.GL import glTranslate
+from OpenGL.GL import glTranslatef
+from OpenGL.GL import GL_TRIANGLES
+from OpenGL.GL import GL_TRIANGLE_STRIP
+from OpenGL.GL import GL_TRUE
+from OpenGL.GL import GL_UNSIGNED_BYTE
+from OpenGL.GL import GL_UNSIGNED_SHORT
+from OpenGL.GL import GL_VENDOR
+from OpenGL.GL import GL_VERSION
+from OpenGL.GL import glVertex
+from OpenGL.GL import glVertex2f
+from OpenGL.GL import glVertex3f
+from OpenGL.GL import glVertex3fv
+from OpenGL.GL import GL_VERTEX_ARRAY
+from OpenGL.GL import glVertexPointer
+from OpenGL.GL import glVertexPointerf
+
+from OpenGL.GLU import gluBuild2DMipmaps
+
+from geometry.VQT import norm, vlen, V, Q, A
+
+from utilities.constants import white, blue, red
+from utilities.constants import darkgreen, lightblue
+from utilities.constants import DIAMOND_BOND_LENGTH
+from utilities.prefs_constants import material_specular_highlights_prefs_key
+from utilities.prefs_constants import material_specular_shininess_prefs_key
+from utilities.prefs_constants import material_specular_finish_prefs_key
+from utilities.prefs_constants import material_specular_brightness_prefs_key
+
+from utilities.debug_prefs import Choice
+import utilities.debug as debug # for debug.print_compact_traceback
+
+#=
+
+import graphics.drawing.drawing_globals as drawing_globals
+from graphics.drawing.gl_buffers import GLBufferObject
+from graphics.drawing.shape_vertices import getSphereTriStrips
+from graphics.drawing.shape_vertices import getSphereTriangles
+from graphics.drawing.shape_vertices import indexVerts
+
+import numpy
+
+numSphereSizes = 3
+
+def setup_drawer():
+ """
+ Set up the usual constant display lists in the current OpenGL context.
+
+ WARNING: THIS IS ONLY CORRECT IF ONLY ONE GL CONTEXT CONTAINS DISPLAY LISTS --
+ or more precisely, only the GL context this has last been called in
+ (or one which shares its display lists) will work properly with the routines in drawer.py,
+ since the allocated display list names are stored in globals set by this function,
+ but in general those names might differ if this was called in different GL contexts.
+ """
+ #bruce 060613 added docstring, cleaned up display list name allocation
+ # bruce 071030 renamed from setup to setup_drawer
+
+ spherelistbase = glGenLists(numSphereSizes)
+ sphereList = []
+ for i in range(numSphereSizes):
+ sphereList += [spherelistbase+i]
+ glNewList(sphereList[i], GL_COMPILE)
+ glBegin(GL_TRIANGLE_STRIP) # GL_LINE_LOOP to see edges.
+ stripVerts = getSphereTriStrips(i)
+ for vertNorm in stripVerts:
+ glNormal3fv(vertNorm)
+ glVertex3fv(vertNorm)
+ continue
+ glEnd()
+ glEndList()
+ continue
+ drawing_globals.sphereList = sphereList
+
+ # Sphere triangle-strip vertices for each level of detail.
+ # (Cache and re-use the work of making them.)
+ # Can use in converter-wrappered calls like glVertexPointerfv,
+ # but the python arrays are re-copied to C each time.
+ sphereArrays = []
+ for i in range(numSphereSizes):
+ sphereArrays += [getSphereTriStrips(i)]
+ continue
+ drawing_globals.sphereArrays = sphereArrays
+
+ # Sphere glDrawArrays triangle-strip vertices for C calls.
+ # (Cache and re-use the work of converting a C version.)
+ # Used in thinly-wrappered calls like glVertexPointer.
+ sphereCArrays = []
+ for i in range(numSphereSizes):
+ CArray = numpy.array(sphereArrays[i], dtype=numpy.float32)
+ sphereCArrays += [CArray]
+ continue
+ drawing_globals.sphereCArrays = sphereCArrays
+
+ # Sphere indexed vertices.
+ # (Cache and re-use the work of making the indexes.)
+ # Can use in converter-wrappered calls like glDrawElementsui,
+ # but the python arrays are re-copied to C each time.
+ sphereElements = [] # Pairs of lists (index, verts) .
+ for i in range(numSphereSizes):
+ sphereElements += [indexVerts(sphereArrays[i], .0001)]
+ continue
+ drawing_globals.sphereElements = sphereElements
+
+ # Sphere glDrawElements index and vertex arrays for C calls.
+ sphereCIndexTypes = [] # numpy index unsigned types.
+ sphereGLIndexTypes = [] # GL index types for drawElements.
+ sphereCElements = [] # Pairs of numpy arrays (Cindex, Cverts) .
+ for i in range(numSphereSizes):
+ (index, verts) = sphereElements[i]
+ if len(index) < 256:
+ Ctype = numpy.uint8
+ GLtype = GL_UNSIGNED_BYTE
+ else:
+ Ctype = numpy.uint16
+ GLtype = GL_UNSIGNED_SHORT
+ pass
+ sphereCIndexTypes += [Ctype]
+ sphereGLIndexTypes += [GLtype]
+ sphereCIndex = numpy.array(index, dtype=Ctype)
+ sphereCVerts = numpy.array(verts, dtype=numpy.float32)
+ sphereCElements += [(sphereCIndex, sphereCVerts)]
+ continue
+ drawing_globals.sphereCIndexTypes = sphereCIndexTypes
+ drawing_globals.sphereGLIndexTypes = sphereGLIndexTypes
+ drawing_globals.sphereCElements = sphereCElements
+
+ if glGetString(GL_EXTENSIONS).find("GL_ARB_vertex_buffer_object") >= 0:
+
+ # A GLBufferObject version for glDrawArrays.
+ sphereArrayVBOs = []
+ for i in range(numSphereSizes):
+ vbo = GLBufferObject(GL_ARRAY_BUFFER_ARB,
+ sphereCArrays[i], GL_STATIC_DRAW)
+ sphereArrayVBOs += [vbo]
+ continue
+ drawing_globals.sphereArrayVBOs = sphereArrayVBOs
+
+ # A GLBufferObject version for glDrawElements indexed verts.
+ sphereElementVBOs = [] # Pairs of (IBO, VBO)
+ for i in range(numSphereSizes):
+ ibo = GLBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB,
+ sphereCElements[i][0], GL_STATIC_DRAW)
+ vbo = GLBufferObject(GL_ARRAY_BUFFER_ARB,
+ sphereCElements[i][1], GL_STATIC_DRAW)
+ sphereElementVBOs += [(ibo, vbo)]
+ continue
+ drawing_globals.sphereElementVBOs = sphereElementVBOs
+
+ ibo.unbind()
+ vbo.unbind()
+ pass
+
+ #bruce 060415
+ drawing_globals.wiresphere1list = wiresphere1list = glGenLists(1)
+ glNewList(wiresphere1list, GL_COMPILE)
+ didlines = {} # don't draw each triangle edge more than once
+ def shoulddoline(v1,v2):
+ v1 = tuple(v1) # make sure not list (unhashable) or Numeric array (bug in __eq__)
+ v2 = tuple(v2)
+ if (v1,v2) not in didlines:
+ didlines[(v1,v2)] = didlines[(v2,v1)] = None
+ return True
+ return False
+ def doline(v1,v2):
+ if shoulddoline(v1,v2):
+ glVertex3fv(v1)
+ glVertex3fv(v2)
+ return
+ glBegin(GL_LINES)
+ ocdec = getSphereTriangles(1)
+ for tri in ocdec:
+ #e could probably optim this more, e.g. using a vertex array or VBO or maybe GL_LINE_STRIP
+ doline(tri[0], tri[1])
+ doline(tri[1], tri[2])
+ doline(tri[2], tri[0])
+ glEnd()
+ glEndList()
+
+ drawing_globals.CylList = CylList = glGenLists(1)
+ glNewList(CylList, GL_COMPILE)
+ glBegin(GL_TRIANGLE_STRIP)
+ for (vtop, ntop, vbot, nbot) in drawing_globals.cylinderEdges:
+ glNormal3fv(nbot)
+ glVertex3fv(vbot)
+ glNormal3fv(ntop)
+ glVertex3fv(vtop)
+ glEnd()
+ glEndList()
+
+ drawing_globals.CapList = CapList = glGenLists(1)
+ glNewList(CapList, GL_COMPILE)
+ glNormal3fv(drawing_globals.cap0n)
+ glBegin(GL_POLYGON)
+ for p in drawing_globals.drum0:
+ glVertex3fv(p)
+ glEnd()
+ glNormal3fv(drawing_globals.cap1n)
+ glBegin(GL_POLYGON)
+ #bruce 060609 fix "ragged edge" bug in this endcap: drum1 -> drum2
+ for p in drawing_globals.drum2:
+ glVertex3fv(p)
+ glEnd()
+ glEndList()
+
+ drawing_globals.diamondGridList = diamondGridList = glGenLists(1)
+ glNewList(diamondGridList, GL_COMPILE)
+ glBegin(GL_LINES)
+ for p in drawing_globals.digrid:
+ glVertex(p[0])
+ glVertex(p[1])
+ glEnd()
+ glEndList()
+
+ drawing_globals.lonsGridList = lonsGridList = glGenLists(1)
+ glNewList(lonsGridList, GL_COMPILE)
+ glBegin(GL_LINES)
+ for p in drawing_globals.lonsEdges:
+ glVertex(p[0])
+ glVertex(p[1])
+ glEnd()
+ glEndList()
+
+ drawing_globals.CubeList = CubeList = glGenLists(1)
+ glNewList(CubeList, GL_COMPILE)
+ glBegin(GL_QUAD_STRIP)
+ # note: CubeList has only 4 faces of the cube; only suitable for use in wireframes;
+ # see also solidCubeList [bruce 051215 comment reporting grantham 20051213 observation]
+ glVertex((-1,-1,-1))
+ glVertex(( 1,-1,-1))
+ glVertex((-1, 1,-1))
+ glVertex(( 1, 1,-1))
+ glVertex((-1, 1, 1))
+ glVertex(( 1, 1, 1))
+ glVertex((-1,-1, 1))
+ glVertex(( 1,-1, 1))
+ glVertex((-1,-1,-1))
+ glVertex(( 1,-1,-1))
+ glEnd()
+ glEndList()
+
+ drawing_globals.solidCubeList = solidCubeList = glGenLists(1)
+ glNewList(solidCubeList, GL_COMPILE)
+ glBegin(GL_QUADS)
+ for i in xrange(len(drawing_globals.cubeIndices)):
+ avenormals = V(0,0,0) #bruce 060302 fixed normals for flat shading
+ for j in xrange(4) :
+ nTuple = tuple(
+ drawing_globals.cubeNormals[drawing_globals.cubeIndices[i][j]])
+ avenormals += A(nTuple)
+ avenormals = norm(avenormals)
+ for j in xrange(4) :
+ vTuple = tuple(
+ drawing_globals.cubeVertices[drawing_globals.cubeIndices[i][j]])
+ #bruce 060302 made size compatible with glut.glutSolidCube(1.0)
+ vTuple = A(vTuple) * 0.5
+ glNormal3fv(avenormals)
+ glVertex3fv(vTuple)
+ glEnd()
+ glEndList()
+
+ drawing_globals.rotSignList = rotSignList = glGenLists(1)
+ glNewList(rotSignList, GL_COMPILE)
+ glBegin(GL_LINE_STRIP)
+ for ii in xrange(len(drawing_globals.rotS0n)):
+ glVertex3fv(tuple(drawing_globals.rotS0n[ii]))
+ glEnd()
+ glBegin(GL_LINE_STRIP)
+ for ii in xrange(len(drawing_globals.rotS1n)):
+ glVertex3fv(tuple(drawing_globals.rotS1n[ii]))
+ glEnd()
+ glBegin(GL_TRIANGLES)
+ for v in drawing_globals.arrow0Vertices + drawing_globals.arrow1Vertices:
+ glVertex3f(v[0], v[1], v[2])
+ glEnd()
+ glEndList()
+
+ drawing_globals.linearArrowList = linearArrowList = glGenLists(1)
+ glNewList(linearArrowList, GL_COMPILE)
+ glBegin(GL_TRIANGLES)
+ for v in drawing_globals.linearArrowVertices:
+ glVertex3f(v[0], v[1], v[2])
+ glEnd()
+ glEndList()
+
+ drawing_globals.linearLineList = linearLineList = glGenLists(1)
+ glNewList(linearLineList, GL_COMPILE)
+ glEnable(GL_LINE_SMOOTH)
+ glBegin(GL_LINES)
+ glVertex3f(0.0, 0.0, -drawing_globals.halfHeight)
+ glVertex3f(0.0, 0.0, drawing_globals.halfHeight)
+ glEnd()
+ glDisable(GL_LINE_SMOOTH)
+ glEndList()
+
+ drawing_globals.circleList = circleList = glGenLists(1)
+ glNewList(circleList, GL_COMPILE)
+ glBegin(GL_LINE_LOOP)
+ for ii in range(60):
+ x = cos(ii*2.0*pi/60)
+ y = sin(ii*2.0*pi/60)
+ glVertex3f(x, y, 0.0)
+ glEnd()
+ glEndList()
+
+ # piotr 080405
+ drawing_globals.filledCircleList = filledCircleList = glGenLists(1)
+ glNewList(filledCircleList, GL_COMPILE)
+ glBegin(GL_POLYGON)
+ for ii in range(60):
+ x = cos(ii*2.0*pi/60)
+ y = sin(ii*2.0*pi/60)
+ glVertex3f(x, y, 0.0)
+ glEnd()
+ glEndList()
+
+ drawing_globals.lineCubeList = lineCubeList = glGenLists(1)
+ glNewList(lineCubeList, GL_COMPILE)
+ glBegin(GL_LINES)
+ cvIndices = [0,1, 2,3, 4,5, 6,7, 0,3, 1,2, 5,6, 4,7, 0,4, 1,5, 2,6, 3,7]
+ for i in cvIndices:
+ glVertex3fv(tuple(drawing_globals.cubeVertices[i]))
+ glEnd()
+ glEndList()
+
+ # Debug Preferences
+ from utilities.debug_prefs import debug_pref, Choice_boolean_True
+ from utilities.debug_prefs import Choice_boolean_False
+ choices = [Choice_boolean_False, Choice_boolean_True]
+
+ # 20060314 grantham
+ initial_choice = choices[drawing_globals.allow_color_sorting_default]
+ drawing_globals.allow_color_sorting_pref = debug_pref(
+ "Use Color Sorting?", initial_choice,
+ prefs_key = drawing_globals.allow_color_sorting_prefs_key)
+ #bruce 060323 removed non_debug = True for A7 release, changed default
+ #value to False (far above), and changed its prefs_key so developers
+ #start with the new default value.
+ #russ 080225: Added.
+ initial_choice = choices[drawing_globals.use_color_sorted_dls_default]
+ drawing_globals.use_color_sorted_dls_pref = debug_pref(
+ "Use Color-sorted Display Lists?", initial_choice,
+ prefs_key = drawing_globals.use_color_sorted_dls_prefs_key)
+ #russ 080225: Added.
+ initial_choice = choices[drawing_globals.use_color_sorted_vbos_default]
+ drawing_globals.use_color_sorted_vbos_pref = debug_pref(
+ "Use Color-sorted Vertex Buffer Objects?", initial_choice,
+ prefs_key = drawing_globals.use_color_sorted_vbos_prefs_key)
+
+ #russ 080403: Added drawing variant selection
+ variants = [
+ "0. OpenGL 1.0 - glBegin/glEnd tri-strips vertex-by-vertex.",
+ "1. OpenGL 1.1 - glDrawArrays from CPU RAM.",
+ "2. OpenGL 1.1 - glDrawElements indexed arrays from CPU RAM.",
+ "3. OpenGL 1.5 - glDrawArrays from graphics RAM VBO.",
+ "4. OpenGL 1.5 - glDrawElements, verts in VBO, index in CPU.",
+ "5. OpenGL 1.5 - VBO/IBO buffered glDrawElements."]
+ drawing_globals.use_drawing_variant = debug_pref(
+ "GLPane: drawing method",
+ Choice(names = variants, values = range(len(variants)),
+ defaultValue = drawing_globals.use_drawing_variant_default),
+ prefs_key = drawing_globals.use_drawing_variant_prefs_key)
+
+ # temporarily always print this, while default setting might be in flux,
+ # and to avoid confusion if the two necessary prefs are set differently
+ # [bruce 080305]
+ if (drawing_globals.allow_color_sorting_pref and
+ drawing_globals.use_color_sorted_dls_pref):
+ print "\nnote: this session WILL use color sorted display lists"
+ else:
+ print "\nnote: this session will NOT use color sorted display lists"
+ if (drawing_globals.allow_color_sorting_pref and
+ drawing_globals.use_color_sorted_vbos_pref):
+ print "note: this session WILL use color sorted Vertex Buffer Objects\n"
+ else:
+ print "note: this session will NOT use color sorted Vertex Buffer Objects\n"
+
+ # 20060313 grantham Added use_c_renderer debug pref, can
+ # take out when C renderer used by default.
+ if drawing_globals.quux_module_import_succeeded:
+ initial_choice = choices[drawing_globals.use_c_renderer_default]
+ drawing_globals.use_c_renderer = (
+ debug_pref("Use native C renderer?",
+ initial_choice,
+ prefs_key = drawing_globals.use_c_renderer_prefs_key))
+ #bruce 060323 removed non_debug = True for A7 release,
+ # and changed its prefs_key so developers start over with the default value.
+
+ #initTexture('C:\\Huaicai\\atom\\temp\\newSample.png', 128,128)
+ return # from setup_drawer
diff --git a/cad/src/graphics/drawing/shape_vertices.py b/cad/src/graphics/drawing/shape_vertices.py
new file mode 100755
index 000000000..ca5a4fded
--- /dev/null
+++ b/cad/src/graphics/drawing/shape_vertices.py
@@ -0,0 +1,648 @@
+# Copyright 2004-2008 Nanorex, Inc. See LICENSE file for details.
+"""
+shape_vertices.py - Geometric constructions of vertex lists used by the drawing functions.
+
+This includes vertices for the shapes of primitives that will go into display
+lists in the setup_drawer function in setup_draw.py .
+
+@version: $Id$
+@copyright: 2004-2008 Nanorex, Inc. See LICENSE file for details.
+
+History:
+
+Originated by Josh as drawer.py .
+
+Various developers extended it since then.
+
+Brad G. added ColorSorter features.
+
+At some point Bruce partly cleaned up the use of display lists.
+
+071030 bruce split some functions and globals into draw_grid_lines.py
+and removed some obsolete functions.
+
+080210 russ Split the single display-list into two second-level lists (with and
+without color) and a set of per-color sublists so selection and hover-highlight
+can over-ride Chunk base colors. ColorSortedDisplayList is now a class in the
+parent's displist attr to keep track of all that stuff.
+
+080311 piotr Added a "drawpolycone_multicolor" function for drawing polycone
+tubes with per-vertex colors (necessary for DNA display style)
+
+080313 russ Added triangle-strip icosa-sphere constructor, "getSphereTriStrips".
+
+080420 piotr Solved highlighting and selection problems for multi-colored
+objects (e.g. rainbow colored DNA structures).
+
+080519 russ pulled the globals into a drawing_globals module and broke drawer.py
+into 10 smaller chunks: glprefs.py setup_draw.py shape_vertices.py
+ColorSorter.py CS_workers.py CS_ShapeList.py CS_draw_primitives.py drawers.py
+gl_lighting.py gl_buffers.py
+"""
+
+import os
+import sys
+
+# the imports from math vs. Numeric are as discovered in existing code
+# as of 2007/06/25. It's not clear why acos is coming from math...
+from math import floor, ceil, acos, atan2
+import Numeric
+from Numeric import sin, cos, sqrt, pi
+degreesPerRadian = 180.0 / pi
+
+# russ 080519 No doubt many of the following imports are unused.
+# When the dust settles, the unnecessary ones will be removed.
+from OpenGL.GL import GL_AMBIENT
+from OpenGL.GL import GL_AMBIENT_AND_DIFFUSE
+from OpenGL.GL import glAreTexturesResident
+from OpenGL.GL import GL_ARRAY_BUFFER_ARB
+from OpenGL.GL import GL_BACK
+from OpenGL.GL import glBegin
+from OpenGL.GL import glBindTexture
+from OpenGL.GL import GL_BLEND
+from OpenGL.GL import glBlendFunc
+from OpenGL.GL import glCallList
+from OpenGL.GL import glColor3f
+from OpenGL.GL import glColor3fv
+from OpenGL.GL import glColor4fv
+from OpenGL.GL import GL_COLOR_MATERIAL
+from OpenGL.GL import GL_COMPILE
+from OpenGL.GL import GL_COMPILE_AND_EXECUTE
+from OpenGL.GL import GL_CONSTANT_ATTENUATION
+from OpenGL.GL import GL_CULL_FACE
+from OpenGL.GL import GL_CURRENT_BIT
+from OpenGL.GL import glDeleteLists
+from OpenGL.GL import glDeleteTextures
+from OpenGL.GL import glDepthMask
+from OpenGL.GL import GL_DEPTH_TEST
+from OpenGL.GL import GL_DIFFUSE
+from OpenGL.GL import glDisable
+from OpenGL.GL import glDisableClientState
+from OpenGL.GL import glDrawArrays
+from OpenGL.GL import glDrawElements
+from OpenGL.GL import glDrawElementsub
+from OpenGL.GL import glDrawElementsui
+from OpenGL.GL import glDrawElementsus
+from OpenGL.GL import GL_ELEMENT_ARRAY_BUFFER_ARB
+from OpenGL.GL import glEnable
+from OpenGL.GL import glEnableClientState
+from OpenGL.GL import glEnd
+from OpenGL.GL import glEndList
+from OpenGL.GL import GL_EXTENSIONS
+from OpenGL.GL import GL_FALSE
+from OpenGL.GL import GL_FILL
+from OpenGL.GL import glFinish
+from OpenGL.GL import GL_FLOAT
+from OpenGL.GL import GL_FOG
+from OpenGL.GL import GL_FOG_COLOR
+from OpenGL.GL import GL_FOG_END
+from OpenGL.GL import GL_FOG_MODE
+from OpenGL.GL import GL_FOG_START
+from OpenGL.GL import GL_FRONT
+from OpenGL.GL import GL_FRONT_AND_BACK
+from OpenGL.GL import glGenLists
+from OpenGL.GL import glGenTextures
+from OpenGL.GL import glGetString
+from OpenGL.GL import GL_LIGHT0
+from OpenGL.GL import GL_LIGHT1
+from OpenGL.GL import GL_LIGHT2
+from OpenGL.GL import glLightf
+from OpenGL.GL import glLightfv
+from OpenGL.GL import GL_LIGHTING
+from OpenGL.GL import GL_LINE
+from OpenGL.GL import GL_LINEAR
+from OpenGL.GL import GL_LINE_LOOP
+from OpenGL.GL import GL_LINES
+from OpenGL.GL import GL_LINE_SMOOTH
+from OpenGL.GL import glLineStipple
+from OpenGL.GL import GL_LINE_STIPPLE
+from OpenGL.GL import GL_LINE_STRIP
+from OpenGL.GL import glLineWidth
+from OpenGL.GL import glLoadIdentity
+from OpenGL.GL import glMaterialf
+from OpenGL.GL import glMaterialfv
+from OpenGL.GL import glMatrixMode
+from OpenGL.GL import GL_MODELVIEW
+from OpenGL.GL import glNewList
+from OpenGL.GL import glNormal3fv
+from OpenGL.GL import glNormalPointer
+from OpenGL.GL import glNormalPointerf
+from OpenGL.GL import GL_NORMAL_ARRAY
+from OpenGL.GL import GL_ONE_MINUS_SRC_ALPHA
+from OpenGL.GL import glPointSize
+from OpenGL.GL import GL_POINTS
+from OpenGL.GL import GL_POINT_SMOOTH
+from OpenGL.GL import GL_POLYGON
+from OpenGL.GL import glPolygonMode
+from OpenGL.GL import glPopAttrib
+from OpenGL.GL import glPopMatrix
+from OpenGL.GL import glPopName
+from OpenGL.GL import GL_POSITION
+from OpenGL.GL import glPushAttrib
+from OpenGL.GL import glPushMatrix
+from OpenGL.GL import glPushName
+from OpenGL.GL import GL_QUADS
+from OpenGL.GL import GL_QUAD_STRIP
+from OpenGL.GL import GL_RENDERER
+from OpenGL.GL import GL_RGBA
+from OpenGL.GL import glRotate
+from OpenGL.GL import glRotatef
+from OpenGL.GL import GL_SHININESS
+from OpenGL.GL import GL_SPECULAR
+from OpenGL.GL import GL_SRC_ALPHA
+from OpenGL.GL import GL_STATIC_DRAW
+from OpenGL.GL import glTexCoord2f
+from OpenGL.GL import glTexCoord2fv
+from OpenGL.GL import GL_TEXTURE_2D
+from OpenGL.GL import glTranslate
+from OpenGL.GL import glTranslatef
+from OpenGL.GL import GL_TRIANGLES
+from OpenGL.GL import GL_TRIANGLE_STRIP
+from OpenGL.GL import GL_TRUE
+from OpenGL.GL import GL_UNSIGNED_BYTE
+from OpenGL.GL import GL_UNSIGNED_SHORT
+from OpenGL.GL import GL_VENDOR
+from OpenGL.GL import GL_VERSION
+from OpenGL.GL import glVertex
+from OpenGL.GL import glVertex2f
+from OpenGL.GL import glVertex3f
+from OpenGL.GL import glVertex3fv
+from OpenGL.GL import GL_VERTEX_ARRAY
+from OpenGL.GL import glVertexPointer
+from OpenGL.GL import glVertexPointerf
+
+from OpenGL.GLU import gluBuild2DMipmaps
+
+from geometry.VQT import norm, vlen, V, Q, A
+
+from utilities.constants import white, blue, red
+from utilities.constants import darkgreen, lightblue
+from utilities.constants import DIAMOND_BOND_LENGTH
+from utilities.prefs_constants import material_specular_highlights_prefs_key
+from utilities.prefs_constants import material_specular_shininess_prefs_key
+from utilities.prefs_constants import material_specular_finish_prefs_key
+from utilities.prefs_constants import material_specular_brightness_prefs_key
+
+from utilities.debug_prefs import Choice
+import utilities.debug as debug # for debug.print_compact_traceback
+
+#=
+
+import graphics.drawing.drawing_globals as drawing_globals
+
+def init_icos():
+ global icosa, icosix
+
+ # the golden ratio
+ global phi
+ phi = (1.0+sqrt(5.0))/2.0
+ vert = norm(V(phi,0,1))
+ a = vert[0]
+ b = vert[1]
+ c = vert[2]
+
+ # vertices of an icosahedron
+ icosa = ((-a,b,c), (b,c,-a), (b,c,a), (a,b,-c), (-c,-a,b), (-c,a,b),
+ (b,-c,a), (c,a,b), (b,-c,-a), (a,b,c), (c,-a,b), (-a,b,-c))
+ icosix = ((9, 2, 6), (1, 11, 5), (11, 1, 8), (0, 11, 4), (3, 1, 7),
+ (3, 8, 1), (9, 3, 7), (0, 6, 2), (4, 10, 6), (1, 5, 7),
+ (7, 5, 2), (8, 3, 10), (4, 11, 8), (9, 7, 2), (10, 9, 6),
+ (0, 5, 11), (0, 2, 5), (8, 10, 4), (3, 9, 10), (6, 0, 4))
+ return
+init_icos()
+
+# generate geodesic spheres by subdividing the faces of an icosahedron
+# recursively:
+# /\ /\
+# / \ / \
+# / \ /____\
+# / \ => /\ /\
+# / \ / \ / \
+# /__________\ /____\/____\
+#
+# and normalizing the resulting vectors to the surface of a sphere
+
+def subdivide(tri,deep):
+ if deep:
+ a = tri[0]
+ b = tri[1]
+ c = tri[2]
+ a1 = norm(A(tri[0]))
+ b1 = norm(A(tri[1]))
+ c1 = norm(A(tri[2]))
+ d = tuple(norm(a1+b1))
+ e = tuple(norm(b1+c1))
+ f = tuple(norm(c1+a1))
+ return subdivide((a,d,f), deep-1) + subdivide((d,e,f), deep-1) +\
+ subdivide((d,b,e), deep-1) + subdivide((f,e,c), deep-1)
+ else: return [tri]
+
+## Get the specific detail level of triangles approximation of a sphere
+def getSphereTriangles(level):
+ ocdec = []
+ for i in icosix:
+ ocdec += subdivide((icosa[i[0]],icosa[i[1]],icosa[i[2]]),level)
+ return ocdec
+
+# ==
+
+# Instead of the above recursive scheme that orients the icosahedron with the
+# midpoints of six edges perpendicular to the major axes, use a ring approach
+# to make subdivided icosa-spheres for Triangle Strips. The vertices are
+# grouped in rings from the North Pole to the South Pole. Each strip zig-zags
+# between two rings, and the poles are surrounded by pentagonal Triangle Fans.
+#
+# ----------------
+#
+# The pattern of five-fold vertices in a "twisted orange-slice" segment
+# covering one-fifth of the icosahedron is:
+#
+# ... [3,0] ... (North Pole)
+# / | \
+# / | ...
+# / |
+# ... [2,1]---[2,0] ...
+# / \ / \
+# ... \ / \ ...
+# \ / \ /
+# ... [1,1]---[1,0] ...
+# | /
+# ... | /
+# \ | /
+# ... [0,0] ... (South Pole)
+#
+# ----------------
+#
+# Higher subdivision levels step the strip verts along the icos edges,
+# interpolating intermediate points on the icos and projecting each onto the
+# sphere. Note: sphere vertex normals are the same as their coords.
+#
+# The "*"s show approximate vertex locations at each subdivision level.
+# Bands are numbered from South to North. (Reason explained below.)
+# Sub-band numbers are in angle-brackets, "<>".
+#
+# Level 0 [3*0] Level 1 [6*0] Level 2 [12*0] _<3>
+# / | (2 steps) / | <1> (4 steps) *-* _<2>
+# Band 2 / | * - * *-*-* _<1>
+# / | / | / | <0> *-*-*-* _<0>
+# [2*1]- -[2*0] => [4*2]-*-[4*0] => [8*4]***[8*0] _<3>
+# \ / \ \ / \ / \ <1> *-*-*-*-* _<2>
+# Band 1 \ / \ * - * - * *-*-*-*-* _<1>
+# \ / \ \ / \ / \ <0> *-*-*-*-* _<0>
+# [1*1]---[1*0] [2*2]-*-[2*0] [4*4]***[4*0]_<3>
+# | / | \ | / <1> *-*-*-* _<2>
+# Band 0 | / * - * *-*-* _<1>
+# | / | / <0> *-* _<0>
+# [0*0] [0*0] [0*0]
+#
+# ----------------
+#
+# The reason for rotating east, then going west along the latitude lines, is
+# that the "grain" of triangle strip diagonals runs that way in the middle
+# band of the icos:
+#
+# Triangle Strip triangles
+#
+# 6 ----- 4 ----- 2
+# \5,4,6/ \3,2,4/ \
+# ... \ / \ / \
+# \ /3,4,5\ /1,2,3\
+# 5 ----- 3 ----- 1 <- Vertex order
+#
+# This draws triangles 1-2-3, 3-2-4, 3-4-5, and 5-4-6, all counter-clockwise
+# so the normal directions don't flip-flop.
+#
+# ----------------
+#
+# This version optimizes by concatenating vertices for separate Triangle Fan
+# and Triangle Strip calls into a single long Triangle Strip to minimize calls.
+#
+# In the "pentagon cap" band at the top of the icos, points 2, 4, and 6 in the
+# above example are collapsed to the North Pole; at the bottom, points 1, 3,
+# and 5 are collapsed to the South Pole. This makes "null triangles" with one
+# zero-length edge, and the other two edges echoing one of the other triangle
+# edges (5,4,6 and 3,2,4 at the top, and 3,4,5 and 1,2,3 at the bottom.)
+#
+# In the subdivided caps, the icosahedron bands are split into horizontal
+# sub-bands. In the tapering-in sub-bands in the North cap, there is one less
+# vertex on the top edges of sub-bands, so we collapse the *LAST* triangle
+# there (e.g. 5,4,6 above) On the bottom edges of the South cap bands there
+# is one less vertex, so we collapse the *FIRST* triangle (e.g. 1,2,3.)
+#
+# Similarly, moving from the end of each sub-band to the beginning of the next
+# requires a *pair* of null triangles. We get that by simply concatenating the
+# wrapped triangle strips. We orient point pairs in the triangle strip from
+# south to north, so this works as long as we jog northward between (sub-)bands.
+# This is the reason we start the Triangle Strip with the South Pole band.
+#
+def getSphereTriStrips(level):
+ steps = 2**level
+ points = [] # Triangle Strip vertices o be returned.
+
+ # Construct an icosahedron with two vertices at the North and South Poles,
+ # +-1 on the Y axis, as you look toward the X-Y plane with the Z axis
+ # pointing out at you. The "middle ring" vertices are all at the same
+ # +-latitudes, on the intersection circles of the globe with a polar-axis
+ # cylinder of the proper radius.
+ #
+ # The third "master vertex" of the icosahedron is placed on the X-Y plane,
+ # which intersects the globe at the Greenwich Meridian (the semi-circle at
+ # longitude 0, through Greenwich Observatory, 5 miles south-east of London.)
+ #
+ # The X (distance from the polar axis) and Y (height above the equatorial
+ # plane) of the master vertex make a "golden rectangle", one unit high by
+ # "phi" (1.6180339887498949) wide. We normalize this to put it on the
+ # unit-radius sphere, and take the distance from the axis as the cylinder
+ # radius used to generate the rest of the vertices of the two middle rings.
+ #
+ # Plotted on the globe, the master vertex (first vertex of the North ring)
+ # is lat-long 31.72,0 due south of London in Africa, about 45 miles
+ # south-southwest of Benoud, Algeria. The first vertex of the south ring is
+ # rotated 1/10 of a circle east, at lat-long -31.72,36 in the south end of
+ # the Indian Ocean, about 350 miles east-southeast of Durban, South Africa.
+ #
+ vert0 = norm(V(phi,1,0)) # Project the "master vertex" onto a unit sphere.
+ cylRad = vert0[0] # Icos vertex distance from the Y axis.
+ ringLat = atan2(vert0[1], vert0[0]) * degreesPerRadian # Latitude +-31.72 .
+
+ # Basic triangle-strip icosahedron vertices. Start and end with the Poles.
+ # Reflect the master vertex into the southern hemisphere and rotate 5 copies
+ # to make the middle rings of 5 vertices at North and South latitudes.
+ p2_5 = 2*pi / 5.0
+ # Simplify indexing by replicating the Poles, so everything is in fives.
+ icosRings = [ 5 * [V(0.0, -1.0, 0.0)], # South Pole.
+
+ # South ring, first edge *centered on* the Greenwich Meridian.
+ [V(cylRad*cos((i-.5)*p2_5), -vert0[1], cylRad*sin((i-.5)*p2_5))
+ for i in range(5)],
+
+ # North ring, first vertex *on* the Greenwich Meridian.
+ [V(cylRad*cos(i*p2_5 ), vert0[1], cylRad*sin(i*p2_5))
+ for i in range(5)],
+
+ 5 * [V(0.0, 1.0, 0.0)] ] # North Pole.
+
+
+ # Three bands, going from bottom to top (South to North.)
+ for band in range(3):
+ lowerRing = icosRings[band]
+ upperRing = icosRings[band+1]
+
+ # Subdivide bands into sub-bands. When level == 0, steps == 1,
+ # subBand == 0, and we get just the icosahedron out. (Really!)
+ for subBand in range(steps):
+
+ # Account for the tapering-in at the poles, making less points on
+ # one edge of a sub-band than there are on the other edge.
+ botOffset = 0
+ if band is 0: # South.
+ botSteps = max(subBand, 1) # Don't divide by zero.
+ topSteps = subBand + 1
+ # Collapse the *first* triangle of south sub-band bottom edges.
+ botOffset = -1
+ elif band is 1: # Middle.
+ botSteps = topSteps = steps
+ else: # band is 2: North.
+ botSteps = steps - subBand
+ topSteps = max(steps - (subBand+1), 1)
+ pass
+ subBandSteps = max(botSteps, topSteps)
+
+ # Do five segments, clockwise around the North Pole (East to West.)
+ for seg in range(5):
+ nextseg = (seg+1) % 5 # Wrap-around.
+
+ # Interpolate ends of bottom & top edges of a sub-band segment.
+ fractBot = float(subBand)/float(steps)
+ fractTop = float(subBand+1)/float(steps)
+ sbBotRight = fractBot * upperRing[seg] + \
+ (1.0-fractBot) * lowerRing[seg]
+ sbTopRight = fractTop * upperRing[seg] + \
+ (1.0-fractTop) * lowerRing[seg]
+ sbBotLeft = fractBot * upperRing[nextseg] + \
+ (1.0-fractBot) * lowerRing[nextseg]
+ sbTopLeft = fractTop * upperRing[nextseg] + \
+ (1.0-fractTop) * lowerRing[nextseg]
+
+ # Output the right end of the first segment of the sub-band.
+ # We'll end up wrapping around to this same pair of points at
+ # the left end of the last segment of the sub-band.
+ if seg is 0:
+ # Project verts from icosahedron faces onto the unit sphere.
+ points += [norm(sbBotRight), norm(sbTopRight)]
+
+ # Step across the sub-band edges from right to left,
+ # stitching triangle pairs from their lower to upper edges.
+ for step in range(1, subBandSteps+1):
+
+ # Interpolate step point pairs along the sub-band edges.
+ fractLower = float(step+botOffset)/float(botSteps)
+ lower = fractLower * sbBotLeft + \
+ (1.0-fractLower) * sbBotRight
+ # Collapse the *last* triangle of north sub-band top edges.
+ fractUpper = float(min(step, topSteps))/float(topSteps)
+ upper = fractUpper * sbTopLeft + \
+ (1.0-fractUpper) * sbTopRight
+
+ # Output verts, projected from icos faces onto unit sphere.
+ points += [norm(lower), norm(upper)]
+
+ continue # step
+ continue # seg
+ continue # subBand
+ continue # band
+ return points
+
+def indexVerts(verts, close):
+ """
+ Compress a vertex array into an array of unique vertices, and an array of
+ index values into the unique vertices. This is good for converting input
+ for glDrawArrays into input for glDrawElements.
+
+ The second arg is 'close', the distance between vertices which are close
+ enough to be considered a single vertex.
+
+ The return value is a pair of arrays (index, verts).
+ """
+ unique = []
+ index = []
+ for v in verts:
+ for i in range(len(unique)):
+ if vlen(unique[i] - v) < close:
+ index += [i]
+ break
+ pass
+ else:
+ index += [len(unique)]
+ unique += [v]
+ pass
+ continue
+ return (index, unique)
+
+# ==
+
+def init_cyls():
+ # generate two circles in space as 13-gons,
+ # one rotated half a segment with respect to the other
+ # these are used as cylinder ends [not quite true anymore, see comments just below]
+ slices = 13
+ circ1 = map((lambda n: n*2.0*pi/slices), range(slices+1))
+ circ2 = map((lambda a: a+pi/slices), circ1)
+ drawing_globals.drum0 = drum0 = map((lambda a: (cos(a), sin(a), 0.0)), circ1)
+ drum1 = map((lambda a: (cos(a), sin(a), 1.0)), circ2)
+ drum1n = map((lambda a: (cos(a), sin(a), 0.0)), circ2)
+
+ # grantham 20051213 I finally decided the look of the oddly twisted
+ # cylinder bonds was not pretty enough, so I made a "drum2" which is just
+ # drum0 with a 1.0 Z coordinate, a la drum1.
+ #bruce 060609: this apparently introduced the bug of the drum1 end-cap of a cylinder being "ragged"
+ # (letting empty space show through), which I fixed by using drum2 for that cap rather than drum1.
+ # drum1 is no longer used except as an intermediate value in the next few lines.
+ drawing_globals.drum2 = drum2 = map((lambda a: (cos(a), sin(a), 1.0)), circ1)
+
+ # This edge list zips up the "top" vertex and normal and then
+ # the "bottom" vertex and normal.
+ # Thus each tuple in the sequence would be (vtop, ntop, vbot, nbot) [grantham 20051213]
+ # (bruce 051215 simplified the python usage in a way which should create the same list.)
+ drawing_globals.cylinderEdges = zip(drum0, drum0, drum2, drum0)
+
+ circle = zip(drum0[:-1],drum0[1:],drum1[:-1]) +\
+ zip(drum1[:-1],drum0[1:],drum1[1:])
+ circlen = zip(drum0[:-1],drum0[1:],drum1n[:-1]) +\
+ zip(drum1n[:-1],drum0[1:],drum1n[1:])
+
+ drawing_globals.cap0n = (0.0, 0.0, -1.0)
+ drawing_globals.cap1n = (0.0, 0.0, 1.0)
+ drum0.reverse()
+ return
+init_cyls()
+
+def init_motors():
+ ###data structure to construct the rotation sign for rotary motor
+ numSeg = 20
+ rotS = map((lambda n: pi/2+n*2.0*pi/numSeg), range(numSeg*3/4 + 1))
+ zOffset = 0.005
+ scaleS = 0.4
+ drawing_globals.rotS0n = rotS0n = map(
+ (lambda a: (scaleS*cos(a), scaleS*sin(a), 0.0 - zOffset)), rotS)
+ drawing_globals.rotS1n = rotS1n = map(
+ (lambda a: (scaleS*cos(a), scaleS*sin(a), 1.0 + zOffset)), rotS)
+
+ ###Linear motor arrow sign data structure
+ drawing_globals.halfHeight = 0.45
+ drawing_globals.halfEdge = halfEdge = 3.0 * scaleS * sin(pi/numSeg)
+
+ arrow0Vertices = [
+ (rotS0n[-1][0]-halfEdge, rotS0n[-1][1], rotS0n[-1][2]),
+ (rotS0n[-1][0]+halfEdge, rotS0n[-1][1], rotS0n[-1][2]),
+ (rotS0n[-1][0], rotS0n[-1][1] + 2.0*halfEdge, rotS0n[-1][2])]
+ arrow0Vertices.reverse()
+ drawing_globals.arrow0Vertices = arrow0Vertices
+
+ drawing_globals.arrow1Vertices = [
+ (rotS1n[-1][0]-halfEdge, rotS1n[-1][1], rotS1n[-1][2]),
+ (rotS1n[-1][0]+halfEdge, rotS1n[-1][1], rotS1n[-1][2]),
+ (rotS1n[-1][0], rotS1n[-1][1] + 2.0*halfEdge, rotS1n[-1][2])]
+
+ drawing_globals.halfEdge = halfEdge = 1.0/3.0 ##1.0/8.0
+ drawing_globals.linearArrowVertices = [
+ (0.0, -halfEdge, 0.0), (0.0, halfEdge, 0.0), (0.0, 0.0,2*halfEdge)]
+
+ return
+init_motors()
+
+def init_diamond():
+ # a chunk of diamond grid, to be tiled out in 3d
+ drawing_globals.sp0 = sp0 = 0.0
+ #bruce 051102 replaced 1.52 with this constant (1.544), re bug 900 (partial fix)
+ drawing_globals.sp1 = sp1 = DIAMOND_BOND_LENGTH / sqrt(3.0)
+ sp2 = 2.0*sp1
+ sp3 = 3.0*sp1
+ drawing_globals.sp4 = sp4 = 4.0*sp1
+
+ digrid=[[[sp0, sp0, sp0], [sp1, sp1, sp1]], [[sp1, sp1, sp1], [sp2, sp2, sp0]],
+ [[sp2, sp2, sp0], [sp3, sp3, sp1]], [[sp3, sp3, sp1], [sp4, sp4, sp0]],
+ [[sp2, sp0, sp2], [sp3, sp1, sp3]], [[sp3, sp1, sp3], [sp4, sp2, sp2]],
+ [[sp2, sp0, sp2], [sp1, sp1, sp1]], [[sp1, sp1, sp1], [sp0, sp2, sp2]],
+ [[sp0, sp2, sp2], [sp1, sp3, sp3]], [[sp1, sp3, sp3], [sp2, sp4, sp2]],
+ [[sp2, sp4, sp2], [sp3, sp3, sp1]], [[sp3, sp3, sp1], [sp4, sp2, sp2]],
+ [[sp4, sp0, sp4], [sp3, sp1, sp3]], [[sp3, sp1, sp3], [sp2, sp2, sp4]],
+ [[sp2, sp2, sp4], [sp1, sp3, sp3]], [[sp1, sp3, sp3], [sp0, sp4, sp4]]]
+ drawing_globals.digrid = A(digrid)
+ drawing_globals.DiGridSp = sp4
+ return
+init_diamond()
+
+def init_cube():
+ drawing_globals.cubeVertices = cubeVertices = [
+ [-1.0, 1.0, -1.0], [-1.0, 1.0, 1.0], [1.0, 1.0, 1.0], [1.0, 1.0, -1.0],
+ [-1.0, -1.0, -1.0], [-1.0, -1.0, 1.0], [1.0, -1.0, 1.0], [1.0, -1.0, -1.0]]
+
+ #bruce 051117: compute this rather than letting a subroutine hardcode it as
+ # a redundant constant
+ flatCubeVertices = []
+ for threemore in cubeVertices:
+ flatCubeVertices.extend(threemore)
+ flatCubeVertices = list(flatCubeVertices) #k probably not needed
+ drawing_globals.flatCubeVertices = flatCubeVertices
+
+ if 1: # remove this when it works
+ flatCubeVertices_hardcoded = [-1.0, 1.0, -1.0,
+ -1.0, 1.0, 1.0,
+ 1.0, 1.0, 1.0,
+ 1.0, 1.0, -1.0,
+ -1.0, -1.0, -1.0,
+ -1.0, -1.0, 1.0,
+ 1.0, -1.0, 1.0,
+ 1.0, -1.0, -1.0]
+ assert flatCubeVertices == flatCubeVertices_hardcoded
+
+ sq3 = sqrt(3.0)/3.0
+ drawing_globals.cubeNormals = [
+ [-sq3, sq3, -sq3], [-sq3, sq3, sq3],
+ [sq3, sq3, sq3], [sq3, sq3, -sq3],
+ [-sq3, -sq3, -sq3], [-sq3, -sq3, sq3],
+ [sq3, -sq3, sq3], [sq3, -sq3, -sq3]]
+ drawing_globals.cubeIndices = [
+ [0, 1, 2, 3], [0, 4, 5, 1], [1, 5, 6, 2],
+ [2, 6, 7, 3], [0, 3, 7, 4], [4, 7, 6, 5]]
+
+ return
+init_cube()
+
+
+# Some variables used by the Lonsdaleite lattice construction.
+ux = 1.262; uy = 0.729; dz = 0.5153; ul = 1.544
+drawing_globals.XLen = XLen = 2*ux
+drawing_globals.YLen = YLen = 6*uy
+drawing_globals.ZLen = ZLen = 2*(ul + dz)
+
+def _makeLonsCell():
+ """Data structure to construct a Lonsdaleite lattice cell"""
+ lVp = [# 2 outward vertices
+ [-ux, -2*uy, 0.0], [0.0, uy, 0.0],
+ # Layer 1: 7 vertices
+ [ux, -2*uy, ul], [-ux, -2*uy, ul], [0.0, uy, ul],
+ [ux, 2*uy, ul+dz], [-ux, 2*uy, ul+dz], [0.0, -uy, ul+dz],
+ [-ux, 4*uy, ul],
+ # Layer 2: 7 vertices
+ [ux, -2*uy, 2*(ul+dz)], [-ux, -2*uy, 2*(ul+dz)], [0.0, uy, 2*(ul+dz)],
+ [ux, 2*uy, 2*ul+dz], [-ux, 2*uy, 2*ul+dz], [0.0, -uy, 2*ul+dz],
+ [-ux, 4*uy, 2*(ul+dz)]
+ ]
+
+ res = [ # 2 outward vertical edges for layer 1
+ [lVp[0], lVp[3]], [lVp[1], lVp[4]],
+ # 6 xy Edges for layer 1
+ [lVp[2], lVp[7]], [lVp[3], lVp[7]], [lVp[7], lVp[4]],
+ [lVp[4], lVp[6]], [lVp[4], lVp[5]],
+ [lVp[6], lVp[8]],
+ # 2 outward vertical edges for layer 2
+ [lVp[14], lVp[7]], [lVp[13], lVp[6]],
+ # 6 xy Edges for layer 2
+ [lVp[14], lVp[9]], [lVp[14], lVp[10]], [lVp[14], lVp[11]],
+ [lVp[11], lVp[13]], [lVp[11], lVp[12]],
+ [lVp[13], lVp[15]]
+ ]
+ return res
+drawing_globals.lonsEdges = _makeLonsCell()
diff --git a/cad/src/graphics/widgets/GLPane.py b/cad/src/graphics/widgets/GLPane.py
index df10c8fd0..693e34d3f 100755
--- a/cad/src/graphics/widgets/GLPane.py
+++ b/cad/src/graphics/widgets/GLPane.py
@@ -128,18 +128,18 @@ from geometry.VQT import V, Q, A, norm, vlen, angleBetween
from Numeric import dot
import graphics.drawing.drawing_globals as drawing_globals
-from graphics.drawing.drawer import glprefs_data_used_by_setup_standard_lights
-from graphics.drawing.drawer import drawwiresphere
-from graphics.drawing.drawer import drawFullWindow
-from graphics.drawing.drawer import drawOriginAsSmallAxis
-from graphics.drawing.drawer import drawaxes
-from graphics.drawing.drawer import _default_lights
-from graphics.drawing.drawer import disable_fog
-from graphics.drawing.drawer import enable_fog
-from graphics.drawing.drawer import setup_fog
-from graphics.drawing.drawer import setup_standard_lights
-from graphics.drawing.drawer import glprefs
-from graphics.drawing.drawer import setup_drawer
+from graphics.drawing.gl_lighting import glprefs_data_used_by_setup_standard_lights
+from graphics.drawing.CS_draw_primitives import drawwiresphere
+from graphics.drawing.drawers import drawFullWindow
+from graphics.drawing.drawers import drawOriginAsSmallAxis
+from graphics.drawing.drawers import drawaxes
+from graphics.drawing.gl_lighting import _default_lights
+from graphics.drawing.gl_lighting import disable_fog
+from graphics.drawing.gl_lighting import enable_fog
+from graphics.drawing.gl_lighting import setup_fog
+from graphics.drawing.gl_lighting import setup_standard_lights
+from graphics.drawing.glprefs import glprefs
+from graphics.drawing.setup_draw import setup_drawer
# note: the list of preloaded_command_classes for the Command Sequencer
# has been moved from here (where it didn't belong) to a new file,
diff --git a/cad/src/graphics/widgets/GLPane_minimal.py b/cad/src/graphics/widgets/GLPane_minimal.py
index c1090a850..cd0e26015 100644
--- a/cad/src/graphics/widgets/GLPane_minimal.py
+++ b/cad/src/graphics/widgets/GLPane_minimal.py
@@ -31,7 +31,7 @@ from utilities.debug import print_compact_traceback
import foundation.env as env
-from graphics.drawing.drawer import setup_drawer
+from graphics.drawing.setup_draw import setup_drawer
from graphics.drawing.draw_grid_lines import setup_draw_grid_lines
DEPTH_TWEAK_UNITS = (2.0)**(-32)
diff --git a/cad/src/graphics/widgets/ThumbView.py b/cad/src/graphics/widgets/ThumbView.py
index d85139d34..6a899630e 100755
--- a/cad/src/graphics/widgets/ThumbView.py
+++ b/cad/src/graphics/widgets/ThumbView.py
@@ -64,10 +64,10 @@ from OpenGL.GLU import gluPickMatrix, gluUnProject
from PyQt4.Qt import Qt
from geometry.VQT import V, Q, A
-from graphics.drawing.drawer import drawFullWindow
-from graphics.drawing.drawer import _default_lights
-from graphics.drawing.drawer import setup_standard_lights
-from graphics.drawing.drawer import setup_drawer
+from graphics.drawing.drawers import drawFullWindow
+from graphics.drawing.gl_lighting import _default_lights
+from graphics.drawing.gl_lighting import setup_standard_lights
+from graphics.drawing.setup_draw import setup_drawer
from model.assembly import Assembly
import foundation.env as env
from utilities import debug_flags
diff --git a/cad/src/model/Line.py b/cad/src/model/Line.py
index ffc430d61..cd5ec3fb3 100755
--- a/cad/src/model/Line.py
+++ b/cad/src/model/Line.py
@@ -14,7 +14,7 @@ import foundation.env as env
from OpenGL.GL import glPushMatrix
from OpenGL.GL import glPopMatrix
from OpenGL.GLU import gluProject, gluUnProject
-from graphics.drawing.drawer import drawPolyLine
+from graphics.drawing.drawers import drawPolyLine
from Numeric import dot
from math import pi, cos
diff --git a/cad/src/model/Plane.py b/cad/src/model/Plane.py
index cff5de1be..6f948e7cb 100755
--- a/cad/src/model/Plane.py
+++ b/cad/src/model/Plane.py
@@ -24,7 +24,8 @@ from OpenGL.GL import glPopMatrix
from OpenGL.GL import glTranslatef
from OpenGL.GL import glRotatef
-from graphics.drawing.drawer import drawLineLoop, drawPlane
+from graphics.drawing.drawers import drawLineLoop
+from graphics.drawing.drawers import drawPlane
from utilities.constants import black, orange, yellow, darkgreen, brown
from geometry.VQT import V, Q, cross, planeXline, vlen, norm, ptonline
diff --git a/cad/src/model/chem.py b/cad/src/model/chem.py
index 8fc8e7550..6cabc3832 100755
--- a/cad/src/model/chem.py
+++ b/cad/src/model/chem.py
@@ -56,11 +56,11 @@ import string
from OpenGL.GL import glPushName
from OpenGL.GL import glPopName
-from graphics.drawing.drawer import ColorSorter
-from graphics.drawing.drawer import drawcylinder
-from graphics.drawing.drawer import drawsphere
-from graphics.drawing.drawer import drawpolycone
-from graphics.drawing.drawer import drawwiresphere
+from graphics.drawing.ColorSorter import ColorSorter
+from graphics.drawing.CS_draw_primitives import drawcylinder
+from graphics.drawing.CS_draw_primitives import drawsphere
+from graphics.drawing.CS_draw_primitives import drawpolycone
+from graphics.drawing.CS_draw_primitives import drawwiresphere
from model.elements import Singlet
from model.elements import Hydrogen
diff --git a/cad/src/model/chunk.py b/cad/src/model/chunk.py
index 560257fc5..0278bcb0e 100755
--- a/cad/src/model/chunk.py
+++ b/cad/src/model/chunk.py
@@ -107,8 +107,8 @@ import model.bonds as bonds # TODO: import specific functions, since no longer a
from model.elements import Singlet
from geometry.BoundingBox import BBox
-from graphics.drawing.drawer import ColorSorter
-from graphics.drawing.drawer import ColorSortedDisplayList
+from graphics.drawing.ColorSorter import ColorSorter
+from graphics.drawing.ColorSorter import ColorSortedDisplayList
##from drawer import drawlinelist
##from constants import PickedColor
@@ -145,7 +145,7 @@ from dna.model.Dna_Constants import getComplementSequence
from operations.bond_chains import grow_directional_bond_chain
import graphics.drawing.drawing_globals as drawing_globals
-from graphics.drawing.drawer import apply_material
+from graphics.drawing.gl_lighting import apply_material
from graphics.drawables.Selobj import Selobj_API
diff --git a/cad/src/model/jigs.py b/cad/src/model/jigs.py
index fab764c00..cdb223e67 100755
--- a/cad/src/model/jigs.py
+++ b/cad/src/model/jigs.py
@@ -52,7 +52,7 @@ from utilities.Log import orangemsg
from graphics.rendering.povray.povheader import povpoint
from utilities.debug import print_compact_stack, print_compact_traceback
import foundation.env as env
-from graphics.drawing.drawer import drawwirecube
+from graphics.drawing.drawers import drawwirecube
from utilities.constants import gensym
from utilities.constants import darkgreen
diff --git a/cad/src/model/jigs_measurements.py b/cad/src/model/jigs_measurements.py
index 1d0073381..10513e4cd 100755
--- a/cad/src/model/jigs_measurements.py
+++ b/cad/src/model/jigs_measurements.py
@@ -34,7 +34,7 @@ from utilities.Log import redmsg, greenmsg, orangemsg
from utilities.debug import print_compact_stack, print_compact_traceback
from model.jigs import Jig
from graphics.drawing.dimensions import drawLinearDimension, drawAngleDimension, drawDihedralDimension
-from graphics.drawing.drawer import drawtext
+from graphics.drawing.drawers import drawtext
from utilities.constants import black
from utilities.prefs_constants import dynamicToolTipAtomDistancePrecision_prefs_key
diff --git a/cad/src/model/jigs_motors.py b/cad/src/model/jigs_motors.py
index 78dc6946b..6947c6427 100755
--- a/cad/src/model/jigs_motors.py
+++ b/cad/src/model/jigs_motors.py
@@ -26,10 +26,10 @@ from OpenGL.GL import glPopMatrix
import foundation.env as env
from geometry.VQT import V, Q, A, norm, cross, vlen
-from graphics.drawing.drawer import drawcylinder
-from graphics.drawing.drawer import drawRotateSign
-from graphics.drawing.drawer import drawbrick
-from graphics.drawing.drawer import drawLinearSign
+from graphics.drawing.CS_draw_primitives import drawcylinder
+from graphics.drawing.drawers import drawRotateSign
+from graphics.drawing.drawers import drawbrick
+from graphics.drawing.drawers import drawLinearSign
from utilities.Log import orangemsg
from utilities.Log import redmsg, greenmsg
diff --git a/cad/src/model/jigs_planes.py b/cad/src/model/jigs_planes.py
index 7d33a4e8a..378fdfd7c 100755
--- a/cad/src/model/jigs_planes.py
+++ b/cad/src/model/jigs_planes.py
@@ -26,7 +26,7 @@ from OpenGL.GL import glTranslatef
from OpenGL.GL import glRotatef
from OpenGL.GL import glPopMatrix
-from graphics.drawing.drawer import drawLineLoop
+from graphics.drawing.drawers import drawLineLoop
from graphics.drawing.draw_grid_lines import drawGPGrid
from graphics.drawing.draw_grid_lines import drawSiCGrid
diff --git a/cad/src/model/virtual_site_indicators.py b/cad/src/model/virtual_site_indicators.py
index 0b92f48d6..013b1057d 100644
--- a/cad/src/model/virtual_site_indicators.py
+++ b/cad/src/model/virtual_site_indicators.py
@@ -12,7 +12,8 @@ not as part of their implementation for minimize.
from model.jigs import Jig
from utilities.constants import red, orange, yellow, average_value, ave_colors, blue, gray, darkgreen
-from graphics.drawing.drawer import drawwirecube, drawline
+from graphics.drawing.drawers import drawwirecube
+from graphics.drawing.CS_draw_primitives import drawline
from geometry.VQT import V, vlen
from model.chunk import Chunk
diff --git a/cad/src/ne1_ui/MWsemantics.py b/cad/src/ne1_ui/MWsemantics.py
index e82920335..f197515b4 100755
--- a/cad/src/ne1_ui/MWsemantics.py
+++ b/cad/src/ne1_ui/MWsemantics.py
@@ -37,7 +37,7 @@ from PyQt4.Qt import QStatusBar
from model.elements import PeriodicTable
from model.assembly import Assembly
-from graphics.drawing.drawer import get_gl_info_string ## grantham 20051201
+from graphics.drawing.gl_lighting import get_gl_info_string ## grantham 20051201
import os, sys
import time
diff --git a/cad/src/prototype/example_expr_command.py b/cad/src/prototype/example_expr_command.py
index 403901003..454a06279 100644
--- a/cad/src/prototype/example_expr_command.py
+++ b/cad/src/prototype/example_expr_command.py
@@ -58,7 +58,7 @@ class ExampleCommand2E_PM( ExampleCommand2_PM ):
# these imports are not needed in a minimal example like ExampleCommand2:
-from graphics.drawing.drawer import drawline
+from graphics.drawing.CS_draw_primitives import drawline
from utilities.constants import red
from geometry.VQT import V
from exprs.instance_helpers import get_glpane_InstanceHolder
diff --git a/cad/src/prototype/test_connectWithState.py b/cad/src/prototype/test_connectWithState.py
index 8342cce2a..211204163 100644
--- a/cad/src/prototype/test_connectWithState.py
+++ b/cad/src/prototype/test_connectWithState.py
@@ -61,8 +61,8 @@ from utilities.constants import pink, white
DX = V(1,0,0)
DY = V(0,1,0)
ORIGIN = V(0,0,0)
-from graphics.drawing.drawer import drawcylinder, drawsphere
-
+from graphics.drawing.CS_draw_primitives import drawcylinder
+from graphics.drawing.CS_draw_primitives import drawsphere
from exprs.ExprsMeta import ExprsMeta
from exprs.instance_helpers import IorE_guest_mixin
from exprs.attr_decl_macros import Instance, State
diff --git a/cad/src/temporary_commands/LineMode.py b/cad/src/temporary_commands/LineMode.py
index fe06ca48a..9247768c1 100644
--- a/cad/src/temporary_commands/LineMode.py
+++ b/cad/src/temporary_commands/LineMode.py
@@ -21,7 +21,8 @@ TODOs:
from commands.Select.Select_Command import Select_Command
from commands.Select.Select_GraphicsMode import Select_GraphicsMode
-from graphics.drawing.drawer import drawline, drawsphere
+from graphics.drawing.CS_draw_primitives import drawline
+from graphics.drawing.CS_draw_primitives import drawsphere
from utilities.constants import black, darkred, blue
from geometry.VQT import vlen, norm, angleBetween, V, ptonline
diff --git a/cad/src/temporary_commands/ZoomToAreaMode.py b/cad/src/temporary_commands/ZoomToAreaMode.py
index de376b13e..2c0257334 100755
--- a/cad/src/temporary_commands/ZoomToAreaMode.py
+++ b/cad/src/temporary_commands/ZoomToAreaMode.py
@@ -28,7 +28,7 @@ from OpenGL.GL import glReadPixelsf
from OpenGL.GLU import gluUnProject
from geometry.VQT import V, A
-from graphics.drawing.drawer import drawrectangle
+from graphics.drawing.drawers import drawrectangle
from utilities.constants import GL_FAR_Z