| accessing |
| boundsChanged
|
boundsChanged _ true.
|
| boundsDepth
|
^ boundsDepth.
|
| boundsDepth: depth
|
boundsDepth _ depth.
frameChildren ifNotNil:[ frameChildren do:[ :fc | fc boundsDepth: depth].].
self boundsChanged.
|
| collapse
|
"Forces all frames to identity transform while retaining translation, and pushes the previous transform to the frame children. This is used primarily for meshes and their supporting groups."
| orient|
orient _ self orientation.
1 to: vertices size do:[ :index |
vertices at: index put:(orient localPointToGlobal: (vertices at: index)).].
1 to: vtxNormals size do:[ :index |
vtxNormals at: index put:(orient localPointToGlobal:( vtxNormals at: index)).].
super collapse.
|
| colorize: col
|
self materialList do:[ :ml |
ml ambientColor: col.
ml diffuseColor: col.
ml textureMode: GLModulate.
].
self resetCaching.
self checkAlpha.
frameChildren ifNotNil:[frameChildren do:[ :fc | fc colorize: col].].
|
| faceGroupsDo: aBlock
|
1 to: faceGroups size by: 2 do:[ :i | aBlock value: (faceGroups at: i+1)].
|
| forceGlobalToLocal
|
"This is used by TMesh where we assume that the imported vertices are pre-transformed and we want to put them back into their untransformed state. Only TMesh will probably need this, but TMeshes can have TGroups which don't know what to do."
| invMat invOrient |
frameChildren ifNotNil:[ frameChildren do:[ :fc | fc forceGlobalToLocal.]].
invMat _ self localTransform orthoNormInverse.
invOrient _ self orientation orthoNormInverse.
1 to: vertices size do:[ :index |
vertices at: index put:(invMat localPointToGlobal: (vertices at: index)).].
1 to: vtxNormals size do:[ :index |
vtxNormals at: index put:(invOrient localPointToGlobal: (vtxNormals at: index)).].
frameParent ifNotNil:[
self localTransform: (
frameParent localTransform orthoNormInverse composeWith: self localTransform).
].
|
| frameBox
|
"Answer the local bounding box of this frame"
boundsChanged ifTrue:[self initBounds].
boundSphere ifNil:[^super frameBox].
^boundSphere box ifNil:[super frameBox]
|
| fullBright: bool
|
super fullBright: bool.
materialList ifNotNil:[ materialList do:[ :ml | ml fullBright: bool]].
|
| hasAlpha: bool
|
alpha _ bool.
|
| inertiaTensor
|
| it |
it _ TTensor initialize.
1 to: faceGroups size by: 2 do:[:i |
it addFaces: (faceGroups at: i+1) vertices: vertices.].
^ it.
|
| isSolid
|
^ solid
|
| material
|
^materialList first
|
| material: aMaterial
|
materialList at: 1 put: aMaterial
|
| materialList
|
^ materialList.
|
| materialList: ml
|
materialList _ ml.
self checkAlpha.
|
| normals
|
^vtxNormals
|
| normals: normals
|
vtxNormals := normals
|
| opaque
|
^ opaque.
|
| opaque: bool
|
opaque _ bool.
|
| pick: pointer
|
" We are here because we already picked the top level boundSphere, so we know that is true. Now what we need to test against the hierarchy, which will return a list of faces if true - otherwise, it will return nil."
^ boundSphere pickChildren: pointer.
|
| scale: scale
|
vertices *= scale.
super scale: scale.
self scaleBounds: scale.
"self boundsChanged."
|
| scaleBounds: scale
|
boundSphere ifNil: [self boundsChanged. ^ self].
boundSphere scale: scale.
|
| transparency: trans
|
self materialList do:[ :ml |
ml transparency: trans.
].
self checkAlpha.
frameChildren ifNotNil:[frameChildren do:[ :fc | fc transparency: trans].].
|
| vertices
|
^vertices
|
| vertices: verts
|
vertices _ verts.
|
| initialize |
| checkAlpha
|
opaque _ false.
alpha _ false.
1 to: faceGroups size by: 2 do:[:i |
((materialList at:(faceGroups at: i)) hasAlpha) ifTrue: [ self hasAlpha: true. ] ifFalse:[ self opaque: true.].
].
boundMaterial ifNotNil:[self hasAlpha: true].
|
| initBounds
|
boundsDepth = 0 ifTrue:[
boundSphere _ TBoundSphere mtfBall: vertices. ]
ifFalse:[
faceGroups size = 2 ifTrue:[
boundSphere _
TBoundSphere calcTree: vertices faces: (faceGroups at: 2) depth: boundsDepth. ]
ifFalse:[
boundSphere _ TBoundSphere mtfBall: vertices.
1 to: faceGroups size by: 2 do:[ :i || child |
child _
TBoundSphere calcTree: vertices faces: (faceGroups at: i+1) depth: boundsDepth-1.
boundSphere addChild: child.].
].].
boundSphere frame: self.
boundsChanged _ false.
|
| initializeWithVertices: v alias: a norms: n textureUV: tuv faceGroups: fg material: ml
|
| mat |
super initialize.
vertices _ v.
alias _ a.
vtxNormals _ n.
textureUV _ tuv.
faceGroups _ fg.
alpha_ false.
opaque _ false.
mat _ ml.
mat ifNil:[
mat _ TMaterial new.
mat ambientColor: #(1.0 0.2 0.2 0.5) asFloatArray.
].
mat subMaterialList ifNotNil:[ materialList _ mat subMaterialList. ]
ifNil:[
materialList _ OrderedCollection new.
materialList add: mat.
1 to: faceGroups size by: 2 do:[ :i |
faceGroups at: i put: 1. ].].
1 to: faceGroups size by: 2 do:[:i |
faceGroups at: i put: 1+(((faceGroups at: i)-1)\\materialList size).
((materialList at:(faceGroups at: i)) hasAlpha) ifTrue: [ self hasAlpha: true.] ifFalse:[ self opaque: true].
].
self optimizeFaceGroups.
boundsDepth _ 2. "must always be a mimimum of 1 - the top sphere, and at least one recursion."
self boundsChanged.
glListID _ nil.
glListAlphaID _ nil.
self enableCaching.
" This code is used to test the bounds sphere."
" boundMaterial _ TMaterial new.
boundMaterial ambientColor: #(0.7 0.2 0.1 0.3)asFloatArray.
boundMaterial diffuseColor: #(0.7 0.2 0.1 0.3)asFloatArray.
alpha _ true."
^self
|
| optimizeFaceGroups
|
"Optimize the face groups to minimize state changes"
| matList faces index |
matList := IdentityDictionary new.
1 to: faceGroups size by: 2 do:[:i|
index := faceGroups at: i.
faces := faceGroups at: i+1.
matList at: index put: ((matList at: index ifAbsent:[#()]) copyWith: faces).
].
index := 0.
matList keysAndValuesDo:[:mIndex :fList|
fList do:[:fGroup|
faceGroups at: (index := index+1) put: mIndex.
faceGroups at: (index := index+1) put: fGroup.
].
].
|
| validateFaceGroups
|
"Check to see if all face groups are valid. For debugging only."
| vtxSize face |
vtxSize := vertices size.
vtxNormals ifNotNil:[
vtxNormals size = vertices size ifFalse:[self error:'normal size mismatch'].
].
textureUV ifNotNil:[
textureUV size = vertices size ifFalse:[self error:'texture size mismatch'].
].
self faceGroupsDo:[:fg|
fg basicSize \\ 3 = 0 ifFalse:[self error:'Face group not divisable by 3'].
1 to: fg basicSize do:[:i|
face := fg basicAt: i.
(face >= 0 and:[face < vtxSize]) ifFalse:[self error:'Vertex out of range'].
].
].
|
| render |
| boundSphere
|
boundsChanged ifTrue:[
self initBounds.
boundsChanged _ false.
].
^ boundSphere.
|
| disableCaching
|
cachingEnabled _ false.
cachingAlphaEnabled _ false.
|
| enableCaching
|
cachingEnabled _ true.
cachingAlphaEnabled _ true.
|
| hasAlpha
|
^ alpha.
|
| oldRender: ogl
|
self opaque ifTrue:[
(cachingEnabled = true) ifFalse:[
(glListID notNil and:[ glInstance = ogl instance]) ifTrue:[
ogl glDeleteLists: glListID with: 1.
ogl unregisterList: self.
].
glListID _ nil.
cachingEnabled = #reset ifTrue:[ cachingEnabled _ true.].
^self renderPrimitive: ogl alpha: false.
].
"if there is a cached list and ogl has not changed, call it"
(glListID notNil and: [glInstance = ogl instance]) ifTrue:[
ogl glCallList: glListID.
] ifFalse:[
glListID _ ogl glGenLists: 1.
ogl registerList: glListID range: 1 owner: self.
glInstance _ nil.
ogl glNewList: glListID with: GLCompileAndExecute.
self renderPrimitive: ogl alpha: false.
"See if current display list completed correctly.
If any other has been constructed in the mean time
defer this lists creation until the next rendering loop."
(ogl glGetInteger: GLListIndex) = glListID ifTrue:[glInstance _ ogl instance].
ogl glEndList.
].
].
|
| oldRenderAlpha: ogl
|
(cachingAlphaEnabled = true) ifFalse:[
(glListAlphaID notNil and:[ glInstance = ogl instance]) ifTrue:[
ogl glDeleteLists: glListAlphaID with: 1.
ogl unregisterList: self.
].
glListAlphaID _ nil.
cachingAlphaEnabled = #reset ifTrue:[ cachingAlphaEnabled _ true.].
^self renderPrimitive: ogl alpha: true.
].
"if there is a cached list and ogl has not changed, call it"
(glListAlphaID notNil and: [glInstance = ogl instance]) ifTrue:[
ogl glCallList: glListAlphaID.
] ifFalse:[
glListAlphaID _ ogl glGenLists: 1.
ogl registerList: glListAlphaID range: 1 owner: self.
glInstance _ nil.
ogl glNewList: glListAlphaID with: GLCompileAndExecute.
self renderPrimitive: ogl alpha: true.
"See if current display list completed correctly.
If any other has been constructed in the mean time
defer this lists creation until the next rendering loop."
(ogl glGetInteger: GLListIndex) = glListAlphaID ifTrue:[glInstance _ ogl instance].
ogl glEndList.
].
|
| render: ogl
|
^self renderPrimitive: ogl alpha: false.
|
| renderAlpha: ogl
|
^self renderPrimitive: ogl alpha: true.
|
| renderPrimitive: ogl alpha: alphaPass
|
| lastMat nextMat |
lastMat := nil.
1 to: faceGroups size by: 2 do:[ :i |
nextMat _ materialList at: (faceGroups at: i).
nextMat hasAlpha = alphaPass ifTrue:[
nextMat == lastMat ifFalse:[
lastMat ifNotNil:[lastMat disable: ogl].
nextMat enable: ogl.
lastMat := nextMat.
].
ogl drawIndexedTriangles: (faceGroups at: i+1)
vertices: vertices
normals: vtxNormals
colors: nil texCoords: textureUV.
].
].
lastMat ifNotNil:[lastMat disable: ogl].
" boundSphere renderBox: self."
|
| resetCaching
|
cachingEnabled _ #reset.
cachingAlphaEnabled _ #reset.
|