Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplemented lod-metric #483

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Build.fs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@
res
*)

let aardiumVersion = "2.0.5"
let aardiumVersion = "2.1.1"
//let versions = getInstalledPackageVersions()
//match Map.tryFind "Aardium" versions with
//| Some v -> v
Expand All @@ -248,7 +248,7 @@
let url = sprintf "https://www.nuget.org/api/v2/package/Aardium-Win32-x64/%s" aardiumVersion
printf "url: %s" url
let tempFile = Path.GetTempFileName()
use c = new System.Net.WebClient()

Check warning on line 251 in Build.fs

View workflow job for this annotation

GitHub Actions / build

This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.

Check warning on line 251 in Build.fs

View workflow job for this annotation

GitHub Actions / build

This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.

Check warning on line 251 in Build.fs

View workflow job for this annotation

GitHub Actions / build

This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.

Check warning on line 251 in Build.fs

View workflow job for this annotation

GitHub Actions / build

This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.

Check warning on line 251 in Build.fs

View workflow job for this annotation

GitHub Actions / build

This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.

Check warning on line 251 in Build.fs

View workflow job for this annotation

GitHub Actions / build

This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.
c.DownloadFile(url, tempFile)
use a = new ZipArchive(File.OpenRead tempFile)
let t = Path.GetTempPath()
Expand Down Expand Up @@ -433,7 +433,7 @@
}
)

// snapshots
//// snapshots
"src/PRo3D.Snapshots/PRo3D.Snapshots.fsproj" |> DotNet.publish (fun o ->
{ o with
Framework = Some "net6.0"
Expand Down Expand Up @@ -486,7 +486,7 @@
let url = sprintf "https://www.nuget.org/api/v2/package/Aardium-Win32-x64/%s" aardiumVersion
printf "url: %s" url
let tempFile = Path.GetTempFileName()
use c = new System.Net.WebClient()

Check warning on line 489 in Build.fs

View workflow job for this annotation

GitHub Actions / build

This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.

Check warning on line 489 in Build.fs

View workflow job for this annotation

GitHub Actions / build

This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.

Check warning on line 489 in Build.fs

View workflow job for this annotation

GitHub Actions / build

This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.

Check warning on line 489 in Build.fs

View workflow job for this annotation

GitHub Actions / build

This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.

Check warning on line 489 in Build.fs

View workflow job for this annotation

GitHub Actions / build

This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.

Check warning on line 489 in Build.fs

View workflow job for this annotation

GitHub Actions / build

This construct is deprecated. WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.
c.DownloadFile(url, tempFile)
use a = new ZipArchive(File.OpenRead tempFile)
let t = Path.GetTempPath()
Expand All @@ -496,7 +496,7 @@
Shell.copyDir (Path.Combine(target, "mac-x64", "tools")) (Path.Combine(tempPath, "tools")) (fun _ -> true)
Shell.copyDir (Path.Combine(target, "win-x64", "tools")) (Path.Combine(tempPath, "tools")) (fun _ -> true)

File.Move("bin/publish/win-x64/PRo3D.Viewer.exe", sprintf "bin/publish/win-x64/PRo3D.Viewer.%s.exe" notes.NugetVersion)
//File.Move("bin/publish/win-x64/PRo3D.Viewer.exe", sprintf "bin/publish/win-x64/PRo3D.Viewer.%s.exe" notes.NugetVersion)
)

"Credits" ==> "Publish" |> ignore
Expand Down
20 changes: 10 additions & 10 deletions src/PRo3D.Core/Drawing/Drawing-App.fs
Original file line number Diff line number Diff line change
Expand Up @@ -636,17 +636,17 @@ module DrawingApp =
pickingTolerance = msmallConfig.getPickingTolerance mbigConfig
}

let annoSet =
let labels =
model.annotations.flat
|> AMap.choose (fun _ y -> y |> tryToAnnotation) // TODO v5: here we collapsed some avals - check correctness
|> AMap.toASet

let labels =
annoSet
|> ASet.map(fun (_,a) ->
Sg.finishedAnnotationText a config view
)
|> Sg.set
|> AMap.toASetValues
|> ASet.chooseA (fun anno ->
match anno |> tryToAnnotation with
| None -> AVal.constant None
| Some v ->
Sg.shouldTextBeRendered v
|> AVal.map (function | true -> Some (Sg.drawText view config v) | _ -> None)
)
|> Sg.set

labels

Expand Down
14 changes: 5 additions & 9 deletions src/PRo3D.Core/Drawing/Drawing.Sg.fs
Original file line number Diff line number Diff line change
Expand Up @@ -413,15 +413,11 @@ module Sg =
dotsAndText
] |> optional anno.visible

let finishedAnnotationText
(anno : AdaptiveAnnotation)
(config : innerViewConfig)
(view : aval<CameraView>) =

anno.text
|> AVal.map3 (fun show visible text -> (String.IsNullOrEmpty text) || (show && visible) ) anno.showText anno.visible
|> optionalSet (drawText view config anno)
|> Sg.set

let shouldTextBeRendered (anno : AdaptiveAnnotation) =
(anno.text, anno.visible, anno.showText)
|||> AVal.map3 (fun text visible show -> show && visible && not (String.IsNullOrEmpty text))


let finishedAnnotation
(anno : AdaptiveAnnotation)
Expand Down
202 changes: 182 additions & 20 deletions src/PRo3D.Core/Surface/Surface.Sg.fs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ open Aardvark.GeoSpatial.Opc.PatchLod
open Aardvark.GeoSpatial.Opc.Load
open OpcViewer.Base
open Aardvark.Rendering.Text
open Aardvark.Geometry

module FootprintSg =
open Aardvark.SceneGraph.Sg
Expand Down Expand Up @@ -147,6 +148,129 @@ module Sg =

log area > 1.0 - (log p.factor) * 1.2

module Helper =

let intersectBox' (b : Box3d) (r : FastRay3d) =
let mutable tmin = -infinity
let mutable tmax = infinity
if r.Intersects(b, &tmin, &tmax) then
Some (tmin, tmax)
else
None

let intersectBox (b : Box3d) (r : Ray3d) =
FastRay3d r |> intersectBox' b



// hs: not sure what the original intention was, but was obviusly wrong (but worked reasonably well for most scenes)
// this this version removed obvious problems but is still much worse than the reworked on reworkedLoD
let cleanedOldLegacyLoD
(preTrafo : Trafo3d)
(self : AdaptiveToken)
(viewTrafo : aval<Trafo3d>)
(projTrafo : aval<Trafo3d>)
(renderPatch : Aardvark.GeoSpatial.Opc.PatchLod.RenderPatch)
(lodParams : aval<LodParameters>)
(isActive : aval<bool>)
=

let isRenderingActive = isActive.GetValue self
if isRenderingActive then
let lodParams = lodParams.GetValue self
let viewTrafo = viewTrafo.GetValue self
let model = preTrafo * renderPatch.trafo.GetValue self
let proj = projTrafo.GetValue self
let viewProj = viewTrafo * proj

let globalBBModelSpace = renderPatch.info.LocalBoundingBox.Transformed(model)
let cornersNdc = globalBBModelSpace.ComputeCorners() |> Array.map viewProj.TransformPosProj
let boundsNdc = Box3d(cornersNdc)
if Box3d(-V3d.IIO, V3d.III).Intersects(boundsNdc) then
let campPos = viewTrafo.Backward.C3.XYZ
let bb = renderPatch.info.GlobalBoundingBox.Transformed(lodParams.trafo)
let closest = bb.GetClosestPointOn(campPos)
let dist = (closest - campPos).Length

let unitPxSize = (lodParams.frustum.right - lodParams.frustum.left) / (float lodParams.size.X * 0.5)
let px = (0.1 * renderPatch.triangleSize) / (pow dist 1.2) // (pow dist 1.2) // (added pow 1.2 here... discuss)

// Log.warn "%f to %f - avgSize: %f" px (unitPxSize * lodParams.factor) p.triangleSize
px > unitPxSize * (exp lodParams.factor)
else
false
else
false

let reworkedLoD
(preTrafo : Trafo3d)
(intersect : ValueOption<FastRay3d -> ValueOption<V3d>>)
(self : AdaptiveToken)
(viewTrafo : aval<Trafo3d>)
(projTrafo : aval<Trafo3d>)
(renderPatch : Aardvark.GeoSpatial.Opc.PatchLod.RenderPatch)
(lodParams : aval<LodParameters>)
(isActive : aval<bool>) =

let renderingActive = isActive.GetValue self
if not renderingActive then false
else
let model = preTrafo * renderPatch.trafo.GetValue self
let view = viewTrafo.GetValue self
let proj = projTrafo.GetValue self
let p = lodParams.GetValue self
let viewProj = view * proj

let globalBBModelSpace = renderPatch.info.LocalBoundingBox.Transformed(model)
let cornersNdc = globalBBModelSpace.ComputeCorners() |> Array.map viewProj.TransformPosProj
let boundsNdc = Box3d(cornersNdc)
if Box3d(-V3d.IIO, V3d.III).Intersects(boundsNdc) then
// if we have a potential hit, also use the hold hacky one, if both (the new one and the old one) agree on going deeper, let's do it
// the situation is rather complex since many special cases (huge bounding boxes, inhomogenous point densities etc)
let legacyDecider = lodDeciderMars preTrafo self viewTrafo projTrafo renderPatch lodParams isActive

let camPos = view.Backward.C3.XYZ
let ray = Ray3d(view.Backward.C3.XYZ, -view.Backward.C2.XYZ)
let fastRay = FastRay3d(ray)
let referencePoint =
match Helper.intersectBox' globalBBModelSpace fastRay with
| Some (tmin,tmax) ->
match intersect with
| ValueSome intersectionFunction ->
match intersectionFunction fastRay with
| ValueNone ->
Log.warn "no hit"
globalBBModelSpace.Center
| ValueSome v ->
v
| ValueNone ->
if globalBBModelSpace.Contains(camPos) then
let scnd = ray.GetPointOnRay(tmax)
scnd
else
ray.GetPointOnRay(tmax)
| _ ->
globalBBModelSpace.Center
// approach: place virtual sphere with radius = triangle size at bb center
// go deeper until virtual sphere is smaller than one pixel
let localLodFocusPoint = referencePoint// arbitrary. use center for computing screen space triangle size
let lodCenterViewSpace = view.TransformPos(localLodFocusPoint)
let pointOnSphere = lodCenterViewSpace + V3d(renderPatch.triangleSize, renderPatch.triangleSize, 0.0)
let lodCenterNdc = proj.TransformPosProj(lodCenterViewSpace)
let pointOnSphereNdc = proj.TransformPosProj(pointOnSphere)
let triangleSizeInNcs = Vec.distance pointOnSphereNdc lodCenterNdc
// true = go deeper
// more restrictive condition = less LoDs
let normalizedQuality = p.factor - (-2.0) / (5.0 - (-2.0))
// triangle size in [-1,1] space, scale to [0,1], rescale with max viewport dimension to get to pixels
// roughly. Next, go deepter if triangle is larger than largestTriangleInPixels

let largestTriangleInPixels = 5.0
triangleSizeInNcs * 0.5 * float p.size.NormMax > largestTriangleInPixels * normalizedQuality && legacyDecider
else
// culled
false

let createPlainSceneGraph
(runtime : IRuntime)
(signature : IFramebufferSignature)
Expand All @@ -167,6 +291,61 @@ module Sg =
PatchHierarchy.load Serialization.binarySerializer.Pickle Serialization.binarySerializer.UnPickle (OpcPaths x)
)
|> Seq.toArray

let intersect =
let rayGuidedLoD = false
if rayGuidedLoD then
let kdTrees =
patchHierarchies
|> Array.choose (fun h ->
Log.startTimed "loading lowesd kd"
let kdTree =
let level, info =
match h.tree with
| QTree.Node(p,_) -> p.level, p.info
| QTree.Leaf p -> 0, p.info
match h.kdTree_FileAbsPath info.Name -1 ViewerModality.XYZ |> KdTrees.tryFixPatchFileIfNeeded with
| None ->
Log.warn "no kd tree for level 0"
None
| Some kdPath ->
let kd = KdTrees.loadKdtree kdPath
match h.opcPaths.Patches_DirAbsPath +/ info.Name +/ info.Positions |> KdTrees.tryFixPatchFileIfNeeded with
| None ->
None
| Some objectSetPath ->
let t = DebugKdTreesX.loadTriangles' info.Local2Global objectSetPath
kd.KdIntersectionTree.ObjectSet <- t
Some (h,kd, info.GlobalBoundingBox)
Log.stop()
kdTree
)

let intersect (r : FastRay3d) =
let hits =
kdTrees
|> Seq.filter (fun (h,kd,bb) ->
Helper.intersectBox' bb r |> Option.isSome
)
|> Seq.choose (fun (h,kd,bb) ->
let mutable hit = ObjectRayHit.MaxRange
let intersecBox = Helper.intersectBox' kd.KdIntersectionTree.BoundingBox3d r
if kd.KdIntersectionTree.Intersect(r, 0.0, Double.MaxValue, &hit) then
Some hit
else
None
)
if Seq.isEmpty hits then
ValueNone
else
let h = hits |> Seq.minBy (fun h -> h.RayHit.T)
ValueSome h.RayHit.Point

ValueSome intersect

else
ValueNone


let kdTreesPerHierarchy =
[|
Expand Down Expand Up @@ -215,8 +394,10 @@ module Sg =
| _ -> AVal.constant false :> IAdaptiveValue
]

let lodDeciderMars = lodDeciderMars scene.preTransform
//let lodDeciderMars = lodDeciderMars scene.preTransform
//let lodDeciderMars = marsArea scene.preTransform
//let lodDeciderMars = reworkedLoD scene.preTransform intersect
let lodDeciderMars = cleanedOldLegacyLoD scene.preTransform

let map =
Map.ofList [
Expand Down Expand Up @@ -260,25 +441,6 @@ module Sg =
Some (getVertexAttributes h.opcPaths),
Aardvark.Data.PixImagePfim.Loader
)

//let plainPatchLod =
// Sg.patchLod'
// signature
// runner
// h.opcPaths.Opc_DirAbsPath
// lodDeciderMars //scene.lodDecider
// scene.useCompressedTextures
// true
// ViewerModality.XYZ
// PatchLod.CoordinatesMapping.Local
// useAsyncLoading
// (PatchLod.toRoseTree h.tree)
// map
// (fun n s ->
// let vp = s.FootprintVP
// vp :> obj
// )
//plainPatchLod
patchLodWithTextures
)
|> SgFSharp.Sg.ofArray
Expand Down
5 changes: 4 additions & 1 deletion src/PRo3D.Viewer/InitialViewerModel.fs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ module Viewer =
//let defaultDashboard = DashboardModes.provenance
let defaultDockConfig = defaultDashboard.dockConfig //DockConfigs.m2020
let viewConfigModel = ViewConfigModel.initial

let applyProvenaceIfEnabled (m : Model) =
ProvenanceApp.emptyWithModel startupArgs.enableProvenanceTracking m
{
scene =
{
Expand Down Expand Up @@ -172,6 +175,6 @@ module Viewer =
animator = Animation.Animator.initial animatorLens

provenanceModel = ProvenanceModel.invalid
} |> ProvenanceApp.emptyWithModel
} |> applyProvenaceIfEnabled


8 changes: 7 additions & 1 deletion src/PRo3D.Viewer/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,13 @@ let main argv =
choose []

let suaveServer =
WebPart.startServer port [
let startServer =
if startupArgs.enableRemoteApi then
WebPart.startServer
else
WebPart.startServerLocalhost

startServer port [
if startupArgs.disableCors then allow_cors
MutableApp.toWebPart' runtime false mainApp
path "/websocket" >=> handShake ws
Expand Down
34 changes: 18 additions & 16 deletions src/PRo3D.Viewer/ProvenanceApp.fs
Original file line number Diff line number Diff line change
Expand Up @@ -90,23 +90,25 @@ module ProvenanceApp =
}


let emptyWithModel (m : Model) =
let emptyWithModel (enabled : bool) (m : Model) =
if enabled then
let i = { id = ProvenanceModel.newNodeId(); model = reduceModel m |> Some }

let i = { id = ProvenanceModel.newNodeId(); model = reduceModel m |> Some }

let pm = {
nodes = HashMap.ofList [i.id, i]
edges = HashMap.empty; lastEdge = None
automaticRecording = false
currentTrail = []
selectedNode = None
initialNode = Some i.id
}


{ m with
provenanceModel = pm
}
let pm = {
nodes = HashMap.ofList [i.id, i]
edges = HashMap.empty; lastEdge = None
automaticRecording = false
currentTrail = []
selectedNode = None
initialNode = Some i.id
}


{ m with
provenanceModel = pm
}
else
m

let track (oldModel : Model) (newModel : Model) (msg : ViewerAnimationAction) : Model =
if newModel.provenanceModel.automaticRecording then
Expand Down
Loading
Loading