diff --git a/Build.fs b/Build.fs index 29563925..785822da 100644 --- a/Build.fs +++ b/Build.fs @@ -237,7 +237,7 @@ let test = """let viewerVersion = "3.1.3" """ res *) -let aardiumVersion = "2.0.5" +let aardiumVersion = "2.1.1" //let versions = getInstalledPackageVersions() //match Map.tryFind "Aardium" versions with //| Some v -> v @@ -433,7 +433,7 @@ Target.create "Publish" (fun _ -> } ) - // snapshots + //// snapshots "src/PRo3D.Snapshots/PRo3D.Snapshots.fsproj" |> DotNet.publish (fun o -> { o with Framework = Some "net6.0" @@ -496,7 +496,7 @@ Target.create "Publish" (fun _ -> 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 diff --git a/TEST_RELEASE_NOTES.md b/TEST_RELEASE_NOTES.md index 20d6657b..9442ff90 100644 --- a/TEST_RELEASE_NOTES.md +++ b/TEST_RELEASE_NOTES.md @@ -1,3 +1,19 @@ +## 4.27.0-prerelease5 +- fixed screenshot functionality + +## 4.27.0-prerelease4 +- reverted polynomial distance decay for lod. + +## 4.27.0-prerelease3 +- fixed wrong picking when using pivot based transformations + +## 4.27.0-prerelease2 +- fixed lod when switching surfaces visible/invisible (keep invisible opcs in lod, to make fast switching possible) + +## 4.27.0-prerelease1 +- coordinate frames as scale bars +- fixed memory leak for high focal length fulcra + ## 4.26.0-prerelease2 - fixed surface priority - improved handling of large trajectories diff --git a/lib/JR.Wrappers.dll b/lib/JR.Wrappers.dll index 8c3d612f..65ae35e3 100644 Binary files a/lib/JR.Wrappers.dll and b/lib/JR.Wrappers.dll differ diff --git a/src/OpcViewer/Program.fs b/src/OpcViewer/Program.fs index c6750e5d..45f11fee 100644 --- a/src/OpcViewer/Program.fs +++ b/src/OpcViewer/Program.fs @@ -11,7 +11,7 @@ type Kind = Scene | Annotations | Solarsystem [] let main argv = - let kind = Scene + let kind = Annotations let shaler = { @@ -93,7 +93,7 @@ let main argv = preTransform = Trafo3d.Identity patchHierarchies = Seq.delay (fun _ -> - System.IO.Directory.GetDirectories(@"I:\OPC\Shaler_OPCs_2019\Shaler_Navcam") + System.IO.Directory.GetDirectories(@"C:\pro3ddata\Shaler_OPCs_2019\Shaler_Navcam") |> Seq.collect System.IO.Directory.GetDirectories ) boundingBox = Box3d.Parse("[[-2490137.664354247, 2285874.562728135, -271408.476700304], [-2490136.248131170, 2285875.658034266, -271406.605430601]]") @@ -103,37 +103,37 @@ let main argv = lodDecider = DefaultMetrics.mars2 } - let scene = - { - useCompressedTextures = true - preTransform = Trafo3d.Identity - patchHierarchies = - Seq.delay (fun _ -> - System.IO.Directory.GetDirectories(@"F:\pro3d\data\20200220_DinosaurQuarry2") - |> Seq.collect System.IO.Directory.GetDirectories - ) - boundingBox = Box3d.Parse("[[-15.699694740, 4.338130733, -0.514935397], [-4.960646670, 36.914955133, 5.004174588]]") - near = 0.1 - far = 10000.0 - speed = 5.0 - lodDecider = DefaultMetrics.mars2 - } + //let scene = + // { + // useCompressedTextures = true + // preTransform = Trafo3d.Identity + // patchHierarchies = + // Seq.delay (fun _ -> + // System.IO.Directory.GetDirectories(@"F:\pro3d\data\20200220_DinosaurQuarry2") + // |> Seq.collect System.IO.Directory.GetDirectories + // ) + // boundingBox = Box3d.Parse("[[-15.699694740, 4.338130733, -0.514935397], [-4.960646670, 36.914955133, 5.004174588]]") + // near = 0.1 + // far = 10000.0 + // speed = 5.0 + // lodDecider = DefaultMetrics.mars2 + // } - let scene = - { - useCompressedTextures = true - preTransform = Trafo3d.Identity - patchHierarchies = - Seq.delay (fun _ -> - System.IO.Directory.GetDirectories(@"F:\pro3d\data\20200220_DinosaurQuarry2") - |> Seq.collect System.IO.Directory.GetDirectories - ) - boundingBox = Box3d.Parse("[[-15.699694740, 4.338130733, -0.514935397], [-4.960646670, 36.914955133, 5.004174588]]") - near = 0.1 - far = 10000.0 - speed = 5.0 - lodDecider = DefaultMetrics.mars2 - } + //let scene = + // { + // useCompressedTextures = true + // preTransform = Trafo3d.Identity + // patchHierarchies = + // Seq.delay (fun _ -> + // System.IO.Directory.GetDirectories(@"F:\pro3d\data\20200220_DinosaurQuarry2") + // |> Seq.collect System.IO.Directory.GetDirectories + // ) + // boundingBox = Box3d.Parse("[[-15.699694740, 4.338130733, -0.514935397], [-4.960646670, 36.914955133, 5.004174588]]") + // near = 0.1 + // far = 10000.0 + // speed = 5.0 + // lodDecider = DefaultMetrics.mars2 + // } //let scene = // { @@ -149,20 +149,20 @@ let main argv = // lodDecider = DefaultMetrics.mars2 // } - let scene = - { - useCompressedTextures = true - preTransform = Trafo3d.Identity - patchHierarchies = - Seq.delay (fun _ -> - System.IO.Directory.GetDirectories(@"F:\pro3d\data\OpcMcz") - ) - boundingBox = Box3d.Parse("[[699507.902347501, 3142696.785742886, 1072717.259930025], [699508.165976587, 3142697.102699531, 1072717.505653937]]") - near = 0.1 - far = 10000.0 - speed = 5.0 - lodDecider = DefaultMetrics.mars2 - } + //let scene = + // { + // useCompressedTextures = true + // preTransform = Trafo3d.Identity + // patchHierarchies = + // Seq.delay (fun _ -> + // System.IO.Directory.GetDirectories(@"F:\pro3d\data\OpcMcz") + // ) + // boundingBox = Box3d.Parse("[[699507.902347501, 3142696.785742886, 1072717.259930025], [699508.165976587, 3142697.102699531, 1072717.505653937]]") + // near = 0.1 + // far = 10000.0 + // speed = 5.0 + // lodDecider = DefaultMetrics.mars2 + // } //let scene = // { @@ -202,6 +202,7 @@ let main argv = //let annotations = @"F:\pro3d\data\OpcMcz\singleAnno.pro3d.ann" let annotations = @"F:\pro3d\data\OpcMcz\blub.pro3d.ann" let annotations = @"F:\pro3d\data\OpcMcz\notworking.pro3d.ann" + let annotations = @"C:\pro3ddata\Shaler_OPCs_2019\Shaler_v2_Mastcam_w_Navcam_v18_merged_measurementsV2.pro3d.ann" //let annotations = @"F:\pro3d\data\OpcMcz\heavy.pro3d.ann" //let annotations = @"F:\pro3d\data\dimorphos\singleanno.pro3d.ann" diff --git a/src/PRo3D.Base/OutlineEffect.fs b/src/PRo3D.Base/OutlineEffect.fs index 7d7b4c58..a0a0d078 100644 --- a/src/PRo3D.Base/OutlineEffect.fs +++ b/src/PRo3D.Base/OutlineEffect.fs @@ -54,7 +54,7 @@ module OutlineEffect = } // NOTE: sg MUST only hold pure Sg without any modes or shaders! - let createForSg (outlineGroup: int) (pass: RenderPass) (color: C4f) sg = + let createForSg' (lineWidth : aval) (outlineGroup: int) (pass: RenderPass) (color: C4f) (sg : ISg<_>) = let sg = sg |> Sg.uniform "Color" (AVal.constant color) let mask = @@ -79,7 +79,7 @@ module OutlineEffect = |> Sg.blendMode (AVal.init BlendMode.Blend) |> Sg.fillMode (AVal.init FillMode.Fill) |> Sg.pass pass - |> Sg.uniform "LineWidth" (AVal.constant 5.0) + |> Sg.uniform "LineWidth" lineWidth |> Sg.shader { do! DefaultSurfaces.stableTrafo do! Shader.lines @@ -89,6 +89,10 @@ module OutlineEffect = } [ mask; outline ] |> Sg.ofList + + // NOTE: sg MUST only hold pure Sg without any modes or shaders! + let createForSg (outlineGroup: int) (pass: RenderPass) (color: C4f) (sg : ISg<_>) = + createForSg' (AVal.constant 5.0) outlineGroup pass color sg let createForLine (points: aval) diff --git a/src/PRo3D.Base/WebClientDeprecation.fs b/src/PRo3D.Base/WebClientDeprecation.fs index 3b6c83d3..ce45e812 100644 --- a/src/PRo3D.Base/WebClientDeprecation.fs +++ b/src/PRo3D.Base/WebClientDeprecation.fs @@ -13,4 +13,4 @@ module Helpers = } member x.DownloadFile(uri : string, filename : string) = - x.DownloadFileAsync(uri, filename).RunSynchronously() \ No newline at end of file + x.DownloadFileAsync(uri, filename).Wait() \ No newline at end of file diff --git a/src/PRo3D.Core/Drawing/Drawing-App.fs b/src/PRo3D.Core/Drawing/Drawing-App.fs index 4b40ee79..631c7cf1 100644 --- a/src/PRo3D.Core/Drawing/Drawing-App.fs +++ b/src/PRo3D.Core/Drawing/Drawing-App.fs @@ -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 diff --git a/src/PRo3D.Core/Drawing/Drawing.Sg.fs b/src/PRo3D.Core/Drawing/Drawing.Sg.fs index 6e0b7fae..d6d18647 100644 --- a/src/PRo3D.Core/Drawing/Drawing.Sg.fs +++ b/src/PRo3D.Core/Drawing/Drawing.Sg.fs @@ -413,15 +413,11 @@ module Sg = dotsAndText ] |> optional anno.visible - let finishedAnnotationText - (anno : AdaptiveAnnotation) - (config : innerViewConfig) - (view : aval) = - - 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) @@ -443,14 +439,7 @@ module Sg = // anno.geometry // config.offset // ) - - let texts = - anno.text - |> AVal.map2 (fun show text -> (String.IsNullOrEmpty text) || show ) anno.showText - |> optionalSet (drawText view config anno) - - let dotsAndText = texts |> Sg.set //ASet.union' [dots; texts] |> Sg.set - + //let selectionColor = AVal.map2(fun x color -> if x then C4b.VRVisGreen else color) picked c let pickingAllowed = // for this particular annotation // whether should fire pick actions AVal.map2 (&&) pickingAllowed anno.visible diff --git a/src/PRo3D.Core/ScaleBars-Model.fs b/src/PRo3D.Core/ScaleBars-Model.fs index 27e05cb6..ebff9b21 100644 --- a/src/PRo3D.Core/ScaleBars-Model.fs +++ b/src/PRo3D.Core/ScaleBars-Model.fs @@ -96,8 +96,12 @@ type scSegment with do! Json.write "color" (x.color.ToString()) } +type ScaleRepresentation = + | ScaleBar = 0 + | CoordinateFrame = 1 + [] -type ScaleBar = { +type ScaleVisualization = { version : int guid : System.Guid name : string @@ -120,6 +124,8 @@ type ScaleBar = { transformation : Transformations preTransform : Trafo3d //direction : V3d + + representation : ScaleRepresentation } [] @@ -175,6 +181,10 @@ module ScaleBar = let orientation = orientation |> enum + let! representation = + Json.tryRead "representation" + + //let! direction = Json.tryRead "direction" return @@ -200,14 +210,12 @@ module ScaleBar = view = view transformation = transformation preTransform = preTransform |> Trafo3d.Parse - //direction = match direction with - // | Some d -> d |> V3d.Parse - // | None -> getDirectionVec orientation view + representation = representation |> Option.map enum |> Option.defaultValue ScaleRepresentation.ScaleBar } } -type ScaleBar with - static member FromJson(_ : ScaleBar) = +type ScaleVisualization with + static member FromJson(_ : ScaleVisualization) = json { let! v = Json.read "version" match v with @@ -217,7 +225,7 @@ type ScaleBar with |> sprintf "don't know version %A of ScaleBar" |> Json.error } - static member ToJson(x : ScaleBar) = + static member ToJson(x : ScaleVisualization) = json { do! Json.write "version" x.version do! Json.write "guid" x.guid @@ -242,6 +250,7 @@ type ScaleBar with do! Json.write "view" camView do! Json.write "transformation" x.transformation do! Json.write "preTransform" (x.preTransform.ToString()) + do! Json.write "representation" (int x.representation) //do! Json.write "direction" (x.direction.ToString()) } @@ -249,7 +258,7 @@ type ScaleBar with [] type ScaleBarsModel = { version : int - scaleBars : HashMap + scaleBars : HashMap selectedScaleBar : Option } @@ -259,7 +268,7 @@ module ScaleBarsModel = let read0 = json { let! scaleBars = Json.read "scaleBars" - let scaleBars = scaleBars |> List.map(fun (a : ScaleBar) -> (a.guid, a)) |> HashMap.ofList + let scaleBars = scaleBars |> List.map(fun (a : ScaleVisualization) -> (a.guid, a)) |> HashMap.ofList let! selected = Json.read "selectedScaleBar" return diff --git a/src/PRo3D.Core/ScaleBars-Model.g.fs b/src/PRo3D.Core/ScaleBars-Model.g.fs index fc9bcb6e..b879cacb 100644 --- a/src/PRo3D.Core/ScaleBars-Model.g.fs +++ b/src/PRo3D.Core/ScaleBars-Model.g.fs @@ -1,5 +1,5 @@ -//27ac5532-ddb7-01d9-9019-b717235c0777 -//652ff85a-951e-e7c3-8a3d-31cd4ac20715 +//55ffe839-1706-fe94-127c-a66d739541fc +//6e02a380-6769-a0ff-1f49-6d0a6d57d862 #nowarn "49" // upper case patterns #nowarn "66" // upcast is unncecessary #nowarn "1337" // internal types @@ -37,7 +37,7 @@ module scSegmentLenses = static member endPoint_ = ((fun (self : scSegment) -> self.endPoint), (fun (value : Aardvark.Base.V3d) (self : scSegment) -> { self with endPoint = value })) static member color_ = ((fun (self : scSegment) -> self.color), (fun (value : Aardvark.Base.C4b) (self : scSegment) -> { self with color = value })) [] -type AdaptiveScaleBar(value : ScaleBar) = +type AdaptiveScaleVisualization(value : ScaleVisualization) = let _version_ = FSharp.Data.Adaptive.cval(value.version) let _guid_ = FSharp.Data.Adaptive.cval(value.guid) let _name_ = FSharp.Data.Adaptive.cval(value.name) @@ -60,12 +60,13 @@ type AdaptiveScaleBar(value : ScaleBar) = let _view_ = FSharp.Data.Adaptive.cval(value.view) let _transformation_ = PRo3D.Core.Surface.AdaptiveTransformations(value.transformation) let _preTransform_ = FSharp.Data.Adaptive.cval(value.preTransform) + let _representation_ = FSharp.Data.Adaptive.cval(value.representation) let mutable __value = value let __adaptive = FSharp.Data.Adaptive.AVal.custom((fun (token : FSharp.Data.Adaptive.AdaptiveToken) -> __value)) - static member Create(value : ScaleBar) = AdaptiveScaleBar(value) - static member Unpersist = Adaptify.Unpersist.create (fun (value : ScaleBar) -> AdaptiveScaleBar(value)) (fun (adaptive : AdaptiveScaleBar) (value : ScaleBar) -> adaptive.Update(value)) - member __.Update(value : ScaleBar) = - if Microsoft.FSharp.Core.Operators.not((FSharp.Data.Adaptive.ShallowEqualityComparer.ShallowEquals(value, __value))) then + static member Create(value : ScaleVisualization) = AdaptiveScaleVisualization(value) + static member Unpersist = Adaptify.Unpersist.create (fun (value : ScaleVisualization) -> AdaptiveScaleVisualization(value)) (fun (adaptive : AdaptiveScaleVisualization) (value : ScaleVisualization) -> adaptive.Update(value)) + member __.Update(value : ScaleVisualization) = + if Microsoft.FSharp.Core.Operators.not((FSharp.Data.Adaptive.ShallowEqualityComparer.ShallowEquals(value, __value))) then __value <- value __adaptive.MarkOutdated() _version_.Value <- value.version @@ -86,6 +87,7 @@ type AdaptiveScaleBar(value : ScaleBar) = _view_.Value <- value.view _transformation_.Update(value.transformation) _preTransform_.Value <- value.preTransform + _representation_.Value <- value.representation member __.Current = __adaptive member __.version = _version_ :> FSharp.Data.Adaptive.aval member __.guid = _guid_ :> FSharp.Data.Adaptive.aval @@ -105,27 +107,29 @@ type AdaptiveScaleBar(value : ScaleBar) = member __.view = _view_ :> FSharp.Data.Adaptive.aval member __.transformation = _transformation_ member __.preTransform = _preTransform_ :> FSharp.Data.Adaptive.aval + member __.representation = _representation_ :> FSharp.Data.Adaptive.aval [] -module ScaleBarLenses = - type ScaleBar with - static member version_ = ((fun (self : ScaleBar) -> self.version), (fun (value : Microsoft.FSharp.Core.int) (self : ScaleBar) -> { self with version = value })) - static member guid_ = ((fun (self : ScaleBar) -> self.guid), (fun (value : System.Guid) (self : ScaleBar) -> { self with guid = value })) - static member name_ = ((fun (self : ScaleBar) -> self.name), (fun (value : Microsoft.FSharp.Core.string) (self : ScaleBar) -> { self with name = value })) - static member text_ = ((fun (self : ScaleBar) -> self.text), (fun (value : Microsoft.FSharp.Core.string) (self : ScaleBar) -> { self with text = value })) - static member textsize_ = ((fun (self : ScaleBar) -> self.textsize), (fun (value : Aardvark.UI.Primitives.NumericInput) (self : ScaleBar) -> { self with textsize = value })) - static member textVisible_ = ((fun (self : ScaleBar) -> self.textVisible), (fun (value : Microsoft.FSharp.Core.bool) (self : ScaleBar) -> { self with textVisible = value })) - static member isVisible_ = ((fun (self : ScaleBar) -> self.isVisible), (fun (value : Microsoft.FSharp.Core.bool) (self : ScaleBar) -> { self with isVisible = value })) - static member position_ = ((fun (self : ScaleBar) -> self.position), (fun (value : Aardvark.Base.V3d) (self : ScaleBar) -> { self with position = value })) - static member scSegments_ = ((fun (self : ScaleBar) -> self.scSegments), (fun (value : FSharp.Data.Adaptive.IndexList) (self : ScaleBar) -> { self with scSegments = value })) - static member orientation_ = ((fun (self : ScaleBar) -> self.orientation), (fun (value : Orientation) (self : ScaleBar) -> { self with orientation = value })) - static member alignment_ = ((fun (self : ScaleBar) -> self.alignment), (fun (value : Pivot) (self : ScaleBar) -> { self with alignment = value })) - static member thickness_ = ((fun (self : ScaleBar) -> self.thickness), (fun (value : Aardvark.UI.Primitives.NumericInput) (self : ScaleBar) -> { self with thickness = value })) - static member length_ = ((fun (self : ScaleBar) -> self.length), (fun (value : Aardvark.UI.Primitives.NumericInput) (self : ScaleBar) -> { self with length = value })) - static member unit_ = ((fun (self : ScaleBar) -> self.unit), (fun (value : Unit) (self : ScaleBar) -> { self with unit = value })) - static member subdivisions_ = ((fun (self : ScaleBar) -> self.subdivisions), (fun (value : Aardvark.UI.Primitives.NumericInput) (self : ScaleBar) -> { self with subdivisions = value })) - static member view_ = ((fun (self : ScaleBar) -> self.view), (fun (value : Aardvark.Rendering.CameraView) (self : ScaleBar) -> { self with view = value })) - static member transformation_ = ((fun (self : ScaleBar) -> self.transformation), (fun (value : PRo3D.Core.Surface.Transformations) (self : ScaleBar) -> { self with transformation = value })) - static member preTransform_ = ((fun (self : ScaleBar) -> self.preTransform), (fun (value : Aardvark.Base.Trafo3d) (self : ScaleBar) -> { self with preTransform = value })) +module ScaleVisualizationLenses = + type ScaleVisualization with + static member version_ = ((fun (self : ScaleVisualization) -> self.version), (fun (value : Microsoft.FSharp.Core.int) (self : ScaleVisualization) -> { self with version = value })) + static member guid_ = ((fun (self : ScaleVisualization) -> self.guid), (fun (value : System.Guid) (self : ScaleVisualization) -> { self with guid = value })) + static member name_ = ((fun (self : ScaleVisualization) -> self.name), (fun (value : Microsoft.FSharp.Core.string) (self : ScaleVisualization) -> { self with name = value })) + static member text_ = ((fun (self : ScaleVisualization) -> self.text), (fun (value : Microsoft.FSharp.Core.string) (self : ScaleVisualization) -> { self with text = value })) + static member textsize_ = ((fun (self : ScaleVisualization) -> self.textsize), (fun (value : Aardvark.UI.Primitives.NumericInput) (self : ScaleVisualization) -> { self with textsize = value })) + static member textVisible_ = ((fun (self : ScaleVisualization) -> self.textVisible), (fun (value : Microsoft.FSharp.Core.bool) (self : ScaleVisualization) -> { self with textVisible = value })) + static member isVisible_ = ((fun (self : ScaleVisualization) -> self.isVisible), (fun (value : Microsoft.FSharp.Core.bool) (self : ScaleVisualization) -> { self with isVisible = value })) + static member position_ = ((fun (self : ScaleVisualization) -> self.position), (fun (value : Aardvark.Base.V3d) (self : ScaleVisualization) -> { self with position = value })) + static member scSegments_ = ((fun (self : ScaleVisualization) -> self.scSegments), (fun (value : FSharp.Data.Adaptive.IndexList) (self : ScaleVisualization) -> { self with scSegments = value })) + static member orientation_ = ((fun (self : ScaleVisualization) -> self.orientation), (fun (value : Orientation) (self : ScaleVisualization) -> { self with orientation = value })) + static member alignment_ = ((fun (self : ScaleVisualization) -> self.alignment), (fun (value : Pivot) (self : ScaleVisualization) -> { self with alignment = value })) + static member thickness_ = ((fun (self : ScaleVisualization) -> self.thickness), (fun (value : Aardvark.UI.Primitives.NumericInput) (self : ScaleVisualization) -> { self with thickness = value })) + static member length_ = ((fun (self : ScaleVisualization) -> self.length), (fun (value : Aardvark.UI.Primitives.NumericInput) (self : ScaleVisualization) -> { self with length = value })) + static member unit_ = ((fun (self : ScaleVisualization) -> self.unit), (fun (value : Unit) (self : ScaleVisualization) -> { self with unit = value })) + static member subdivisions_ = ((fun (self : ScaleVisualization) -> self.subdivisions), (fun (value : Aardvark.UI.Primitives.NumericInput) (self : ScaleVisualization) -> { self with subdivisions = value })) + static member view_ = ((fun (self : ScaleVisualization) -> self.view), (fun (value : Aardvark.Rendering.CameraView) (self : ScaleVisualization) -> { self with view = value })) + static member transformation_ = ((fun (self : ScaleVisualization) -> self.transformation), (fun (value : PRo3D.Core.Surface.Transformations) (self : ScaleVisualization) -> { self with transformation = value })) + static member preTransform_ = ((fun (self : ScaleVisualization) -> self.preTransform), (fun (value : Aardvark.Base.Trafo3d) (self : ScaleVisualization) -> { self with preTransform = value })) + static member representation_ = ((fun (self : ScaleVisualization) -> self.representation), (fun (value : ScaleRepresentation) (self : ScaleVisualization) -> { self with representation = value })) [] type AdaptiveScaleBarDrawing(value : ScaleBarDrawing) = let _orientation_ = FSharp.Data.Adaptive.cval(value.orientation) @@ -164,10 +168,10 @@ module ScaleBarDrawingLenses = type AdaptiveScaleBarsModel(value : ScaleBarsModel) = let _version_ = FSharp.Data.Adaptive.cval(value.version) let _scaleBars_ = - let inline __arg2 (m : AdaptiveScaleBar) (v : ScaleBar) = + let inline __arg2 (m : AdaptiveScaleVisualization) (v : ScaleVisualization) = m.Update(v) m - FSharp.Data.Traceable.ChangeableModelMap(value.scaleBars, (fun (v : ScaleBar) -> AdaptiveScaleBar(v)), __arg2, (fun (m : AdaptiveScaleBar) -> m)) + FSharp.Data.Traceable.ChangeableModelMap(value.scaleBars, (fun (v : ScaleVisualization) -> AdaptiveScaleVisualization(v)), __arg2, (fun (m : AdaptiveScaleVisualization) -> m)) let _selectedScaleBar_ = FSharp.Data.Adaptive.cval(value.selectedScaleBar) let mutable __value = value let __adaptive = FSharp.Data.Adaptive.AVal.custom((fun (token : FSharp.Data.Adaptive.AdaptiveToken) -> __value)) @@ -182,12 +186,12 @@ type AdaptiveScaleBarsModel(value : ScaleBarsModel) = _selectedScaleBar_.Value <- value.selectedScaleBar member __.Current = __adaptive member __.version = _version_ :> FSharp.Data.Adaptive.aval - member __.scaleBars = _scaleBars_ :> FSharp.Data.Adaptive.amap + member __.scaleBars = _scaleBars_ :> FSharp.Data.Adaptive.amap member __.selectedScaleBar = _selectedScaleBar_ :> FSharp.Data.Adaptive.aval> [] module ScaleBarsModelLenses = type ScaleBarsModel with static member version_ = ((fun (self : ScaleBarsModel) -> self.version), (fun (value : Microsoft.FSharp.Core.int) (self : ScaleBarsModel) -> { self with version = value })) - static member scaleBars_ = ((fun (self : ScaleBarsModel) -> self.scaleBars), (fun (value : FSharp.Data.Adaptive.HashMap) (self : ScaleBarsModel) -> { self with scaleBars = value })) + static member scaleBars_ = ((fun (self : ScaleBarsModel) -> self.scaleBars), (fun (value : FSharp.Data.Adaptive.HashMap) (self : ScaleBarsModel) -> { self with scaleBars = value })) static member selectedScaleBar_ = ((fun (self : ScaleBarsModel) -> self.selectedScaleBar), (fun (value : Microsoft.FSharp.Core.Option) (self : ScaleBarsModel) -> { self with selectedScaleBar = value })) diff --git a/src/PRo3D.Core/ScaleBarsApp.fs b/src/PRo3D.Core/ScaleBarsApp.fs index e618f8c5..fc93e996 100644 --- a/src/PRo3D.Core/ScaleBarsApp.fs +++ b/src/PRo3D.Core/ScaleBarsApp.fs @@ -61,8 +61,9 @@ module ScaleBarProperties = | SetOrientation of Orientation | SetUnit of PRo3D.Core.Unit | SetSubdivisions of Numeric.Action + | SetRepresentation of ScaleRepresentation - let update (model : ScaleBar) (act : Action) = + let update (model : ScaleVisualization) (act : Action) = match act with | SetName s -> { model with name = s } @@ -85,8 +86,10 @@ module ScaleBarProperties = { model with unit = mode; text = text'} | SetSubdivisions a -> { model with subdivisions = Numeric.update model.subdivisions a} + | SetRepresentation mode -> + { model with representation = mode } - let view (model : AdaptiveScaleBar) = + let view (model : AdaptiveScaleVisualization) = require GuiEx.semui ( Html.table [ Html.row "Name:" [Html.SemUi.textBox model.name SetName ] @@ -98,6 +101,7 @@ module ScaleBarProperties = Html.row "Subdivisions:" [Numeric.view' [NumericInputType.InputBox] model.subdivisions |> UI.map SetSubdivisions ] Html.row "Orientation:" [Html.SemUi.dropDown model.orientation SetOrientation] Html.row "Unit:" [Html.SemUi.dropDown model.unit SetUnit] + Html.row "Representation:" [Html.SemUi.dropDown model.representation SetRepresentation] //Html.row "Pivot:" [Html.SemUi.dropDown model.alignment SetPivot] ] ) @@ -139,9 +143,9 @@ module ScaleBarUtils = | Orientation.Horizontal_cam -> view.Right | Orientation.Vertical_cam -> view.Up | Orientation.Sky_cam -> view.Sky - | Orientation.Horizontal_planet -> planetUp.Cross(view.Backward) + | Orientation.Horizontal_planet -> planetUp.Cross(view.Backward).Normalized | Orientation.Sky_planet -> planetUp - |_ -> view.Right + |_ -> view.Right.Normalized let getP1 @@ -184,7 +188,7 @@ module ScaleBarUtils = segments <- segments |> IndexList.add segment segments - let updateSegments (scaleBar : ScaleBar) (planet : Planet) = + let updateSegments (scaleBar : ScaleVisualization) (planet : Planet) = let direction = getDirectionVec scaleBar.orientation scaleBar.view scaleBar.position planet let length = getLengthInMeter scaleBar.unit scaleBar.length.value getSegments scaleBar.position length direction scaleBar.alignment ((int)scaleBar.subdivisions.value) @@ -224,7 +228,7 @@ module ScaleBarUtils = transformation = Init.transformations preTransform = Trafo3d.Identity - //direction = direction + representation = ScaleRepresentation.ScaleBar } @@ -504,7 +508,7 @@ module ScaleBarsApp = } |> Sg.dynamic let getP1P2 - (scaleBar : AdaptiveScaleBar) + (scaleBar : AdaptiveScaleVisualization) (planet : aval)= aval { let! position = scaleBar.position @@ -523,7 +527,7 @@ module ScaleBarsApp = } let viewSingleText - (scaleBar : AdaptiveScaleBar) + (scaleBar : AdaptiveScaleVisualization) (view : aval) (near : aval) (hfov : aval) @@ -589,7 +593,7 @@ module ScaleBarsApp = |> Sg.set let viewSingleScaleBarCylinder - (scaleBar : AdaptiveScaleBar) + (scaleBar : AdaptiveScaleVisualization) (view : aval) (near : aval) (selected : aval>) @@ -654,6 +658,88 @@ module ScaleBarsApp = } |> Sg.dynamic + + let coordinateCrossCylinders (colors : array) (isMask : bool) (thickness : aval) (length : aval) = + length + |> AVal.map (fun length -> + [ + { startPoint = V3d.Zero; endPoint = V3d.XAxis * length; color = colors[0] } + { startPoint = V3d.Zero; endPoint = V3d.YAxis * length; color = colors[1] } + { startPoint = V3d.Zero; endPoint = V3d.ZAxis * length; color = colors[2] } + ] + |> List.map (fun seg -> + let aseg = seg |> AdaptivescSegment.Create + if isMask then + getSgSegmentCylinderMask aseg thickness V3d.Zero + else + getSgSegmentCylinder aseg thickness V3d.Zero + ) + |> Sg.ofList + ) + |> Sg.dynamic + + + let viewScaleCoordinateFrame + (scaleBar : AdaptiveScaleVisualization) + (view : aval) + (near : aval) + (selected : aval>) + (refSys : AdaptiveReferenceSystem) = + + let inRefFrame = + refSys.Current + |> AVal.map (fun refSys -> + TransformationApp.getReferenceSystemBasis V3d.Zero refSys + ) + + let fullTranslation = + adaptive { + let! scaleBarTrans = scaleBar.transformation.translation.value + //translation along north, east, up + let! refsys = refSys.Current + let translation = (TransformationApp.translationFromReferenceSystemBasis scaleBarTrans V3d.Zero refsys) //|> Trafo3d.Translation + + let! pos = scaleBar.position + return (Trafo3d.Translation pos) * (translation |> Trafo3d.Translation) + } + + let selectionSg = + let visible = + (scaleBar.guid, selected) ||> AVal.map2 (fun current selected -> + match selected with + | Some sel when sel = current -> true + | _ -> false + ) + let selectionSg = + coordinateCrossCylinders [| C4b.IndianRed; C4b.DarkGreen; C4b.DarkBlue |] true scaleBar.thickness.value scaleBar.length.value + |> Sg.onOff visible + // does not work nicely with those cylinders + OutlineEffect.createForSg' (AVal.constant 2.0) 2 RenderPass.main C4f.VRVisGreen selectionSg + //selectionSg + + + coordinateCrossCylinders [| C4b.Red; C4b.Green; C4b.Blue |] false scaleBar.thickness.value scaleBar.length.value + |> Sg.andAlso selectionSg + |> Sg.trafo inRefFrame // for orientation + |> Sg.trafo fullTranslation // for translation (not happy with how it is handled currently though, part of trafo rework) + |> Sg.onOff scaleBar.isVisible + + let viewScaleBarVisualization + (viewScaleModel : AdaptiveScaleVisualization) + (view : aval) + (near : aval) + (selected : aval>) + (refSys : AdaptiveReferenceSystem) = + + viewScaleModel.representation + |> AVal.map (function + | ScaleRepresentation.CoordinateFrame -> + viewScaleCoordinateFrame viewScaleModel view near selected refSys + | _ -> + viewSingleScaleBarCylinder viewScaleModel view near selected refSys + ) + |> Sg.dynamic + let view (scaleBarsModel : AdaptiveScaleBarsModel) (view : aval) @@ -668,7 +754,7 @@ module ScaleBarsApp = scaleBars |> AMap.map( fun id sb -> - viewSingleScaleBarCylinder + viewScaleBarVisualization sb view near diff --git a/src/PRo3D.Core/SequencedBookmarks/SequencedBookmarks-Model.g.fs b/src/PRo3D.Core/SequencedBookmarks/SequencedBookmarks-Model.g.fs index 8e3886dc..e3edfd20 100644 --- a/src/PRo3D.Core/SequencedBookmarks/SequencedBookmarks-Model.g.fs +++ b/src/PRo3D.Core/SequencedBookmarks/SequencedBookmarks-Model.g.fs @@ -1,5 +1,5 @@ //6d8cd910-4dda-ff00-b5b9-3124d680763e -//3c8b49e2-8409-5ae6-0249-2d61ef7d14b6 +//27fed84a-92a3-c0f8-2bf4-85ad9cadf2db #nowarn "49" // upper case patterns #nowarn "66" // upcast is unncecessary #nowarn "1337" // internal types @@ -12,11 +12,11 @@ open Adaptify open PRo3D.Core.SequencedBookmarks [] type AdaptiveSequencedBookmarkModel(value : SequencedBookmarkModel) = - let mutable _cameraView_ = FSharp.Data.Adaptive.cval(value.cameraView) - let mutable _name_ = FSharp.Data.Adaptive.cval(value.name) - let mutable _key_ = FSharp.Data.Adaptive.cval(value.key) let mutable _path_ = FSharp.Data.Adaptive.cval(value.path) + let mutable _key_ = FSharp.Data.Adaptive.cval(value.key) + let mutable _cameraView_ = FSharp.Data.Adaptive.cval(value.cameraView) let mutable _filename_ = FSharp.Data.Adaptive.cval(value.filename) + let mutable _name_ = FSharp.Data.Adaptive.cval(value.name) let _bookmark_ = PRo3D.Core.AdaptiveBookmark(value.bookmark) let _metadata_ = FSharp.Data.Adaptive.cval(value.metadata) let _frustumParameters_ = FSharp.Data.Adaptive.cval(value.frustumParameters) @@ -41,11 +41,11 @@ type AdaptiveSequencedBookmarkModel(value : SequencedBookmarkModel) = if Microsoft.FSharp.Core.Operators.not((FSharp.Data.Adaptive.ShallowEqualityComparer.ShallowEquals(value, __value))) then __value <- value __adaptive.MarkOutdated() - _cameraView_.Value <- value.cameraView - _name_.Value <- value.name - _key_.Value <- value.key _path_.Value <- value.path + _key_.Value <- value.key + _cameraView_.Value <- value.cameraView _filename_.Value <- value.filename + _name_.Value <- value.name _bookmark_.Update(value.bookmark) _metadata_.Value <- value.metadata _frustumParameters_.Value <- value.frustumParameters @@ -56,11 +56,11 @@ type AdaptiveSequencedBookmarkModel(value : SequencedBookmarkModel) = _duration_.Update(value.duration) _observationInfo_.Update(value.observationInfo) member __.Current = __adaptive - member __.cameraView = _cameraView_ :> FSharp.Data.Adaptive.aval - member __.name = _name_ :> FSharp.Data.Adaptive.aval - member __.key = _key_ :> FSharp.Data.Adaptive.aval member __.path = _path_ :> FSharp.Data.Adaptive.aval + member __.key = _key_ :> FSharp.Data.Adaptive.aval + member __.cameraView = _cameraView_ :> FSharp.Data.Adaptive.aval member __.filename = _filename_ :> FSharp.Data.Adaptive.aval + member __.name = _name_ :> FSharp.Data.Adaptive.aval member __.version = __value.version member __.bookmark = _bookmark_ member __.metadata = _metadata_ :> FSharp.Data.Adaptive.aval> diff --git a/src/PRo3D.Core/Surface/Surface.Sg.fs b/src/PRo3D.Core/Surface/Surface.Sg.fs index 2b0692fc..e135d6e4 100644 --- a/src/PRo3D.Core/Surface/Surface.Sg.fs +++ b/src/PRo3D.Core/Surface/Surface.Sg.fs @@ -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 @@ -147,6 +148,131 @@ 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) + (projTrafo : aval) + (renderPatch : Aardvark.GeoSpatial.Opc.PatchLod.RenderPatch) + (lodParams : aval) + (isActive : aval) + = + + let isRenderingActive = + //isActive.GetValue self, using isActive (actually is invisible) is not possible here, see https://github.com/pro3d-space/PRo3D/issues/484 + true + 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) / dist // (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 ValueOption>) + (self : AdaptiveToken) + (viewTrafo : aval) + (projTrafo : aval) + (renderPatch : Aardvark.GeoSpatial.Opc.PatchLod.RenderPatch) + (lodParams : aval) + (isActive : aval) = + + 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) @@ -167,6 +293,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 = [| @@ -215,8 +396,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 [ @@ -260,25 +443,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 diff --git a/src/PRo3D.Core/TransformationApp.fs b/src/PRo3D.Core/TransformationApp.fs index 9e177fdc..d00cdbb9 100644 --- a/src/PRo3D.Core/TransformationApp.fs +++ b/src/PRo3D.Core/TransformationApp.fs @@ -64,13 +64,13 @@ module TransformationApp = //let upP = CooTransformation.getUpVector transform.pivot.value refsys.planet let upP = CooTransformation.getUpVector pivot refsys.planet - let eastP = V3d.OOI.Cross(upP) + let eastP = V3d.OOI.Cross(upP.Normalized).Normalized let northP = match refsys.planet with | Planet.None | Planet.JPL -> V3d.IOO | Planet.ENU -> V3d.OIO - | _ -> upP.Cross(eastP) + | _ -> upP.Cross(eastP).Normalized let noP = Rot3d.Rotation(upP, refsys.noffset.value |> Double.radiansFromDegrees).Transform(northP) diff --git a/src/PRo3D.Viewer/InitialViewerModel.fs b/src/PRo3D.Viewer/InitialViewerModel.fs index f940dcc1..d96e91c7 100644 --- a/src/PRo3D.Viewer/InitialViewerModel.fs +++ b/src/PRo3D.Viewer/InitialViewerModel.fs @@ -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 = { @@ -172,6 +175,6 @@ module Viewer = animator = Animation.Animator.initial animatorLens provenanceModel = ProvenanceModel.invalid - } |> ProvenanceApp.emptyWithModel + } |> applyProvenaceIfEnabled diff --git a/src/PRo3D.Viewer/Program.fs b/src/PRo3D.Viewer/Program.fs index 284d9794..5f3b7bea 100644 --- a/src/PRo3D.Viewer/Program.fs +++ b/src/PRo3D.Viewer/Program.fs @@ -52,7 +52,7 @@ type Result = result : string; } -let viewerVersion = "4.26.0-prerelease1" +let viewerVersion = "4.27.0-prerelease1" let catchDomainErrors = false open System.IO @@ -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 diff --git a/src/PRo3D.Viewer/ProvenanceApp.fs b/src/PRo3D.Viewer/ProvenanceApp.fs index bbdd3c0c..d2786371 100644 --- a/src/PRo3D.Viewer/ProvenanceApp.fs +++ b/src/PRo3D.Viewer/ProvenanceApp.fs @@ -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 diff --git a/src/PRo3D.Viewer/Viewer/Viewer.fs b/src/PRo3D.Viewer/Viewer/Viewer.fs index 11fec86f..645af0a0 100644 --- a/src/PRo3D.Viewer/Viewer/Viewer.fs +++ b/src/PRo3D.Viewer/Viewer/Viewer.fs @@ -1099,7 +1099,6 @@ module ViewerApp = m.screenshotDirectory _animator m.viewerVersion - |> ProvenanceApp.emptyWithModel { initialModel with recent = m.recent} |> ViewerIO.loadRoverData @@ -2219,7 +2218,7 @@ module ViewerApp = if startEmpty |> not then PRo3D.Viewer.Viewer.initial messagingMailbox StartupArgs.initArgs renderingUrl dataSamples screenshotDirectory _animator viewerVersion - |> ProvenanceApp.emptyWithModel + |> ProvenanceApp.emptyWithModel enableProvenance |> SceneLoader.loadLastScene runtime signature |> SceneLoader.loadLogBrush |> ViewerIO.loadRoverData @@ -2235,7 +2234,7 @@ module ViewerApp = else PRo3D.Viewer.Viewer.initial messagingMailbox StartupArgs.initArgs renderingUrl dataSamples screenshotDirectory _animator viewerVersion - |> ProvenanceApp.emptyWithModel + |> ProvenanceApp.emptyWithModel enableProvenance |> ViewerIO.loadRoverData let app = { diff --git a/src/PRo3D.Viewer/Viewer/ViewerLenses.fs b/src/PRo3D.Viewer/Viewer/ViewerLenses.fs index ee656c1d..2c6d3900 100644 --- a/src/PRo3D.Viewer/Viewer/ViewerLenses.fs +++ b/src/PRo3D.Viewer/Viewer/ViewerLenses.fs @@ -110,7 +110,7 @@ module ViewerLenses = let scaleBars = // check scale bars; using old segments for performance reasons if haveSameKeys state.stateScaleBars.scaleBars m.scene.scaleBars.scaleBars then - let inline update (newBar : ScaleBar) = + let inline update (newBar : ScaleVisualization) = let current = HashMap.tryFind newBar.guid m.scene.scaleBars.scaleBars match current with | Some current ->