Summary: |
Example: Scene Animation | |
![]() | |
{import * from CURL.GRAPHICS.SCENE} {import * from CURL.PGUIDE.SCENEUTILS, location = "../../default/support/SceneUtils.scurl"} {value let scene:ExampleScene = {ExampleScene} {scene.camera-setup} let scene-graphic:SceneGraphic = {SceneGraphic scene, width=4in, height=4in, background = {FillPattern.get-black} } let quad:Quad = {Quad 0in, 0in, z = 1ft, 4ft, 4ft } {scene.add-object quad} let tri:Triangle = {Triangle {Distance3d -1ft, 0ft, 1ft}, {Distance3d -1ft, -5ft, 1ft}, {Distance3d -1ft, 0ft, 4ft} } {scene.add-object tri} {scene.add-object {make-axis-object 1m}} let tmr:Timer= {scene-graphic.animate interval=.05s, repeat = 0, {on TimerEvent do {tri.rotate {Fraction3d 0, 0, 1}, -5deg} {scene-graphic.update-drawable} } } let run-stop-button:CommandButton = {CommandButton label = "Start", {on Action at b:CommandButton do {if tmr.repeat == 0 then set tmr.repeat = -1 set b.label = "Stop" else set tmr.repeat = 0 set b.label = "Start" } } } let reset-camera:CommandButton = {CommandButton label = "Reset Camera", {on Action at b:CommandButton do {scene.camera-setup} {scene-graphic.update-drawable} } } {VBox scene-graphic, {HBox run-stop-button, reset-camera } } } |
Example: Triangle and Quad Interaction | |
![]() | |
{import * from CURL.GRAPHICS.SCENE} {import * from CURL.PGUIDE.SCENEUTILS, location = "../../default/support/SceneUtils.scurl"} {define-class public TriangleCollisionSceneEvent {inherits BoxIntersectionSceneEvent} {constructor public {default ...} {construct-super intersection-style = IntersectionStyle.contained, predicate = Predicate.all, sort-order = SortOrder.none, ... } } } {value let scene:ExampleScene = {ExampleScene} {scene.camera-setup} let scene-graphic:SceneGraphic = {SceneGraphic scene, width=4in, height=4in, background = {FillPattern.get-black} } let eh-collision:EventHandler = {on e:TriangleCollisionSceneEvent at q:Quad do set q.fill-pattern = {FillPattern.get-yellow} } let quad:Quad = {Quad 0in, 0in, z = 1ft, 4ft, 4ft, fill-pattern = {FillPattern.get-gray}, eh-collision } {scene.add-object quad} let tri:Triangle = {Triangle {Distance3d -1ft, 0ft, 1ft}, {Distance3d -1ft, -5ft, 1ft}, {Distance3d -1ft, 0ft, 4ft} } {scene.add-object tri} {scene.add-object {make-axis-object 1m}} let tmr:Timer= {scene-graphic.animate interval=.05s, repeat = 0, {on TimerEvent do {tri.rotate {Fraction3d 0, 0, 1}, -5deg} let a:Distance3d let b:Distance3d set (a, b) = {tri.get-parent-bounding-box} let tce:TriangleCollisionSceneEvent = {TriangleCollisionSceneEvent a, b} set quad.fill-pattern = {FillPattern.get-gray} {scene.handle-event tce} {scene-graphic.update-drawable} } } let run-stop-button:CommandButton = {CommandButton label = "Start", {on Action at b:CommandButton do {if tmr.repeat == 0 then set tmr.repeat = -1 set b.label = "Stop" else set tmr.repeat = 0 set b.label = "Start" } } } let reset-camera:CommandButton = {CommandButton label = "Reset Camera", {on Action at b:CommandButton do {scene.camera-setup} {scene-graphic.update-drawable} } } {VBox scene-graphic, {HBox run-stop-button, reset-camera } } } |
Example: Using sort-order and predicate | |
![]() | |
{import * from CURL.GRAPHICS.SCENE} {import * from CURL.PGUIDE.SCENEUTILS, location = "../../default/support/SceneUtils.scurl"} {define-class RayEvent {inherits RayIntersectionSceneEvent} {constructor {default ...} {construct-super ... }}} {value let scene:ExampleScene = {ExampleScene} set scene.camera-position = {Distance3d 0ft, -2ft, 3ft} {scene.camera-setup} let scene-graphic:SceneGraphic = {SceneGraphic scene, width=4in, height=4in, background = {FillPattern.get-black} } let event-handler:EventHandler = {on event:PointerPressSceneEvent at tri:Triangle do set tri.fill-pattern = {Color.from-rgb 1, 1, 1} let intersection-point:Distance3d = ((event.intersection asa PointIntersection).intersection-point + {Distance3d .5in, 0in, 0in}) let mpi:MultiPointIntersection = {scene.get-intersections {RayEvent intersection-point, {Direction3d 1, 0, 0}, predicate = Predicate.all, || predicate = Predicate.first, || sort-order = SortOrder.none || sort-order = SortOrder.backward sort-order = SortOrder.forward } } let clr-fract:Fraction = 0.0 {for p:PointIntersection in mpi.intersections do {if p.object isa Triangle and p.object != tri then set clr-fract = clr-fract + .1 set (p.object asa Triangle).fill-pattern = {Color.from-rgb clr-fract, clr-fract, clr-fract} } } } {for x:Distance = -2.5ft to 2.5ft step 1ft do let vertex:Distance3d = {Distance3d x, 0in, 0in} {scene.add-object {Triangle vertex, vertex + {Distance3d .5ft, 0in, .2ft}, vertex + {Distance3d 0in, .5ft, .2ft}, event-handler } } } {scene.add-object {make-axis-object 1m}} let reset-colors:CommandButton = {CommandButton label = "Reset Colors", {on Action at b:CommandButton do let mpi1:MultiPointIntersection = {scene.get-intersections {RayEvent {Distance3d -3ft, .1ft, .1ft}, {Direction3d 1, 0, 0}, predicate = Predicate.all, sort-order = SortOrder.forward } } {for p:PointIntersection in mpi1.intersections do {if p.object isa Triangle then set (p.object asa Triangle).fill-pattern = {FillPattern.get-magenta} } } {scene-graphic.update-drawable} } } let reset-camera:CommandButton = {CommandButton label = "Reset Camera", {on Action at b:CommandButton do {scene.camera-setup} {scene-graphic.update-drawable} } } {VBox scene-graphic, {HBox reset-camera, reset-colors } } } |
Example: Intersection Style | |
![]() | |
{import * from CURL.GRAPHICS.SCENE} {import * from CURL.PGUIDE.SCENEUTILS, location = "../../default/support/SceneUtils.scurl"} {define-class public BoundarySceneGraphic {inherits SceneGraphic} field public circle:Circle field public intersection-style:IntersectionStyle = IntersectionStyle.contained {constructor public {default scene:Scene, circle:Circle, ...} {construct-super scene, ... } set self.circle = circle } {method public {handle-motion button-pressed:int, dx:Distance, dy:Distance}:void {if button-pressed == 1 then let (sx:double, sy:double, sz:double) = {self.circle.transformation.to-world-scale} let s:double = 20 / {max sx, sy, sz} {self.circle.translate dx*s, -dy*s, 0m} elseif button-pressed == 3 then let s:float = (1 + dx/1in) asa float {self.circle.scale s, s, s} } {for obj:SceneObject in self.scene.objects do {if (obj isa Quad) then set (obj asa Quad).fill-pattern = {FillPattern.get-silver} } } {self.scene.handle-event {BoundarySceneEvent {self.circle.transformed-center}, {self.circle.transformed-radius}, self.intersection-style} } {self.update-drawable} } {method public {reset-quads}:void {for obj:SceneObject in self.scene.objects do {if (obj isa Quad) then set (obj asa Quad).fill-pattern = {FillPattern.get-silver} } } {self.update-drawable} } } {define-proc {make-command-button label:String, bsg:BoundarySceneGraphic, intstyle:IntersectionStyle, circle:Circle, scene:Scene}:CommandButton let button:CommandButton = {CommandButton label=label, width = 1in, {on Action do {bsg.reset-quads} set bsg.intersection-style = intstyle {scene.handle-event {BoundarySceneEvent {circle.transformed-center}, {circle.transformed-radius}, intstyle} } } } {return button} } {define-class public BoundarySceneEvent {inherits SphereIntersectionSceneEvent} {constructor public {default center:Distance3d, radius:Distance, intersection-style:IntersectionStyle, ...} {construct-super center, radius, intersection-style = intersection-style, predicate = Predicate.all, sort-order = SortOrder.none, ... } } } {define-class public Circle {inherits SceneObject} field public center:Distance3d = {Distance3d 0m, 0m, 0m} field public radius:Distance field public color:Color = {Palette.get-cyan} {method public {paint renderer:Renderer3d, viewport-width:Distance, viewport-height:Distance}:void let center:Distance3d = self.center let radius:Distance = self.radius {renderer.render-elliptic-path center.x - radius, center.y - radius, 0m, radius * 2, radius * 2, texture=self.color, line-width = 1.5pt} } {method public {get-local-bounding-box check-visibility?:bool = false }:(min-xyz:Distance3d, max-xyz:Distance3d, valid-bounds?:bool) let center:Distance3d = self.center let radius:Distance = self.radius let a:Distance3d = {Distance3d center.x - radius, center.y - radius, 0m} let b:Distance3d = {Distance3d center.x + radius, center.y + radius, 0m} {return a, b, not check-visibility? or self.bounding-box-or-object-visible?} } {constructor public {default center:Distance3d, radius:Distance, ...} {construct-super ... } set self.center = center set self.radius = radius } {method public {transformed-center}:Distance3d {return {self.world-transformation.point-to-world self.center}} } {method public {transformed-radius}:Distance let (sx:double, sy:double, sz:double) = {self.world-transformation.to-world-scale} {return self.radius * {max sx, sy, sz}} } } {value let scene:ExampleScene = {ExampleScene} set scene.camera-position = {Distance3d 0in, -3ft, 5ft} {scene.camera-setup} let circle:Circle = {Circle {Distance3d 0m, 0m, 0m}, 3.1ft } {scene.add-object circle} let bsg:BoundarySceneGraphic = {BoundarySceneGraphic scene, circle, width=4in, height=4in, background = {FillPattern.get-black} } let eh:EventHandler = {on e:BoundarySceneEvent at obj:Quad do set obj.fill-pattern = {FillPattern.get-yellow} {bsg.update-drawable} } let quad:#Quad {for x:Distance = -5ft to 5ft step 1ft do {for y:Distance = -5ft to 5ft step 1ft do set quad = {Quad 0ft, 0ft, 6in, 6in, fill-pattern = {FillPattern.get-silver}, eh } {quad.translate x, y, 0m} {scene.add-object {non-null quad}} } } {VBox bsg, {HBox {make-command-button "always", bsg, IntersectionStyle.always, circle, scene}, {make-command-button "entirely-contained", bsg, IntersectionStyle.entirely-contained, circle, scene}, {make-command-button "contained", bsg, IntersectionStyle.contained, circle, scene}, {make-command-button "not-on-border", bsg, IntersectionStyle.not-on-border, circle, scene} }, {HBox {make-command-button "never", bsg, IntersectionStyle.never, circle, scene}, {make-command-button "outside", bsg, IntersectionStyle.outside, circle, scene}, {make-command-button "entirely-outside", bsg, IntersectionStyle.entirely-outside, circle, scene}, {make-command-button "only-on-border", bsg, IntersectionStyle.only-on-border, circle, scene} }}} |
get in the wayof another object receiving intersection events. Set this property to false to enable events to pass through the object to intersect other objects.
Example: Using opaque-to-intersection? | |
![]() | |
{import * from CURL.GRAPHICS.SCENE} {import * from CURL.PGUIDE.SCENEUTILS, location = "../../default/support/SceneUtils.scurl"} {paragraph Click on the triangle to rotate clockwise} {paragraph Click on the rectangle to rotate counter clockwise} {value let scene:ExampleScene = {ExampleScene} {scene.camera-setup} let scene-graphic:SceneGraphic = {SceneGraphic scene, width=4in, height=4in, background = {FillPattern.get-black} } let quad:Quad = {Quad 0in, 0in, z = 1ft, 4ft, 4ft, {on PointerPressSceneEvent at obj:Quad do {obj.parent.rotate {Fraction3d 0, 0, 1}, 10deg} } } let cover-quad:Quad = {Quad 0in, 0in, z = 1.1ft, 3ft, 2ft, fill-pattern = {FillPattern.get-blue} } || Comment following line to start blocking intersection events set cover-quad.opaque-to-intersection? = false let tri:Triangle = {Triangle {Distance3d -1ft, 0ft, 1ft}, {Distance3d -1ft, -5ft, 1ft}, {Distance3d -1ft, 0ft, 4ft}, {on PointerPressSceneEvent at obj:Triangle do {obj.parent.rotate {Fraction3d 0, 0, 1}, -10deg} } } {scene.add-object {SceneGroup quad, tri}} {scene.add-object cover-quad} {scene.add-object {make-axis-object 1m}} let reset-camera:CommandButton = {CommandButton label = "Reset Camera", {on Action at b:CommandButton do {scene.camera-setup} {scene-graphic.update-drawable} } } {VBox scene-graphic, reset-camera } } |
Example: Using pointer events in a scene | |
![]() | |
{import * from CURL.GRAPHICS.SCENE} {import * from CURL.PGUIDE.SCENEUTILS, location = "../../default/support/SceneUtils.scurl"} {value let scene:ExampleScene = {ExampleScene} {scene.camera-setup} let scene-graphic:SceneGraphic = {SceneGraphic scene, width=4in, height=4in, background = {FillPattern.get-black} } let quad:Quad = {Quad 0in, 0in, z = 1ft, 4ft, 4ft, {on e:PointerPressSceneEvent at obj:Quad do {if e.state-mask.shift? then {if e.button == left-button then set obj.fill-pattern = {FillPattern.get-red} } {if e.button == middle-button then set obj.fill-pattern = {FillPattern.get-orange} } {if e.button == right-button then set obj.fill-pattern = {FillPattern.get-yellow} } else {if e.button == left-button then {obj.rotate {Fraction3d 0, 0, 1}, 10deg} } {if e.button == middle-button then {obj.rotate {Fraction3d 0, 1, 0}, 10deg} } {if e.button == right-button then {obj.rotate {Fraction3d 1, 0, 0}, 10deg} } } } } {scene.add-object quad} {scene.add-object {make-axis-object 1m}} let reset-camera:CommandButton = {CommandButton label = "Reset Camera", {on Action at b:CommandButton do {scene.camera-setup} {scene-graphic.update-drawable} } } {VBox {text font-weight="bold", Click on the Quad!}, {text Left mouse: rotation around z axis}, {text Middle mouse: rotation around y axis}, {text Right mouse: rotation around x axis}, {text Shift-Left mouse: red}, {text Shift-Middle mouse: orange}, {text Shift-Right mouse: yellow}, scene-graphic, reset-camera } } |