Skip to content

Commit feb926b

Browse files
committed
Fix various issues with Global-/LocalBoundingBox
This commit fixes various issues with the computation of bounding boxes: - Both attributes ignored the transform for Sg.RenderObjectNode (Sg.renderObjectSet) - Neither attribute supported Sg.RuntimeCommandNode (Sg.execute) - LocalBoundingBox was computed by using the local positions and subsequently transforming the resulting bounding box. This commit makes LocalBoundingBox truly identical to GlobalBoundingBox. - Retrieval of positions and indices was limited (ArrayBuffer only, type restrictions)
1 parent 5d1b664 commit feb926b

6 files changed

Lines changed: 516 additions & 291 deletions

File tree

RELEASE_NOTES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
- Fixed support for 64-bit attributes and uniforms
2+
- Fixed various issues with `GlobalBoundingBox` and `LocalBoundingBox`. Both attributes are now equivalent.
23
- Made `IBuffer.ToArray` and `BufferView.download` robust to out-of-range arguments
34
- [Sg] Fixed broken Ag rule for `FaceVertexCount`
45
- [Sg] Added `rotation` and `rotation'`

src/Aardvark.SceneGraph/HighLevelSceneGraph/Commands.fs

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -140,56 +140,82 @@ open Aardvark.SceneGraph
140140
[<AutoOpen>]
141141
module RuntimeCommandSemantics =
142142

143-
module private RuntimeCommand =
144-
let rec ofRenderCommand (scope : Ag.Scope) (parent : ISg) (cmd : RenderCommand) =
143+
module private RenderCommand =
144+
let rec toRuntimeCommand (scope : Ag.Scope) (cmd : RenderCommand) =
145145
match cmd with
146-
| RenderCommand.REmpty ->
147-
RuntimeCommand.Empty
146+
| RenderCommand.REmpty ->
147+
RuntimeCommand.Empty
148148

149-
| RenderCommand.RUnorderedScenes scenes ->
150-
let objects = scenes |> ASet.collect (fun s -> s.RenderObjects(scope))
151-
RuntimeCommand.Render(objects)
149+
| RenderCommand.RUnorderedScenes scenes ->
150+
let objects = scenes |> ASet.collect _.RenderObjects(scope)
151+
RuntimeCommand.Render(objects)
152152

153-
| RenderCommand.RClear values ->
154-
RuntimeCommand.Clear(values)
153+
| RenderCommand.RClear values ->
154+
RuntimeCommand.Clear(values)
155155

156-
| RenderCommand.RGeometries(config, geometries) ->
157-
let effect =
158-
match scope.Surface with
159-
| Surface.Effect e -> e
160-
| s -> failwithf "[Sg] cannot create GeometryCommand with shader: %A" s
156+
| RenderCommand.RGeometries(config, geometries) ->
157+
let effect =
158+
match scope.Surface with
159+
| Surface.Effect e -> e
160+
| s -> failwithf "[Sg] cannot create GeometryCommand with shader: %A" s
161161

162-
let state =
163-
{ PipelineState.ofScope scope with
164-
Mode = config.mode
165-
VertexInputTypes = config.vertexInputTypes
166-
PerGeometryUniforms = config.perGeometryUniforms }
162+
let state =
163+
{ PipelineState.ofScope scope with
164+
Mode = config.mode
165+
VertexInputTypes = config.vertexInputTypes
166+
PerGeometryUniforms = config.perGeometryUniforms }
167167

168-
RuntimeCommand.Geometries(effect, state, geometries)
168+
RuntimeCommand.Geometries(effect, state, geometries)
169169

170-
| RenderCommand.ROrdered(list) ->
171-
let commands = list |> AList.map (ofRenderCommand scope parent)
172-
RuntimeCommand.Ordered(commands)
170+
| RenderCommand.ROrdered(list) ->
171+
let commands = list |> AList.map (toRuntimeCommand scope)
172+
RuntimeCommand.Ordered(commands)
173173

174-
| RenderCommand.RIfThenElse(c,t,f) ->
175-
RuntimeCommand.IfThenElse(c, ofRenderCommand scope parent t, ofRenderCommand scope parent f)
174+
| RenderCommand.RIfThenElse(c, t, f) ->
175+
RuntimeCommand.IfThenElse(c, toRuntimeCommand scope t, toRuntimeCommand scope f)
176176

177-
| RenderCommand.RLodTree(config,g) ->
178-
let state =
179-
{ PipelineState.ofScope scope with
180-
Mode = config.mode
181-
VertexInputTypes = config.vertexInputTypes
182-
PerGeometryUniforms = config.perGeometryUniforms }
177+
| RenderCommand.RLodTree(config, g) ->
178+
let state =
179+
{ PipelineState.ofScope scope with
180+
Mode = config.mode
181+
VertexInputTypes = config.vertexInputTypes
182+
PerGeometryUniforms = config.perGeometryUniforms }
183183

184-
RuntimeCommand.LodTree(scope.Surface, state, g)
184+
RuntimeCommand.LodTree(scope.Surface, state, g)
185+
186+
let rec getBoundingBox (scope : Ag.Scope) (cmd : RenderCommand) =
187+
match cmd with
188+
| RenderCommand.REmpty ->
189+
Box3d.invalid
190+
191+
| RenderCommand.RClear _ ->
192+
Box3d.invalid
193+
194+
| RenderCommand.RIfThenElse (c, t, f) ->
195+
let t = getBoundingBox scope t
196+
let f = getBoundingBox scope f
197+
c |> AVal.bind (fun c -> if c then t else f)
198+
199+
| RenderCommand.ROrdered commands ->
200+
commands |> AList.mapA (getBoundingBox scope) |> Box3d.ofAList
201+
202+
| RenderCommand.RUnorderedScenes objects ->
203+
objects |> ASet.mapA _.GlobalBoundingBox(scope) |> Box3d.ofASet
204+
205+
| RenderCommand.RLodTree _
206+
| RenderCommand.RGeometries _ ->
207+
Log.warn "[Sg] Bounding box computation for %A not implemented" cmd
208+
Box3d.invalid
185209

186210
[<Rule>]
187211
type RuntimeCommandSem() =
188212
member x.RenderObjects(n : Sg.RuntimeCommandNode, scope : Ag.Scope) : aset<IRenderObject> =
189-
let cmd = n.Command
190-
let runtimeCommand = RuntimeCommand.ofRenderCommand scope n cmd
213+
let runtimeCommand = n.Command |> RenderCommand.toRuntimeCommand scope
214+
let obj = CommandRenderObject(scope.RenderPass, scope, runtimeCommand)
215+
ASet.single (obj :> IRenderObject)
191216

192-
let pass = scope.RenderPass
217+
member _.GlobalBoundingBox(n : Sg.RuntimeCommandNode, scope : Ag.Scope) : aval<Box3d> =
218+
n.Command |> RenderCommand.getBoundingBox scope
193219

194-
let obj = CommandRenderObject(pass, scope, runtimeCommand)
195-
ASet.single (obj :> IRenderObject)
220+
member this.LocalBoundingBox(n : Sg.RuntimeCommandNode, scope: Ag.Scope) : aval<Box3d> =
221+
this.GlobalBoundingBox(n, scope)

0 commit comments

Comments
 (0)