TBox


Croquet-Teapot

Comment:

TBox has a number of uses. It is an axis aligned bounding box (AABB) defined by two 3D corners. It is used by the TBoundSphere to help define the boundSphere tree. 

Hierarchy:

ProtoObject
Object
TBox

Summary:

instance variables:

maxCorner minCorner

methods:

instance class
accessing comparing initialize math render instance creation

Detail:

instance variables:

maxCorner
minCorner

instance methods:

accessing
atRandom: segments


	| dm |
	dm _ (maxCorner - minCorner)/segments.
	^ B3DVector3 x:(dm x * (segments atRandom) + minCorner x) 
				y:(dm y * (segments atRandom) + minCorner y)
				z:(dm z * (segments atRandom) + minCorner z).
center


	^ (minCorner + maxCorner)/2.0.
centerX


	^ (minCorner x + maxCorner x)/2.0.
centerY


	^ (minCorner y + maxCorner y)/2.0.
centerZ


	^ (minCorner z + maxCorner z)/2.0.
corner

	^maxCorner
cornerVertices

	"Answer all the vertices defining the corners of this block"
	| out |
	out := (WriteStream on: (Array new: 8)).
	self cornerVerticesDo:[:vtx| out nextPut: vtx].
	^out contents
cornerVerticesDo: aBlock

	"Evaluate aBlock with all the vertices defining the corners of this block"
	| min max |
	min := minCorner.
	max := maxCorner.
	aBlock value: min x @ min y @ min z.
	aBlock value: min x @ min y @ max z.
	aBlock value: min x @ max y @ min z.
	aBlock value: min x @ max y @ max z.
	aBlock value: max x @ min y @ min z.
	aBlock value: max x @ min y @ max z.
	aBlock value: max x @ max y @ min z.
	aBlock value: max x @ max y @ max z.
diagonal


	^ (maxCorner - minCorner)length.
extent


	^ maxCorner - minCorner.
extentMax



	^ (maxCorner - minCorner) max.
extentMin


	^ (maxCorner - minCorner) min.

extentX


	^ maxCorner x - minCorner x.
extentY


	^ maxCorner y - minCorner y.
extentZ


	^ maxCorner z - minCorner z.
growVertex: v


	minCorner _ minCorner min: v.
	maxCorner _ maxCorner max: v.
max


	^ maxCorner.
max: mx


	maxCorner _ mx.
merge: aBox

	"Answer a Box that contains both the receiver and aBox."

	^TBox 
		origin: (self origin min: aBox origin)
		corner: (self corner max: aBox corner)
min


	^ minCorner.
min: mn


	minCorner _ mn.
origin

	^minCorner
radius


	^ self diagonal/2.0.
scale: scale


	minCorner _ minCorner * scale.
	maxCorner _ maxCorner * scale.
splitXMax


	| corner |
	corner _ self min copy.
	corner x: self centerX.
	^ TBox min: corner max: self max copy.
splitXMin


	| corner |
	corner _ self max copy.
	corner x: self centerX.
	^ TBox min: self min copy max: corner.
splitYMax


	| corner |
	corner _ self min copy.
	corner y: self centerY.
	^ TBox min: corner max: self max copy.
splitYMin


	| corner |
	corner _ self max copy.
	corner y: self centerY.
	^ TBox min: self min copy max: corner.
splitZMax


	| corner |
	corner _ self min copy.
	corner z: self centerZ.
	^ TBox min: corner max: self max copy.
splitZMin


	| corner |
	corner _ self max copy.
	corner z: self centerZ.
	^ TBox min: self min copy max: corner.
transformedBy: aTransform

	"Answer a box transformed by the given transformation"
	| aVertex min max |
	min := max := nil.
	self cornerVerticesDo:[:vtx| 
		aVertex := aTransform localPointToGlobal: vtx.
		min ifNil:[
			min := max := aVertex.
		] ifNotNil:[
			min := min min: aVertex.
			max := max max: aVertex.
		].
	].
	^TBox origin: min corner: max
translatedBy: delta

	"Answer a box transformed by the given transformation"
	^TBox origin: minCorner + delta corner: maxCorner + delta

comparing
axisTestXv1: v1 v2: v2 a: a b: b fa: fa fb: fb


	| p0 p1 min max rad |

	p0 _ (a * v1 y) - (b * v1 z).
	p1 _ (a * v2 y) - (b * v2 z).
	p0 < p1 ifTrue:[min _ p0. max _ p1.] ifFalse:[min _ p1. max _ p0.].
	rad _ ((fa * self extentY) + (fb * self extentZ))/2.0.
	(min > rad or:[max < (rad negated)]) ifTrue:[^ false.].
	^ true.
axisTestYv1: v1 v2: v2 a: a b: b fa: fa fb: fb


	| p0 p1 min max rad |

	p0 _ (b * v1 z) - (a * v1 x).
	p1 _ (b * v2 z) - (a * v2 x).
	p0 < p1 ifTrue:[min _ p0. max _ p1.] ifFalse:[min _ p1. max _ p0.].
	rad _ ((fa * self extentX) + (fb * self extentZ))/2.0.
	(min > rad or:[max < (rad negated)]) ifTrue:[^ false.].
	^ true.
axisTestZv1: v1 v2: v2 a: a b: b fa: fa fb: fb


	| p0 p1 min max rad |

	p0 _ (a * v1 x) - (b * v1 y).
	p1 _ (a * v2 x) - (b * v2 y).
	p0 < p1 ifTrue:[min _ p0. max _ p1.] ifFalse:[min _ p1. max _ p0.].
	rad _ ((fa * self extentX) + (fb * self extentY))/2.0.
	(min > rad or:[max < (rad negated)]) ifTrue:[^ false.].
	^ true.
intersectBox: bx

	| mn mx |
	mn _ bx min max: self min.
	mx _ bx max min: self max.
	^ TBox min: mn max: mx.
intersectT1: t1 T2: t2 T3: t3


	| v1 v2 v3 e1 e2 e3 a1 a2 a3 center tNormal d vmin vmax |
" This method is based upon:
	Fast 3D Triangle-Box Overlap Testing 
	Tomas Akenine-Moller
	March 2001, updated June 2001.

The order of this code is somewhat different from that presented in the example C source provided with the paper.

Though this is considered to be the fastest test in the graphics literature, I think that there is a better approach by attempting to construct a seperating plane between the two objects. Since I am not currently using it for real-time work, I won't worry about it."

" First, the naive test - is the triangle all on one side of a half-plane?"
	(t1 x < minCorner x and:[ t2 x < minCorner x and:[ t3 x < minCorner x]]) 
		ifTrue:[ ^ false. ].
	(t1 x > maxCorner x and:[. t2 x > maxCorner x and:[ t3 x > maxCorner x]]) 
		ifTrue:[ ^ false. ].
	(t1 y < minCorner y and:[ t2 y < minCorner y and:[ t3 y < minCorner y]]) 
		ifTrue:[^ false. ].
	(t1 y > maxCorner y and:[ t2 y > maxCorner y and:[ t3 y > maxCorner y]]) 
		ifTrue:[ ^ false. ].
	(t1 z < minCorner z and:[ t2 z < minCorner z and:[ t3 z < minCorner z]]) 
		ifTrue:[ ^ false. ].
	(t1 z > maxCorner z and:[ t2 z > maxCorner z and:[ t3 z > maxCorner z]]) 
		ifTrue:[ ^ false. ].
" Second, the cross product (edge from tri, (x y z) direction. "
	center _ self center.
	v1 _ t1 - center.
	v2 _ t2 - center.
	v3 _ t3 - center.

	e1 _ t2 - t1.
	a1 _ e1 abs.
	(self axisTestXv1:v1 v2:v3 a: e1 z  b: e1 y fa: a1 z fb: a1 y) ifFalse:[^ false.].
	(self axisTestYv1:v1 v2:v3 a: e1 z b: e1 x fa: a1 z fb: a1 x) ifFalse:[^ false.].
	(self axisTestZv1:v2 v2:v3 a: e1 y b: e1 x fa: a1 y fb: a1 x) ifFalse:[^ false.].

	e2 _ t3 - t2.
	a2 _ e2 abs.
	(self axisTestXv1:v1 v2:v3 a: e2 z  b: e2 y fa: a2 z fb: a2 y) ifFalse:[^ false.].
	(self axisTestYv1:v1 v2:v3 a: e2 z b: e2 x fa: a2 z fb: a2 x) ifFalse:[^ false.].
	(self axisTestZv1: v1 v2:v2 a:e2 y b: e2 x fa: a2 y fb: a2 x) ifFalse:[^ false.].

	e3 _ t1 - t3.
	a3 _ e3 abs.
	(self axisTestXv1:v1 v2:v2 a: e3 z  b: e3 y fa: a3 z fb: a3 y) ifFalse:[^ false.].
	(self axisTestYv1:v1 v2:v2 a: e3 z b: e3 x fa: a3 z fb: a3 x) ifFalse:[^ false.].
	(self axisTestZv1:v2 v2:v3 a: e3 y b: e3 x fa: a3 y fb: a3 x) ifFalse:[^ false.].

" Third, test if the box intersects the plane of the triangle."

	tNormal _ e1 cross: e2.
	d _ (tNormal dot: v1)negated.
	vmin _ B3DVector3 new.	
	vmax _ B3DVector3 new.
	
	tNormal x>0.0 ifTrue:[
		vmin x: self extentX negated.
		vmax x: self extentX.] ifFalse:[
		vmin x: self extentX.
		vmax x: self extentX negated.].
	tNormal y>0.0 ifTrue:[
		vmin y: self extentY negated.
		vmax y: self extentY.] ifFalse:[
		vmin y: self extentY.
		vmax y: self extentY negated.].
	tNormal z>0.0 ifTrue:[
		vmin z: self extentZ negated.
		vmax z: self extentZ.] ifFalse:[
		vmin z: self extentZ.
		vmax z: self extentZ negated.].
	(tNormal dot: vmin)+d >0.0 ifTrue:[^ false. ].
	(tNormal dot: vmax)+d >= 0.0 ifTrue:[^ true.].
	^ true.
	
pointInBox: v


	v x < minCorner x ifTrue:[^ false.].
	v x > maxCorner x ifTrue:[^ false.].
	v y < minCorner y ifTrue:[^ false.].
	v y > maxCorner y ifTrue:[^ false.].
	v z < minCorner z ifTrue:[^ false.].
	v z > maxCorner z ifTrue:[^ false. ].
	^ true.
pointOverBox: v


	v x < minCorner x ifTrue:[^ false.].
	v x > maxCorner x ifTrue:[^ false.].
"	v y < minCorner y ifTrue:[^ false.].
	v y > maxCorner y ifTrue:[^ false.]."
	v z < minCorner z ifTrue:[^ false.].
	v z > maxCorner z ifTrue:[^ false. ].
	^ true.
unionBox: bx

	| mn mx |
	mn _ bx min min: self min.
	mx _ bx max max: self max.
	^ TBox min: mn max: mx.
unionSphere: position radius: radius

	| mn mx |
	mn _ (position - radius) min: self min.
	mx _ (position + radius) max: self max.
	^ TBox min: mn max: mx.

initialize
initialize

	| iP iN |

" Defines an infinitely empty box - min is positive infinity, max is negative infinity. We then add vertices to the box via the #growVertex: method to 'grow' it."

	iP _ Float infinity.
	iN _ Float infinity negated.
	minCorner _ B3DVector3 x: iP y: iP z: iP.
	maxCorner _ B3DVector3 x: iN y: iN z: iN.
min: mn max: mx


	minCorner _ mn.
	maxCorner _ mx.

math
* aNumber


	
	^ TBox min: (minCorner * aNumber) max: (maxCorner * aNumber).
addBox: aBox


	^ TBox min: minCorner + aBox min max: maxCorner + aBox max.

render
render: ogl frame: frm


	frm render: ogl box: self

class methods:

instance creation
min: mn max: mx


	^ self new min:mn max: mx.
new

	^self basicNew
		initialize. "public constructor"
origin: origin corner: corner


	^ self new min: origin max: corner.

^top


- made by Dandelion -