'From Squeak3.6 of ''6 October 2003'' [latest update: #5429] on 26 February 2007 at 2:58:04 pm'! "Change Set: earthSwarms Date: 19 February 2007 Author: Bruce O'Neel Please make sure you load the B3DTutorialFix change set as well. "! Object subclass: #EarthSwarms instanceVariableNames: 'scene ' classVariableNames: '' poolDictionaries: '' category: 'EarthSwarms'! !EarthSwarms commentStamp: 'BEO 2/25/2007 16:33' prior: 0! EarthSwarms main class. Copies from B3DDemoSurfaces. EarthSwarms main.! BorderedMorph subclass: #EarthSwarmsPresenterMorph instanceVariableNames: 'wheels frameWidth b3DSceneMorph source textAccessor ' classVariableNames: '' poolDictionaries: '' category: 'EarthSwarms'! !EarthSwarmsPresenterMorph commentStamp: 'BEO 2/25/2007 16:52' prior: 0! This is a slightly modified copy of B3DSceneExplorerMorph and B3DTutorialScenePresenterMorph.! !EarthSwarms methodsFor: 'toplevel' stamp: 'BEO 2/25/2007 16:46'! main self show.! ! !EarthSwarms methodsFor: 'toplevel' stamp: 'BEO 2/25/2007 17:14'! show " EarthSwarms new show" | view | self createScene. (view := EarthSwarmsPresenterMorph new) source: self description: #descriptionScene; scene: scene. view rotateX: 12.0. view clearColor: (Color gray: 0.86). view addFrameAndExplanationField openInWorldExtent: Display extent x//2 @ (Display extent y * 7 // 8).! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/25/2007 17:41'! createLightsForScene: aScene | light1 light2 light3 light4 | light1 := B3DDirectionalLight new. light1 direction: 100 @ -20 @ 0. light1 lightColor: (B3DMaterialColor color: (Color r: 0.75 g: 0.28 b: 0.28)). scene lights add: light1. light2 := B3DDirectionalLight new. light2 direction: (240 degreesToRadians cos) * 100 @ -20 @ (240 degreesToRadians sin * 100). light2 lightColor: (B3DMaterialColor color: (Color r: 0.25 g: 0.8 b: 0.25)). scene lights add: light2. light3 := B3DDirectionalLight new. light3 direction: (120 degreesToRadians cos) * 100 @ -20 @ (120 degreesToRadians sin * 100). light3 lightColor: (B3DMaterialColor color: (Color r: 0.25 g: 0.25 b: 0.8)). scene lights add: light3. light4 := B3DDirectionalLight new. light4 direction: 0 @ -100 @ -10. light4 lightColor: (B3DMaterialColor color: (Color r: 0.3 g: 0.3 b: 0.02)). scene lights add: light4. ! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/26/2007 14:53'! createScene | camera | camera _ B3DCamera new. camera position: 0@0@250. camera target: 0@0@0. camera fov: 2.5. scene _ B3DScene new. scene defaultCamera: camera. self createSolidsForScene: scene; createLightsForScene: scene.! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/26/2007 14:45'! createSolidsForScene: aScene | sceneObj mat arr | arr := Array2D width: 20 height: 20. 1 to: 20 do: [:x | 1 to: 20 do: [:y | arr at: x at: y put: 5].]. arr at: 5 at: 5 put: 7. arr at: 6 at: 6 put: 3. sceneObj _ B3DSceneObject named: 'EarthSwarms Scene'. sceneObj geometry: (self createTrianglesFromArray: arr). mat := B3DMaterial new. mat shininess: 0.9; emission: (Color gray: 0.22); specularPart: (Color gray: 0.8). sceneObj material: mat. aScene objects add: sceneObj.! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/26/2007 14:01'! createSolidsForSceneSave: aScene | sceneObj mat | sceneObj _ B3DSceneObject named: 'EarthSwarms Scene'. sceneObj geometry: (self createTriangleGeometry: [:x :y | (x*x + (y*y)) negated exp * x * 4.0] withDerivatives: [:u1 :v1 | (u1*u1 + (v1*v1)) negated exp * 4.0 - ((u1*u1 + (v1*v1)) negated exp * u1 *u1* 8.0)] and: [:u1 :v1 | ((u1*u1 + (v1*v1)) negated exp * u1 *v1* -8.0)] uFrom: -2.0 to:2.0 vFrom: -2.0 to: 2.5 divisionU: 38 divisionV: 42 coloring: nil ). mat := B3DMaterial new. mat shininess: 0.9; emission: (Color gray: 0.22); specularPart: (Color gray: 0.8). sceneObj material: mat. aScene objects add: sceneObj.! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/25/2007 16:48'! createTriangleGeometry: fn withDerivatives: dufn and: dvfn uFrom: xStart to: xStop vFrom: yStart to: yStop divisionU: nroPx divisionV: nroPy coloring: aBlock " here we create a triangle mesh. The scene is created elsewhere. " | stepPx stepPy x y low high idxF vtx face faces mesh vtxNormals vtxColors fnValue | stepPx := xStop - xStart / (nroPx - 1). stepPy := yStop - yStart / (nroPy - 1). vtx _ WriteStream on: (B3DVector3Array new: nroPx * nroPy). dufn notNil ifTrue: [vtxNormals _ WriteStream on: (B3DVector3Array new: nroPx * nroPy)]. aBlock notNil ifTrue: [vtxColors := WriteStream on: (B3DColor4Array new: nroPx * nroPy)]. x := xStart. y := yStart. " compute the vertices " nroPx timesRepeat: [y := yStart. nroPy timesRepeat: [vtx nextPut: (B3DVector3 x: x y: (fnValue := fn value: x value: y) z: y). dufn notNil ifTrue: [vtxNormals nextPut: (B3DVector3 x: (dufn value: x value: y) y: -1.0 z: (dvfn value: x value: y)) safelyNormalized]. aBlock notNil ifTrue: [vtxColors nextPut: (aBlock value: x - xStart/(xStop - xStart) value: y - yStart/(yStop - yStart) value: fnValue)]. y := y + stepPy. ]. x := x + stepPx. ]. faces := B3DIndexedTriangleArray new: (nroPx - 1)*(nroPy - 1)*2. idxF := low := 1. 1 to: nroPx -1 do: [:i | high := low + nroPy. 1 to: nroPy - 1 do: [:j | face := B3DIndexedTriangle with: low + j - 1 with: low + j with: high + j. faces at: idxF put: face. idxF := idxF + 1. face := B3DIndexedTriangle with: low + j - 1 with: high + j with: high + j - 1. faces at: idxF put: face. idxF := idxF + 1. ]. low := high. ]. mesh := B3DIndexedTriangleMesh new. mesh vertices: vtx contents; faces: faces. dufn notNil ifTrue: [mesh vertexNormals: vtxNormals contents]. aBlock notNil ifTrue: [mesh vertexColors: vtxColors contents]. ^mesh ! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/26/2007 14:13'! createTrianglesFromArray: twoDarray ^self createTrianglesFromArray: twoDarray uFrom: nil to: nil vFrom: nil to: nil. ! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/26/2007 14:56'! createTrianglesFromArray: twoDarray uFrom: xStart to: xStop vFrom: yStart to: yStop " here we create a triangle mesh. The scene is created elsewhere. " | x y low high idxF vtx face faces mesh vtxNormals nroPx nroPy lowX highX lowY highY | lowX := xStart. highX := xStop. lowX ifNil: [lowX := 2.]. highX ifNil: [highX := (twoDarray width) - 1.]. lowY := yStart. highY := yStop. lowY ifNil: [lowY := 2.]. highY ifNil: [highY := (twoDarray height) - 1 .]. nroPx := highX - lowX + 1. nroPy := highY - lowY + 1. vtx := WriteStream on: (B3DVector3Array new: nroPx * nroPy). vtxNormals := WriteStream on: (B3DVector3Array new: nroPx * nroPy). x := lowX. y := lowY. " compute the vertices " nroPx timesRepeat: [y := lowY. nroPy timesRepeat: [vtx nextPut: (B3DVector3 x: (x - lowX - ((highX-lowX)/2.0) ) y: (twoDarray at: x at: y) z: (y - lowY - ((highY-lowY)/2.0))). vtxNormals nextPut: (B3DVector3 x: (self dxArray2D: twoDarray x: x y: y) y: -1.0 z: (self dyArray2D: twoDarray x: x y: y)) safelyNormalized. y := y + 1. ]. x := x + 1. ]. faces := B3DIndexedTriangleArray new: (nroPx - 1)*(nroPy - 1)*2. idxF := low := 1. 1 to: nroPx -1 do: [:i | high := low + nroPy. 1 to: nroPy - 1 do: [:j | face := B3DIndexedTriangle with: low + j - 1 with: low + j with: high + j. faces at: idxF put: face. idxF := idxF + 1. face := B3DIndexedTriangle with: low + j - 1 with: high + j with: high + j - 1. faces at: idxF put: face. idxF := idxF + 1. ]. low := high. ]. mesh := B3DIndexedTriangleMesh new. mesh vertices: vtx contents; faces: faces. mesh vertexNormals: vtxNormals contents. ^mesh ! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/25/2007 16:45'! descriptionScene ^'First try. Second Paragraph.'! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/26/2007 13:57'! dxArray2D: arr x: x y: y "Return the X derivitive of arr at x,y" | d1 d2 | d1 := (arr at: x at: y) - (arr at: (x - 1) at: y). d2 := (arr at: (x + 1) at: y) - (arr at: x at: y). ^(d2 + d1)/2.0! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/26/2007 13:57'! dyArray2D: arr x: x y: y "Return the Y derivitive of arr at x,y" | d1 d2 | d1 := (arr at: x at: y) - (arr at: x at: (y - 1)). d2 := (arr at: x at: (y + 1)) - (arr at: x at: y). ^(d2 + d1)/2.0! ! !EarthSwarms class methodsFor: 'toplevel' stamp: 'BEO 2/25/2007 16:32'! main " EarthSwarms main." EarthSwarms new main. ! ! !EarthSwarms class methodsFor: 'cleanup' stamp: 'BEO 2/19/2007 11:51'! cleanUpProjects "Cleanup extra projects. This doesn't belong here but it's convient" Project allSubInstancesDo: [:p | (p == Project current) ifFalse: [Project deletingProject: p]. ]. ! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:16'! addFrameAndExplanationField | topView | topView := SystemWindow labelled: 'EarthSwarms'. topView addMorph: self fullFrame: (LayoutFrame fractions: (0 @ 0 corner: 1.0 @ 0.8)). topView addMorph: (PluggableTextMorph on: self text: #contents accept: #acceptContents: readSelection: nil menu: #codePaneMenu:shifted:) frame: (0@0.8 corner: 1@1). ^topView! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 16:59'! clearColor: aColor " set the background color of the B3DSceneMorph " b3DSceneMorph color: aColor! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:00'! closeEnabled ^true! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:00'! codePaneMenu: aMenu shifted: shifted "Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items in a text pane" | donorMenu | donorMenu _ shifted ifTrue: [ParagraphEditor shiftedYellowButtonMenu] ifFalse: [ParagraphEditor yellowButtonMenu]. ^ aMenu labels: donorMenu labelString lines: donorMenu lineArray selections: donorMenu selections! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:00'! contents ^source perform: textAccessor! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:00'! scene ^b3DSceneMorph scene! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:00'! scene: aScene b3DSceneMorph scene: aScene.! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:00'! source: anInstance description: aSymbol source := anInstance. textAccessor := aSymbol.! ! !EarthSwarmsPresenterMorph methodsFor: 'actions' stamp: 'BEO 2/25/2007 16:54'! acceptContents: xx ^true! ! !EarthSwarmsPresenterMorph methodsFor: 'actions' stamp: 'BEO 2/25/2007 16:55'! closeMorph self delete! ! !EarthSwarmsPresenterMorph methodsFor: 'actions' stamp: 'BEO 2/25/2007 16:55'! switchRotationStatus b3DSceneMorph switchRotationStatus! ! !EarthSwarmsPresenterMorph methodsFor: 'change reporting' stamp: 'BEO 2/25/2007 17:03'! layoutChanged | ctrl | super layoutChanged. b3DSceneMorph ifNil: [^self]. b3DSceneMorph extent: (self extent - ((frameWidth * 2)@(frameWidth * 2))). b3DSceneMorph position: (self bounds origin + ((frameWidth)@(frameWidth))). wheels ifNil: [^self]. wheels isEmpty ifTrue: [^self]. ctrl := wheels at: #fov ifAbsent: [nil]. ctrl ifNotNil: [ ctrl position: self bounds corner - ctrl extent - (frameWidth@((frameWidth - ctrl extent y) / 2) rounded)]. ctrl := wheels at: #dolly ifAbsent: [nil]. ctrl ifNotNil: [ ctrl position: self bounds corner - ctrl extent - ((((frameWidth - ctrl extent x) / 2) rounded)@frameWidth)]. ctrl := wheels at: #rotX ifAbsent: [nil]. ctrl ifNotNil: [ ctrl position: (self bounds origin x + (((frameWidth - ctrl extent x) / 2) rounded))@(self bounds corner y - ctrl extent y - frameWidth)]. ctrl := wheels at: #rotY ifAbsent: [nil]. ctrl ifNotNil: [ ctrl position: (self bounds origin x + frameWidth)@(self bounds corner y - ctrl extent y - (((frameWidth - ctrl extent y) / 2) rounded))]. ctrl := wheels at: #rotZ ifAbsent: [nil]. ctrl ifNotNil: [ ctrl position: self bounds origin + ((((frameWidth - ctrl extent x) / 2) rounded)@frameWidth)]. ctrl := wheels at: #accel ifAbsent:[nil]. ctrl ifNotNil:[ ctrl position: self bounds origin + (frameWidth @ ((((frameWidth - ctrl extent y) / 2) rounded)))]. ctrl := wheels at: #accel ifAbsent:[nil]. ctrl ifNotNil:[ ctrl position: self bounds origin + (frameWidth @ ((((frameWidth - ctrl extent y) / 2) rounded)))]. ! ! !EarthSwarmsPresenterMorph methodsFor: 'drawing' stamp: 'BEO 2/25/2007 17:02'! drawOn: aCanvas "Don't fill if my b3dScene does it" (b3DSceneMorph notNil and:[b3DSceneMorph color isOpaque]) ifTrue:[ (aCanvas clipRect areasOutside: b3DSceneMorph bounds) do:[:r| aCanvas clipBy: r during:[:cc| super drawOn: cc]. ]. ] ifFalse: [super drawOn: aCanvas].! ! !EarthSwarmsPresenterMorph methodsFor: 'event handling' stamp: 'BEO 2/25/2007 17:02'! handlesMouseDown: evt ^evt yellowButtonPressed ! ! !EarthSwarmsPresenterMorph methodsFor: 'event handling' stamp: 'BEO 2/25/2007 17:03'! mouseDown: evt evt yellowButtonPressed ifTrue: [ self yellowButtonMenu. ^super mouseDown: evt].! ! !EarthSwarmsPresenterMorph methodsFor: 'hardware acceleration' stamp: 'BEO 2/25/2007 17:04'! accelerationEnabled ^b3DSceneMorph ifNil:[false] ifNotNil:[b3DSceneMorph accelerationEnabled].! ! !EarthSwarmsPresenterMorph methodsFor: 'hardware acceleration' stamp: 'BEO 2/25/2007 17:04'! accelerationEnabled: aBool ^b3DSceneMorph ifNotNil:[b3DSceneMorph accelerationEnabled: aBool].! ! !EarthSwarmsPresenterMorph methodsFor: 'hardware acceleration' stamp: 'BEO 2/25/2007 17:05'! toggleAcceleration self accelerationEnabled: self accelerationEnabled not.! ! !EarthSwarmsPresenterMorph methodsFor: 'initialization' stamp: 'BEO 2/25/2007 17:01'! closeButton | outerButton aButton str miniWrapper aHelp | outerButton _ AlignmentMorph newRow height: 24. outerButton beTransparent. outerButton hResizing: #spaceFill; vResizing: #shrinkWrap. outerButton addMorph: (aButton _ UpdatingThreePhaseButtonMorph checkBox). aButton target: self; actionSelector: #toggleAcceleration; arguments: #(); getSelector: #accelerationEnabled. outerButton addTransparentSpacerOfSize: (2 @ 0). str _ StringMorph contents: 'hardware acceleration' font: nil. "(StrikeFont familyName: 'NewYork' size: 12)." miniWrapper _ AlignmentMorph newRow hResizing: #shrinkWrap; vResizing: #shrinkWrap. miniWrapper beTransparent addMorphBack: str lock. outerButton addMorphBack: miniWrapper. aButton setBalloonText: (aHelp _ 'Turn on hardware acceleration if supported'). miniWrapper setBalloonText: aHelp; setProperty: #balloonTarget toValue: aButton. ^outerButton! ! !EarthSwarmsPresenterMorph methodsFor: 'menus' stamp: 'BEO 2/25/2007 17:37'! addCustomMenuItems: aCustomMenu (aCustomMenu isKindOf: MenuMorph) ifTrue: [aCustomMenu addUpdating: #rotationString action: #switchRotationStatus] ifFalse: [aCustomMenu add: 'switch rotation status' action: #switchRotationStatus]. ! ! !EarthSwarmsPresenterMorph methodsFor: 'menus' stamp: 'BEO 2/25/2007 16:56'! addCustomMenuItems: aCustomMenu hand: aHandMorph super addCustomMenuItems: aCustomMenu hand: aHandMorph. aCustomMenu addLine. self addCustomMenuItems: aCustomMenu. ! ! !EarthSwarmsPresenterMorph methodsFor: 'menus' stamp: 'BEO 2/25/2007 16:56'! initialize | ctrl | super initialize. color := Color gray: 0.8. frameWidth := 25. b3DSceneMorph := AdvancedB3DScenePresenterMorph new. b3DSceneMorph color: Color white; borderStyle: (BorderStyle width: 1 color: Color black). self addMorphFront: b3DSceneMorph. wheels := Dictionary new. ctrl := WheelMorph new. ctrl target: b3DSceneMorph. ctrl actionSelector: #addFovAngle:. ctrl factor: -0.07. ctrl setBalloonText: 'FOV'. self addMorphFront: ctrl. wheels at: #fov put: ctrl. ctrl := WheelMorph new. ctrl target: b3DSceneMorph. ctrl actionSelector: #addDolly:. ctrl factor: 0.005. ctrl beVertical. ctrl setBalloonText: 'Dolly'. self addMorphFront: ctrl. wheels at: #dolly put: ctrl. ctrl := WheelMorph new. ctrl target: b3DSceneMorph. ctrl actionSelector: #rotateZ:. ctrl beVertical. ctrl setBalloonText: 'z Axis'. self addMorphFront: ctrl. wheels at: #rotZ put: ctrl. ctrl := WheelMorph new. ctrl target: b3DSceneMorph. ctrl actionSelector: #rotateY:. ctrl setBalloonText: 'y Axis'. self addMorphFront: ctrl. wheels at: #rotY put: ctrl. ctrl := WheelMorph new. ctrl target: b3DSceneMorph. ctrl actionSelector: #rotateX:. ctrl beVertical. ctrl setBalloonText: 'x Axis'. self addMorphFront: ctrl. wheels at: #rotX put: ctrl. ctrl _ self closeButton. self addMorphFront: ctrl. wheels at: #accel put: ctrl. ! ! !EarthSwarmsPresenterMorph methodsFor: 'menus' stamp: 'BEO 2/25/2007 16:57'! rotationString ^b3DSceneMorph isRotating ifTrue: ['stop rotating'] ifFalse: ['start rotating']! ! !EarthSwarmsPresenterMorph methodsFor: 'menus' stamp: 'BEO 2/25/2007 16:57'! yellowButtonMenu | menu sel | menu _ CustomMenu new. menu title: self class name. self addCustomMenuItems: menu. sel := menu startUp. sel ifNotNil: [self perform: sel]! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:57'! addDolly: a b3DSceneMorph addDolly: a! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:57'! beRotating b3DSceneMorph beRotating! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:58'! defaultColor ^Color gray! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:58'! panBy: a b3DSceneMorph panBy: a! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:58'! rotateX: a b3DSceneMorph rotateX: a! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:58'! rotateY: a b3DSceneMorph rotateY: a! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:58'! rotateZ: a b3DSceneMorph rotateZ: a! ! !EarthSwarmsPresenterMorph class methodsFor: 'initialization' stamp: 'BEO 2/25/2007 16:53'! descriptionForPartsBin ^ self partName: 'EarthSwarms' categories: #('3-D') documentation: '3D Earth Data Display'! ! !EarthSwarmsPresenterMorph class reorganize! ('initialization' descriptionForPartsBin) ! EarthSwarmsPresenterMorph removeSelector: #openInSystemWindow! !EarthSwarmsPresenterMorph reorganize! ('accessing' addFrameAndExplanationField clearColor: closeEnabled codePaneMenu:shifted: contents scene scene: source:description:) ('actions' acceptContents: closeMorph switchRotationStatus) ('change reporting' layoutChanged) ('drawing' drawOn:) ('event handling' handlesMouseDown: mouseDown:) ('hardware acceleration' accelerationEnabled accelerationEnabled: toggleAcceleration) ('initialization' closeButton) ('menus' addCustomMenuItems: addCustomMenuItems:hand: initialize rotationString yellowButtonMenu) ('visual properties' addDolly: beRotating defaultColor panBy: rotateX: rotateY: rotateZ:) ! !EarthSwarms class reorganize! ('toplevel' main) ('cleanup' cleanUpProjects) ! EarthSwarms removeSelector: #createGeometry:uFrom:to:vFrom:to:divisionU:divisionV:coloring:! EarthSwarms removeSelector: #createLightsForScene8:! EarthSwarms removeSelector: #createSolidsForScene8:! EarthSwarms removeSelector: #createTriangleGeometryAndTexture:! !EarthSwarms reorganize! ('toplevel' main show) ('support routines' createLightsForScene: createScene createSolidsForScene: createSolidsForSceneSave: createTriangleGeometry:withDerivatives:and:uFrom:to:vFrom:to:divisionU:divisionV:coloring: createTrianglesFromArray: createTrianglesFromArray:uFrom:to:vFrom:to: descriptionScene dxArray2D:x:y: dyArray2D:x:y:) !