From 42fe9f81b0def7a0c30dc61b09f85d6745e96772 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 13:24:49 +0100 Subject: [PATCH 01/26] gizmos: add basic widget and api design --- ExtraWidgets.go | 10 +++++++++- Gizmo.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ MasterWindow.go | 3 +++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 Gizmo.go diff --git a/ExtraWidgets.go b/ExtraWidgets.go index e6f7134c..fe43ef01 100644 --- a/ExtraWidgets.go +++ b/ExtraWidgets.go @@ -112,7 +112,11 @@ func (h *SplitterWidget) Build() { canvas.AddRectFilled(pt.Add(ptMin), pt.Add(ptMax), c, 0, 0) } -var _ Widget = &CustomWidget{} +var ( + _ Widget = &CustomWidget{} + _ PlotWidget = &CustomWidget{} + _ GizmoI = &CustomWidget{} +) // CustomWidget allows you to do whatever you want. // This includes: @@ -142,6 +146,10 @@ func (c *CustomWidget) Plot() { c.Build() } +func (c *CustomWidget) Gizmo() { + c.Build() +} + var _ Widget = &ConditionWidget{} // ConditionWidget allows to build if a condition is met diff --git a/Gizmo.go b/Gizmo.go new file mode 100644 index 00000000..a3758f65 --- /dev/null +++ b/Gizmo.go @@ -0,0 +1,46 @@ +package giu + +import "github.com/AllenDang/cimgui-go/imguizmo" + +// GizmoI should be implemented by every sub-element of GizmoWidget. +type GizmoI interface { + Gizmo() +} + +var _ Widget = &GizmoWidget{} + +// GizmoWidget implement ImGuizmo features. +// It is designed just like PlotWidget. +// This structure provides an "area" where you can put Gizmos (see (*GizmoWidget).Gizmos). +type GizmoWidget struct { + gizmos []GizmoI +} + +// Gizmo creates a new GizmoWidget. +func Gizmo() *GizmoWidget { + return &GizmoWidget{ + gizmos: []GizmoI{}, + } +} + +func (g *GizmoWidget) Gizmos(gizmos ...GizmoI) *GizmoWidget { + g.gizmos = append(g.gizmos, gizmos...) + return g +} + +func (g *GizmoWidget) build() { + for _, gizmo := range g.gizmos { + gizmo.Gizmo() + } +} + +// Build implements Widget interface. +func (g *GizmoWidget) Build() { + imguizmo.SetDrawlist() + g.build() +} + +// Global works like Build() but does not attach the gizmo to the current window. +func (g *GizmoWidget) Global() { + g.build() +} diff --git a/MasterWindow.go b/MasterWindow.go index af5d2526..b65ccede 100644 --- a/MasterWindow.go +++ b/MasterWindow.go @@ -9,6 +9,7 @@ import ( "github.com/AllenDang/cimgui-go/backend" "github.com/AllenDang/cimgui-go/backend/glfwbackend" "github.com/AllenDang/cimgui-go/imgui" + "github.com/AllenDang/cimgui-go/imguizmo" "github.com/AllenDang/cimgui-go/imnodes" "github.com/AllenDang/cimgui-go/implot" "golang.org/x/image/colornames" @@ -230,6 +231,8 @@ func (w *MasterWindow) beforeDestroy() { } func (w *MasterWindow) render() { + imguizmo.BeginFrame() + Context.cleanStates() defer Context.SetDirty() From e4814bbd9643d26f7fac448e24619e51d80a9074 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 13:25:00 +0100 Subject: [PATCH 02/26] examples: add gizmo example --- examples/gizmo/main.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 examples/gizmo/main.go diff --git a/examples/gizmo/main.go b/examples/gizmo/main.go new file mode 100644 index 00000000..9c2ab8a5 --- /dev/null +++ b/examples/gizmo/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + + "github.com/AllenDang/giu" +) + +func loop() { + giu.Gizmo().Gizmos(giu.Custom(func() { + fmt.Println("Hello world from global gizmos") + })).Global() + + giu.Window("Gizmo demo").Layout( + giu.Gizmo().Gizmos( + giu.Custom(func() { + fmt.Println("Hello world from window gizmos") + }), + ), + ) +} + +func main() { + wnd := giu.NewMasterWindow("Gizmo (ImGuizmo) demo", 1280, 720, 0) + wnd.Run(loop) +} From 5369a080c820b7f0d18bd3c6fd4b3977e5a2649e Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 18:39:53 +0100 Subject: [PATCH 03/26] update gizmo things - add CubeGizmo and GridGizmo --- ExtraWidgets.go | 2 +- Gizmo.go | 204 +++++++++++++++++++++++++++++++++++++++-- examples/gizmo/main.go | 70 ++++++++++++-- 3 files changed, 262 insertions(+), 14 deletions(-) diff --git a/ExtraWidgets.go b/ExtraWidgets.go index fe43ef01..e1fd845c 100644 --- a/ExtraWidgets.go +++ b/ExtraWidgets.go @@ -146,7 +146,7 @@ func (c *CustomWidget) Plot() { c.Build() } -func (c *CustomWidget) Gizmo() { +func (c *CustomWidget) Gizmo(_, _ *HumanReadableMatrix) { c.Build() } diff --git a/Gizmo.go b/Gizmo.go index a3758f65..38533aa3 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -1,10 +1,14 @@ package giu -import "github.com/AllenDang/cimgui-go/imguizmo" +import ( + "github.com/AllenDang/cimgui-go/imgui" + "github.com/AllenDang/cimgui-go/imguizmo" + "github.com/AllenDang/cimgui-go/utils" +) // GizmoI should be implemented by every sub-element of GizmoWidget. type GizmoI interface { - Gizmo() + Gizmo(view, projection *HumanReadableMatrix) } var _ Widget = &GizmoWidget{} @@ -13,13 +17,16 @@ var _ Widget = &GizmoWidget{} // It is designed just like PlotWidget. // This structure provides an "area" where you can put Gizmos (see (*GizmoWidget).Gizmos). type GizmoWidget struct { - gizmos []GizmoI + gizmos []GizmoI + view, projection *HumanReadableMatrix } // Gizmo creates a new GizmoWidget. -func Gizmo() *GizmoWidget { +func Gizmo(view, projection *HumanReadableMatrix) *GizmoWidget { return &GizmoWidget{ - gizmos: []GizmoI{}, + gizmos: []GizmoI{}, + view: view, + projection: projection, } } @@ -30,13 +37,15 @@ func (g *GizmoWidget) Gizmos(gizmos ...GizmoI) *GizmoWidget { func (g *GizmoWidget) build() { for _, gizmo := range g.gizmos { - gizmo.Gizmo() + gizmo.Gizmo(g.view, g.projection) } } // Build implements Widget interface. func (g *GizmoWidget) Build() { imguizmo.SetDrawlist() + displaySize := imgui.CurrentIO().DisplaySize() + imguizmo.SetRect(0, 0, displaySize.X, displaySize.Y) g.build() } @@ -44,3 +53,186 @@ func (g *GizmoWidget) Build() { func (g *GizmoWidget) Global() { g.build() } + +// [Gizmos] + +var _ GizmoI = &GridGizmo{} + +// GridGizmo draws a grid in the gizmo area. +type GridGizmo struct { + // default to Identity + matrix *HumanReadableMatrix + thickness float32 +} + +func Grid() *GridGizmo { + return &GridGizmo{ + matrix: IdentityMatrix(), + thickness: 10, + } +} + +func (g *GridGizmo) Gizmo(view, projection *HumanReadableMatrix) { + imguizmo.DrawGrid( + view.Matrix(), + projection.Matrix(), + g.matrix.Matrix(), + g.thickness, + ) +} + +// CubeGizmo draws a 3D cube in the gizmo area. +// View and Projection matrices are provided by GizmoWidget. +type CubeGizmo struct { + matrix *HumanReadableMatrix +} + +func Cube(matrix *HumanReadableMatrix) *CubeGizmo { + return &CubeGizmo{ + matrix: matrix, + } +} + +// Gizmo implements GizmoI interface. +func (c *CubeGizmo) Gizmo(view, projection *HumanReadableMatrix) { + imguizmo.DrawCubes( + view.Matrix(), + projection.Matrix(), + c.matrix.Matrix(), + 1, + ) +} + +// [Gizmo helpers] + +// HumanReadableMatrix is a suitable thing here. +// It makes it even possible to use gizmos. +// Recommended use is presented in examples/gizmo +// NOTE: You are supposed to allocate this with NewHumanReadableMatrix (do not use zero value)!!! +type HumanReadableMatrix struct { + transform []float32 // supposed len is 3 + rotation []float32 // supposed len is 3 + scale []float32 // supposed len is 3 + matrix []float32 // supposed len is 16 + dirty bool +} + +func NewHumanReadableMatrix() *HumanReadableMatrix { + return &HumanReadableMatrix{ + transform: make([]float32, 3), + rotation: make([]float32, 3), + scale: make([]float32, 3), + matrix: make([]float32, 16), + dirty: true, + } +} + +func IdentityMatrix() *HumanReadableMatrix { + r := NewHumanReadableMatrix() + r.matrix = []float32{ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + } + + r.Decompile() + r.dirty = false + + return r +} + +func (m *HumanReadableMatrix) Transform(x, y, z float32) *HumanReadableMatrix { + m.transform[0] = x + m.transform[1] = y + m.transform[2] = z + m.dirty = true + return m +} + +func (m *HumanReadableMatrix) Rotation(x, y, z float32) *HumanReadableMatrix { + m.rotation[0] = x + m.rotation[1] = y + m.rotation[2] = z + m.dirty = true + return m +} + +func (m *HumanReadableMatrix) Scale(x, y, z float32) *HumanReadableMatrix { + m.scale[0] = x + m.scale[1] = y + m.scale[2] = z + m.dirty = true + return m +} + +func (m *HumanReadableMatrix) SetMatrix(f []float32) *HumanReadableMatrix { + m.matrix = f + m.Decompile() + m.dirty = false + return m +} + +// Compile updates m.Matrix +// NOTE: this supposes matrix was allocated correctly! +func (m *HumanReadableMatrix) Compile() { + imguizmo.RecomposeMatrixFromComponents( + utils.SliceToPtr(m.transform), + utils.SliceToPtr(m.rotation), + utils.SliceToPtr(m.scale), + utils.SliceToPtr(m.matrix), + ) + + m.dirty = false +} + +func (m *HumanReadableMatrix) Decompile() { + imguizmo.DecomposeMatrixToComponents( + utils.SliceToPtr(m.matrix), + utils.SliceToPtr(m.transform), + utils.SliceToPtr(m.rotation), + utils.SliceToPtr(m.scale), + ) +} + +func (m *HumanReadableMatrix) GetTransform() []float32 { + if m.dirty { + m.Compile() + } + + return m.transform +} + +func (m *HumanReadableMatrix) GetRotation() []float32 { + if m.dirty { + m.Compile() + } + + return m.rotation +} + +func (m *HumanReadableMatrix) GetScale() []float32 { + if m.dirty { + m.Compile() + } + + return m.scale +} + +// Matrix returns current matrix compatible with ImGuizmo (pointer to 4x4m). +// It recompiles as necessary. +func (m *HumanReadableMatrix) Matrix() *float32 { + if m.dirty { + m.Compile() + } + + return utils.SliceToPtr(m.matrix) +} + +func (m *HumanReadableMatrix) MatrixSlice() []float32 { + if m.dirty { + m.Compile() + } + + return m.matrix +} diff --git a/examples/gizmo/main.go b/examples/gizmo/main.go index 9c2ab8a5..9d815dc0 100644 --- a/examples/gizmo/main.go +++ b/examples/gizmo/main.go @@ -1,20 +1,76 @@ package main import ( - "fmt" - + "github.com/AllenDang/cimgui-go/imguizmo" "github.com/AllenDang/giu" ) +var ( + view = giu.NewHumanReadableMatrix(). + Transform(0, 0, -7). + Rotation(10, 5, 0). + Scale(1, 1, 1) + + projection = giu.NewHumanReadableMatrix().SetMatrix([]float32{ + 2.3787, 0, 0, 0, + 0, 3.1716, 0, 0, + 0, 0, -1.0002, -1, + 0, 0, -0.2, 0, + }) + + cube = giu.NewHumanReadableMatrix(). + Transform(0.5, 0.5, 0.5). + Rotation(0, 0, 0). + Scale(1, 1, 1) + + zmoOP = int32(imguizmo.TRANSLATE) + zmoMODE = int32(imguizmo.LOCAL) + + Bounds = []float32{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5} + + // GizmoControls can be enabled in editor and allows mouse control over gizmo + GizmoControls bool + UsingGizmo bool +) + +func gizmos() []giu.GizmoI { + return []giu.GizmoI{ + giu.Grid(), + giu.Cube(cube), + giu.Custom(func() { + /* + imguizmo.ManipulateV( + //&(View[0]), + view.Matrix(), + projection.Matrix(), + imguizmo.OPERATION(zmoOP), + imguizmo.MODE(zmoMODE), + cube.Matrix(), + nil, nil, + nil, + nil) + */ + + /* + imguizmo.ViewManipulateFloat( + view.Matrix(), + 1, + imgui.Vec2{128, 128}, + imgui.Vec2{128, 128}, + 0x01010101, + ) + */ + }), + } +} + func loop() { - giu.Gizmo().Gizmos(giu.Custom(func() { - fmt.Println("Hello world from global gizmos") - })).Global() + giu.Gizmo(view, projection).Gizmos(gizmos()...).Global() giu.Window("Gizmo demo").Layout( - giu.Gizmo().Gizmos( + giu.Gizmo(view, projection).Gizmos( giu.Custom(func() { - fmt.Println("Hello world from window gizmos") + // fmt.Println("Hello world from window gizmos") }), ), ) From fb155e94d51baa51d12b1fd45c2eed3c0bcbd73f Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 18:50:43 +0100 Subject: [PATCH 04/26] gizmo: add manipulate gizmo --- Gizmo.go | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/Gizmo.go b/Gizmo.go index 38533aa3..579e2d88 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -6,6 +6,10 @@ import ( "github.com/AllenDang/cimgui-go/utils" ) +type GizmoOperation int + +type GizmoMode int + // GizmoI should be implemented by every sub-element of GizmoWidget. type GizmoI interface { Gizmo(view, projection *HumanReadableMatrix) @@ -84,7 +88,8 @@ func (g *GridGizmo) Gizmo(view, projection *HumanReadableMatrix) { // CubeGizmo draws a 3D cube in the gizmo area. // View and Projection matrices are provided by GizmoWidget. type CubeGizmo struct { - matrix *HumanReadableMatrix + matrix *HumanReadableMatrix + manipulate bool } func Cube(matrix *HumanReadableMatrix) *CubeGizmo { @@ -93,6 +98,12 @@ func Cube(matrix *HumanReadableMatrix) *CubeGizmo { } } +// Manipulate adds ManipulateGizmo to the CubeGizmo. +func (c *CubeGizmo) Manipulate() *CubeGizmo { + c.manipulate = true + return c +} + // Gizmo implements GizmoI interface. func (c *CubeGizmo) Gizmo(view, projection *HumanReadableMatrix) { imguizmo.DrawCubes( @@ -101,6 +112,39 @@ func (c *CubeGizmo) Gizmo(view, projection *HumanReadableMatrix) { c.matrix.Matrix(), 1, ) + + if c.manipulate { + Manipulate(c.matrix).Gizmo(view, projection) + } +} + +type ManipulateGizmo struct { + matrix *HumanReadableMatrix + operation GizmoOperation + mode GizmoMode +} + +// Manipulate creates a new ManipulateGizmo. +func Manipulate(matrix *HumanReadableMatrix) *ManipulateGizmo { + return &ManipulateGizmo{ + matrix: matrix, + mode: GizmoMode(imguizmo.LOCAL), + operation: GizmoOperation(imguizmo.TRANSLATE), + } +} + +// Gizmo implements GizmoI interface. +func (m *ManipulateGizmo) Gizmo(view, projection *HumanReadableMatrix) { + imguizmo.ManipulateV( + view.Matrix(), + projection.Matrix(), + imguizmo.OPERATION(m.operation), + imguizmo.MODE(m.mode), + m.matrix.Matrix(), + nil, // this is deltaMatrix (Can't see usecase for now) + nil, // snap idk what is this + nil, // localBounds idk what is this + nil) // boundsSnap idk what is this } // [Gizmo helpers] From 549ff8ad6bc990a469d861b46273f0689d55d5f1 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 19:10:19 +0100 Subject: [PATCH 05/26] Gizmo: add comments --- Gizmo.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Gizmo.go b/Gizmo.go index 579e2d88..72f830db 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -20,6 +20,12 @@ var _ Widget = &GizmoWidget{} // GizmoWidget implement ImGuizmo features. // It is designed just like PlotWidget. // This structure provides an "area" where you can put Gizmos (see (*GizmoWidget).Gizmos). +// If you wnat to have more understanding about what is going on here, read this: +// https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ (DISCLAIMER: giu authors are not responsible if you get mad or something!) +// TODO: grid thickness +// TODO: Manipulate mode and operation +// TODO: ViewManipulate +// TODO: ProjectionMatrix edition (see https://github.com/jbowtie/glm-go) type GizmoWidget struct { gizmos []GizmoI view, projection *HumanReadableMatrix @@ -34,11 +40,14 @@ func Gizmo(view, projection *HumanReadableMatrix) *GizmoWidget { } } +// Gizmos adds GizmoI elements to the GizmoWidget area. func (g *GizmoWidget) Gizmos(gizmos ...GizmoI) *GizmoWidget { g.gizmos = append(g.gizmos, gizmos...) return g } +// build is a local build function. +// Just to separate Global() and Build() methods. func (g *GizmoWidget) build() { for _, gizmo := range g.gizmos { gizmo.Gizmo(g.view, g.projection) @@ -69,6 +78,7 @@ type GridGizmo struct { thickness float32 } +// Grid creates a new GridGizmo. func Grid() *GridGizmo { return &GridGizmo{ matrix: IdentityMatrix(), @@ -76,6 +86,7 @@ func Grid() *GridGizmo { } } +// Gizmo implements GizmoI interface. func (g *GridGizmo) Gizmo(view, projection *HumanReadableMatrix) { imguizmo.DrawGrid( view.Matrix(), @@ -92,6 +103,7 @@ type CubeGizmo struct { manipulate bool } +// Cube creates a new CubeGizmo. func Cube(matrix *HumanReadableMatrix) *CubeGizmo { return &CubeGizmo{ matrix: matrix, @@ -118,6 +130,9 @@ func (c *CubeGizmo) Gizmo(view, projection *HumanReadableMatrix) { } } +// ManipulateGizmo is a gizmo that allows you to "visually manipulate a matrix". +// It can be attached to another Gizmo (e.g. CubeGizmo) and will allow to move/rotate/scale it. +// See (*CubeGizmo).Manipulate() method. type ManipulateGizmo struct { matrix *HumanReadableMatrix operation GizmoOperation From 3c8da73c034f3f60910075f9cf4e96d21e06a03c Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 19:16:07 +0100 Subject: [PATCH 06/26] gizmos: add grid thickness --- Gizmo.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Gizmo.go b/Gizmo.go index 72f830db..068e1eac 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -17,12 +17,11 @@ type GizmoI interface { var _ Widget = &GizmoWidget{} -// GizmoWidget implement ImGuizmo features. +// GizmoWidget implements ImGuizmo features. // It is designed just like PlotWidget. // This structure provides an "area" where you can put Gizmos (see (*GizmoWidget).Gizmos). // If you wnat to have more understanding about what is going on here, read this: -// https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ (DISCLAIMER: giu authors are not responsible if you get mad or something!) -// TODO: grid thickness +// https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ (DISCLAIMER: giu authors are not responsible if you go mad or something!) // TODO: Manipulate mode and operation // TODO: ViewManipulate // TODO: ProjectionMatrix edition (see https://github.com/jbowtie/glm-go) @@ -86,6 +85,12 @@ func Grid() *GridGizmo { } } +// Thickness sets a thickness of grid lines. +func (g *GridGizmo) Thickness(t float32) *GridGizmo { + g.thickness = t + return g +} + // Gizmo implements GizmoI interface. func (g *GridGizmo) Gizmo(view, projection *HumanReadableMatrix) { imguizmo.DrawGrid( From f45cf38b06fba43beca8eea90e462036ab45516b Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 19:22:31 +0100 Subject: [PATCH 07/26] Gizmos: handle positions/sizes correctly --- Gizmo.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Gizmo.go b/Gizmo.go index 068e1eac..3e7e7b2f 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -56,13 +56,17 @@ func (g *GizmoWidget) build() { // Build implements Widget interface. func (g *GizmoWidget) Build() { imguizmo.SetDrawlist() - displaySize := imgui.CurrentIO().DisplaySize() - imguizmo.SetRect(0, 0, displaySize.X, displaySize.Y) + displaySize := imgui.ContentRegionAvail() + pos0 := imgui.CursorScreenPos() + imguizmo.SetRect(pos0.X, pos0.Y, displaySize.X, displaySize.Y) g.build() } // Global works like Build() but does not attach the gizmo to the current window. func (g *GizmoWidget) Global() { + displaySize := imgui.CurrentIO().DisplaySize() + pos0 := imgui.MainViewport().Pos() + imguizmo.SetRect(pos0.X, pos0.Y, displaySize.X, displaySize.Y) g.build() } From 9af76dbbf944349c3dd9b1bea6e82e57a7e9bfa9 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 19:29:16 +0100 Subject: [PATCH 08/26] update example --- examples/gizmo/main.go | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/examples/gizmo/main.go b/examples/gizmo/main.go index 9d815dc0..ade3955f 100644 --- a/examples/gizmo/main.go +++ b/examples/gizmo/main.go @@ -1,6 +1,8 @@ package main import ( + "fmt" + "github.com/AllenDang/cimgui-go/imguizmo" "github.com/AllenDang/giu" ) @@ -36,21 +38,10 @@ var ( func gizmos() []giu.GizmoI { return []giu.GizmoI{ giu.Grid(), - giu.Cube(cube), + giu.Cube(cube), //.Manipulate(), + giu.Manipulate(cube), giu.Custom(func() { - /* - imguizmo.ManipulateV( - //&(View[0]), - view.Matrix(), - projection.Matrix(), - imguizmo.OPERATION(zmoOP), - imguizmo.MODE(zmoMODE), - cube.Matrix(), - nil, nil, - nil, - nil) - */ - + fmt.Println(cube) /* imguizmo.ViewManipulateFloat( view.Matrix(), @@ -69,9 +60,7 @@ func loop() { giu.Window("Gizmo demo").Layout( giu.Gizmo(view, projection).Gizmos( - giu.Custom(func() { - // fmt.Println("Hello world from window gizmos") - }), + gizmos()..., ), ) } From d59df04f1161fd43c9005c64a23c9352779410a8 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 22:21:58 +0100 Subject: [PATCH 09/26] gizmo: add mode and operation --- Gizmo.go | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/Gizmo.go b/Gizmo.go index 3e7e7b2f..e5e8833c 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -6,10 +6,47 @@ import ( "github.com/AllenDang/cimgui-go/utils" ) +// GizmoOperation specifies the operation of Gizmo (used by manipulate). type GizmoOperation int +// Possible Operations +const ( + OperationTranslateX GizmoOperation = GizmoOperation(imguizmo.TRANSLATEX) + OperationTranslateY GizmoOperation = GizmoOperation(imguizmo.TRANSLATEY) + OperationTranslateZ GizmoOperation = GizmoOperation(imguizmo.TRANSLATEZ) + OperationTranslate GizmoOperation = GizmoOperation(imguizmo.TRANSLATE) + + OperationRotateX GizmoOperation = GizmoOperation(imguizmo.ROTATEX) + OperationRotateY GizmoOperation = GizmoOperation(imguizmo.ROTATEY) + OperationRotateZ GizmoOperation = GizmoOperation(imguizmo.ROTATEZ) + OperationRotate GizmoOperation = GizmoOperation(imguizmo.ROTATE) + + OperationScaleX GizmoOperation = GizmoOperation(imguizmo.SCALEX) + OperationScaleY GizmoOperation = GizmoOperation(imguizmo.SCALEY) + OperationScaleZ GizmoOperation = GizmoOperation(imguizmo.SCALEZ) + OperationScale GizmoOperation = GizmoOperation(imguizmo.SCALE) + + OperationScaleXU GizmoOperation = GizmoOperation(imguizmo.SCALEXU) + OperationScaleYU GizmoOperation = GizmoOperation(imguizmo.SCALEYU) + OperationScaleZU GizmoOperation = GizmoOperation(imguizmo.SCALEZU) + OperationScaleU GizmoOperation = GizmoOperation(imguizmo.SCALEU) + + OperationBounds GizmoOperation = GizmoOperation(imguizmo.BOUNDS) + + OperationRotateScreen GizmoOperation = GizmoOperation(imguizmo.ROTATESCREEN) + + OperationUniversal GizmoOperation = GizmoOperation(imguizmo.UNIVERSAL) +) + +// GizmoMode specifies the mode of Gizmo (used by manipulate). type GizmoMode int +// values are not explained in source code +const ( + ModeLocal GizmoMode = GizmoMode(imguizmo.LOCAL) + ModeWorld GizmoMode = GizmoMode(imguizmo.WORLD) +) + // GizmoI should be implemented by every sub-element of GizmoWidget. type GizmoI interface { Gizmo(view, projection *HumanReadableMatrix) @@ -22,7 +59,6 @@ var _ Widget = &GizmoWidget{} // This structure provides an "area" where you can put Gizmos (see (*GizmoWidget).Gizmos). // If you wnat to have more understanding about what is going on here, read this: // https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ (DISCLAIMER: giu authors are not responsible if you go mad or something!) -// TODO: Manipulate mode and operation // TODO: ViewManipulate // TODO: ProjectionMatrix edition (see https://github.com/jbowtie/glm-go) type GizmoWidget struct { From cfb8ed76ee477a015702525f858345878f0eb737 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 22:51:07 +0100 Subject: [PATCH 10/26] gizmo: add ViewManipulate --- Gizmo.go | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/Gizmo.go b/Gizmo.go index e5e8833c..1fb222c8 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -1,6 +1,8 @@ package giu import ( + "image/color" + "github.com/AllenDang/cimgui-go/imgui" "github.com/AllenDang/cimgui-go/imguizmo" "github.com/AllenDang/cimgui-go/utils" @@ -59,7 +61,6 @@ var _ Widget = &GizmoWidget{} // This structure provides an "area" where you can put Gizmos (see (*GizmoWidget).Gizmos). // If you wnat to have more understanding about what is going on here, read this: // https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ (DISCLAIMER: giu authors are not responsible if you go mad or something!) -// TODO: ViewManipulate // TODO: ProjectionMatrix edition (see https://github.com/jbowtie/glm-go) type GizmoWidget struct { gizmos []GizmoI @@ -207,6 +208,47 @@ func (m *ManipulateGizmo) Gizmo(view, projection *HumanReadableMatrix) { nil) // boundsSnap idk what is this } +type ViewManipulateGizmo struct { + position imgui.Vec2 + size imgui.Vec2 + color uint32 +} + +func ViewManipulate() *ViewManipulateGizmo { + return &ViewManipulateGizmo{ + position: imgui.Vec2{128, 128}, + size: imgui.Vec2{128, 128}, + } +} + +// Position sets the position of the gizmo. +func (v *ViewManipulateGizmo) Position(x, y float32) *ViewManipulateGizmo { + v.position = imgui.Vec2{x, y} + return v +} + +// Size sets the size of the gizmo. +func (v *ViewManipulateGizmo) Size(x, y float32) *ViewManipulateGizmo { + v.size = imgui.Vec2{x, y} + return v +} + +func (v *ViewManipulateGizmo) Color(c color.Color) *ViewManipulateGizmo { + v.color = ColorToUint(c) + return v +} + +// Gizmo implements GizmoI interface. +func (v *ViewManipulateGizmo) Gizmo(view, projection *HumanReadableMatrix) { + imguizmo.ViewManipulateFloat( + view.Matrix(), + 1, + v.position, + v.size, + v.color, + ) +} + // [Gizmo helpers] // HumanReadableMatrix is a suitable thing here. From b0a2a50d51cc71bbd815061f80be8923aa00747d Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 22:51:33 +0100 Subject: [PATCH 11/26] examples/gizmo: update exmple --- examples/gizmo/main.go | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/examples/gizmo/main.go b/examples/gizmo/main.go index ade3955f..429df895 100644 --- a/examples/gizmo/main.go +++ b/examples/gizmo/main.go @@ -1,7 +1,7 @@ package main import ( - "fmt" + "image/color" "github.com/AllenDang/cimgui-go/imguizmo" "github.com/AllenDang/giu" @@ -38,20 +38,15 @@ var ( func gizmos() []giu.GizmoI { return []giu.GizmoI{ giu.Grid(), - giu.Cube(cube), //.Manipulate(), - giu.Manipulate(cube), - giu.Custom(func() { - fmt.Println(cube) - /* - imguizmo.ViewManipulateFloat( - view.Matrix(), - 1, - imgui.Vec2{128, 128}, - imgui.Vec2{128, 128}, - 0x01010101, - ) - */ - }), + giu.Cube(cube).Manipulate(), + giu.ViewManipulate().Color( + color.RGBA{ + R: 45, + G: 15, + B: 121, + A: 255, + }, + ), } } From 220152085436508048079aa30da810d6559fa521 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 23:27:47 +0100 Subject: [PATCH 12/26] gizmos: implement projection matrix --- ExtraWidgets.go | 2 +- Gizmo.go | 89 ++++++++++++++++++++++++++++++++++++++++++++----- Utils.go | 5 +++ go.mod | 5 ++- go.sum | 2 ++ 5 files changed, 90 insertions(+), 13 deletions(-) diff --git a/ExtraWidgets.go b/ExtraWidgets.go index e1fd845c..44a0152a 100644 --- a/ExtraWidgets.go +++ b/ExtraWidgets.go @@ -146,7 +146,7 @@ func (c *CustomWidget) Plot() { c.Build() } -func (c *CustomWidget) Gizmo(_, _ *HumanReadableMatrix) { +func (c *CustomWidget) Gizmo(_ *HumanReadableMatrix, _ *ProjectionMatrix) { c.Build() } diff --git a/Gizmo.go b/Gizmo.go index 1fb222c8..9d8bba21 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -6,6 +6,7 @@ import ( "github.com/AllenDang/cimgui-go/imgui" "github.com/AllenDang/cimgui-go/imguizmo" "github.com/AllenDang/cimgui-go/utils" + glm "github.com/gucio321/glm-go" ) // GizmoOperation specifies the operation of Gizmo (used by manipulate). @@ -51,7 +52,7 @@ const ( // GizmoI should be implemented by every sub-element of GizmoWidget. type GizmoI interface { - Gizmo(view, projection *HumanReadableMatrix) + Gizmo(view *HumanReadableMatrix, projection *ProjectionMatrix) } var _ Widget = &GizmoWidget{} @@ -61,14 +62,14 @@ var _ Widget = &GizmoWidget{} // This structure provides an "area" where you can put Gizmos (see (*GizmoWidget).Gizmos). // If you wnat to have more understanding about what is going on here, read this: // https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ (DISCLAIMER: giu authors are not responsible if you go mad or something!) -// TODO: ProjectionMatrix edition (see https://github.com/jbowtie/glm-go) type GizmoWidget struct { - gizmos []GizmoI - view, projection *HumanReadableMatrix + gizmos []GizmoI + view *HumanReadableMatrix + projection *ProjectionMatrix } // Gizmo creates a new GizmoWidget. -func Gizmo(view, projection *HumanReadableMatrix) *GizmoWidget { +func Gizmo(view *HumanReadableMatrix, projection *ProjectionMatrix) *GizmoWidget { return &GizmoWidget{ gizmos: []GizmoI{}, view: view, @@ -133,7 +134,7 @@ func (g *GridGizmo) Thickness(t float32) *GridGizmo { } // Gizmo implements GizmoI interface. -func (g *GridGizmo) Gizmo(view, projection *HumanReadableMatrix) { +func (g *GridGizmo) Gizmo(view *HumanReadableMatrix, projection *ProjectionMatrix) { imguizmo.DrawGrid( view.Matrix(), projection.Matrix(), @@ -142,6 +143,8 @@ func (g *GridGizmo) Gizmo(view, projection *HumanReadableMatrix) { ) } +var _ GizmoI = &CubeGizmo{} + // CubeGizmo draws a 3D cube in the gizmo area. // View and Projection matrices are provided by GizmoWidget. type CubeGizmo struct { @@ -163,7 +166,7 @@ func (c *CubeGizmo) Manipulate() *CubeGizmo { } // Gizmo implements GizmoI interface. -func (c *CubeGizmo) Gizmo(view, projection *HumanReadableMatrix) { +func (c *CubeGizmo) Gizmo(view *HumanReadableMatrix, projection *ProjectionMatrix) { imguizmo.DrawCubes( view.Matrix(), projection.Matrix(), @@ -176,6 +179,8 @@ func (c *CubeGizmo) Gizmo(view, projection *HumanReadableMatrix) { } } +var _ GizmoI = &ManipulateGizmo{} + // ManipulateGizmo is a gizmo that allows you to "visually manipulate a matrix". // It can be attached to another Gizmo (e.g. CubeGizmo) and will allow to move/rotate/scale it. // See (*CubeGizmo).Manipulate() method. @@ -195,7 +200,7 @@ func Manipulate(matrix *HumanReadableMatrix) *ManipulateGizmo { } // Gizmo implements GizmoI interface. -func (m *ManipulateGizmo) Gizmo(view, projection *HumanReadableMatrix) { +func (m *ManipulateGizmo) Gizmo(view *HumanReadableMatrix, projection *ProjectionMatrix) { imguizmo.ManipulateV( view.Matrix(), projection.Matrix(), @@ -208,6 +213,8 @@ func (m *ManipulateGizmo) Gizmo(view, projection *HumanReadableMatrix) { nil) // boundsSnap idk what is this } +var _ GizmoI = &ViewManipulateGizmo{} + type ViewManipulateGizmo struct { position imgui.Vec2 size imgui.Vec2 @@ -239,7 +246,7 @@ func (v *ViewManipulateGizmo) Color(c color.Color) *ViewManipulateGizmo { } // Gizmo implements GizmoI interface. -func (v *ViewManipulateGizmo) Gizmo(view, projection *HumanReadableMatrix) { +func (v *ViewManipulateGizmo) Gizmo(view *HumanReadableMatrix, projection *ProjectionMatrix) { imguizmo.ViewManipulateFloat( view.Matrix(), 1, @@ -382,3 +389,67 @@ func (m *HumanReadableMatrix) MatrixSlice() []float32 { return m.matrix } + +// ref: https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/#the-projection-matrix +type ProjectionMatrix struct { + // The vertical Field of View, in radians: the amount of "zoom". Think "camera lens". Usually between 90° (extra wide) and 30° (quite zoomed in) + // This value is in radians! + fov float32 + // Aspect Ratio. Depends on the size of your window. Notice that 4/3 == 800/600 == 1280/960, sounds familiar? + aspect float32 + // Near clipping plane. Keep as big as possible, or you'll get precision issues. + nearClipping float32 + // Far clipping plane. Keep as little as possible. + farClipping float32 + + dirty bool + matrix []float32 +} + +func NewProjectionMatrix() *ProjectionMatrix { + return &ProjectionMatrix{ + fov: Deg2Rad(45), + aspect: 3.0 / 4.0, + nearClipping: 0.1, + farClipping: 100.0, + dirty: true, + matrix: make([]float32, 16), + } +} + +func (p *ProjectionMatrix) FOV(fov float32) *ProjectionMatrix { + p.fov = fov + p.dirty = true + return p +} + +func (p *ProjectionMatrix) Aspect(aspect float32) *ProjectionMatrix { + p.aspect = aspect + p.dirty = true + return p +} + +func (p *ProjectionMatrix) NearClipping(near float32) *ProjectionMatrix { + p.nearClipping = near + p.dirty = true + return p +} + +func (p *ProjectionMatrix) FarClipping(far float32) *ProjectionMatrix { + p.farClipping = far + p.dirty = true + return p +} + +func (p *ProjectionMatrix) Matrix() *float32 { + if p.dirty { + p.Compile() + } + + return utils.SliceToPtr(p.matrix) +} + +func (p *ProjectionMatrix) Compile() { + p.matrix = glm.MatrixPerspective(p.fov, p.aspect, p.nearClipping, p.farClipping) + p.dirty = false +} diff --git a/Utils.go b/Utils.go index f6330945..5adfcc37 100644 --- a/Utils.go +++ b/Utils.go @@ -267,3 +267,8 @@ func UintToColor(col uint32) *color.RGBA { A: a, } } + +// Deg2Rad converts degrees to radians. +func Deg2Rad(deg float32) float32 { + return deg * 0.01745329252 // deg * 2pi / 360 +} diff --git a/go.mod b/go.mod index 8818ab7f..f0fa7835 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ module github.com/AllenDang/giu -go 1.22.0 - -toolchain go1.23.1 +go 1.23.2 require ( github.com/AllenDang/cimgui-go v1.1.0 @@ -20,6 +18,7 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gucio321/glm-go v0.0.0-20241029220517-e1b5a3e011c8 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect golang.design/x/mainthread v0.3.0 // indirect diff --git a/go.sum b/go.sum index aae7f016..290dba3d 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 h1:baVdMKlASEHrj19iqjARrPbaRisD7EuZEVJj6ZMLl1Q= github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3/go.mod h1:VEPNJUlxl5KdWjDvz6Q1l+rJlxF2i6xqDeGuGAxa87M= +github.com/gucio321/glm-go v0.0.0-20241029220517-e1b5a3e011c8 h1:aczNwZRrReVWrZcqxvDjDmxP1NFISTAu+1Cp+3OCbUg= +github.com/gucio321/glm-go v0.0.0-20241029220517-e1b5a3e011c8/go.mod h1:Z3+NtD1rjXUVZg97dojhs70i5oneOrZ1xcFKfF/c2Ts= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/mazznoer/csscolorparser v0.1.5 h1:Wr4uNIE+pHWN3TqZn2SGpA2nLRG064gB7WdSfSS5cz4= From 97938331389c0cecbf88a1e2836d95dae94855d3 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Tue, 29 Oct 2024 23:27:56 +0100 Subject: [PATCH 13/26] update example --- examples/gizmo/main.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/examples/gizmo/main.go b/examples/gizmo/main.go index 429df895..0d028d88 100644 --- a/examples/gizmo/main.go +++ b/examples/gizmo/main.go @@ -13,12 +13,9 @@ var ( Rotation(10, 5, 0). Scale(1, 1, 1) - projection = giu.NewHumanReadableMatrix().SetMatrix([]float32{ - 2.3787, 0, 0, 0, - 0, 3.1716, 0, 0, - 0, 0, -1.0002, -1, - 0, 0, -0.2, 0, - }) + projection = giu.NewProjectionMatrix(). + FOV(giu.Deg2Rad(30)). + Aspect(1280.0 / 720.0) cube = giu.NewHumanReadableMatrix(). Transform(0.5, 0.5, 0.5). From dba7bfb5f1a316644744f494c4f1e2a59562c3a4 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 07:42:41 +0100 Subject: [PATCH 14/26] gizmo: rename HumanReadableMatrix -> ViewMatrix --- ExtraWidgets.go | 2 +- Gizmo.go | 60 ++++++++++++++++++++++++------------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/ExtraWidgets.go b/ExtraWidgets.go index 44a0152a..a991dae1 100644 --- a/ExtraWidgets.go +++ b/ExtraWidgets.go @@ -146,7 +146,7 @@ func (c *CustomWidget) Plot() { c.Build() } -func (c *CustomWidget) Gizmo(_ *HumanReadableMatrix, _ *ProjectionMatrix) { +func (c *CustomWidget) Gizmo(_ *ViewMatrix, _ *ProjectionMatrix) { c.Build() } diff --git a/Gizmo.go b/Gizmo.go index 9d8bba21..862ff196 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -52,7 +52,7 @@ const ( // GizmoI should be implemented by every sub-element of GizmoWidget. type GizmoI interface { - Gizmo(view *HumanReadableMatrix, projection *ProjectionMatrix) + Gizmo(view *ViewMatrix, projection *ProjectionMatrix) } var _ Widget = &GizmoWidget{} @@ -64,12 +64,12 @@ var _ Widget = &GizmoWidget{} // https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ (DISCLAIMER: giu authors are not responsible if you go mad or something!) type GizmoWidget struct { gizmos []GizmoI - view *HumanReadableMatrix + view *ViewMatrix projection *ProjectionMatrix } // Gizmo creates a new GizmoWidget. -func Gizmo(view *HumanReadableMatrix, projection *ProjectionMatrix) *GizmoWidget { +func Gizmo(view *ViewMatrix, projection *ProjectionMatrix) *GizmoWidget { return &GizmoWidget{ gizmos: []GizmoI{}, view: view, @@ -115,7 +115,7 @@ var _ GizmoI = &GridGizmo{} // GridGizmo draws a grid in the gizmo area. type GridGizmo struct { // default to Identity - matrix *HumanReadableMatrix + matrix *ViewMatrix thickness float32 } @@ -134,7 +134,7 @@ func (g *GridGizmo) Thickness(t float32) *GridGizmo { } // Gizmo implements GizmoI interface. -func (g *GridGizmo) Gizmo(view *HumanReadableMatrix, projection *ProjectionMatrix) { +func (g *GridGizmo) Gizmo(view *ViewMatrix, projection *ProjectionMatrix) { imguizmo.DrawGrid( view.Matrix(), projection.Matrix(), @@ -148,12 +148,12 @@ var _ GizmoI = &CubeGizmo{} // CubeGizmo draws a 3D cube in the gizmo area. // View and Projection matrices are provided by GizmoWidget. type CubeGizmo struct { - matrix *HumanReadableMatrix + matrix *ViewMatrix manipulate bool } // Cube creates a new CubeGizmo. -func Cube(matrix *HumanReadableMatrix) *CubeGizmo { +func Cube(matrix *ViewMatrix) *CubeGizmo { return &CubeGizmo{ matrix: matrix, } @@ -166,7 +166,7 @@ func (c *CubeGizmo) Manipulate() *CubeGizmo { } // Gizmo implements GizmoI interface. -func (c *CubeGizmo) Gizmo(view *HumanReadableMatrix, projection *ProjectionMatrix) { +func (c *CubeGizmo) Gizmo(view *ViewMatrix, projection *ProjectionMatrix) { imguizmo.DrawCubes( view.Matrix(), projection.Matrix(), @@ -185,13 +185,13 @@ var _ GizmoI = &ManipulateGizmo{} // It can be attached to another Gizmo (e.g. CubeGizmo) and will allow to move/rotate/scale it. // See (*CubeGizmo).Manipulate() method. type ManipulateGizmo struct { - matrix *HumanReadableMatrix + matrix *ViewMatrix operation GizmoOperation mode GizmoMode } // Manipulate creates a new ManipulateGizmo. -func Manipulate(matrix *HumanReadableMatrix) *ManipulateGizmo { +func Manipulate(matrix *ViewMatrix) *ManipulateGizmo { return &ManipulateGizmo{ matrix: matrix, mode: GizmoMode(imguizmo.LOCAL), @@ -200,7 +200,7 @@ func Manipulate(matrix *HumanReadableMatrix) *ManipulateGizmo { } // Gizmo implements GizmoI interface. -func (m *ManipulateGizmo) Gizmo(view *HumanReadableMatrix, projection *ProjectionMatrix) { +func (m *ManipulateGizmo) Gizmo(view *ViewMatrix, projection *ProjectionMatrix) { imguizmo.ManipulateV( view.Matrix(), projection.Matrix(), @@ -246,7 +246,7 @@ func (v *ViewManipulateGizmo) Color(c color.Color) *ViewManipulateGizmo { } // Gizmo implements GizmoI interface. -func (v *ViewManipulateGizmo) Gizmo(view *HumanReadableMatrix, projection *ProjectionMatrix) { +func (v *ViewManipulateGizmo) Gizmo(view *ViewMatrix, projection *ProjectionMatrix) { imguizmo.ViewManipulateFloat( view.Matrix(), 1, @@ -258,11 +258,11 @@ func (v *ViewManipulateGizmo) Gizmo(view *HumanReadableMatrix, projection *Proje // [Gizmo helpers] -// HumanReadableMatrix is a suitable thing here. +// ViewMatrix is a suitable thing here. // It makes it even possible to use gizmos. // Recommended use is presented in examples/gizmo -// NOTE: You are supposed to allocate this with NewHumanReadableMatrix (do not use zero value)!!! -type HumanReadableMatrix struct { +// NOTE: You are supposed to allocate this with NewViewMatrix (do not use zero value)!!! +type ViewMatrix struct { transform []float32 // supposed len is 3 rotation []float32 // supposed len is 3 scale []float32 // supposed len is 3 @@ -270,8 +270,8 @@ type HumanReadableMatrix struct { dirty bool } -func NewHumanReadableMatrix() *HumanReadableMatrix { - return &HumanReadableMatrix{ +func NewViewMatrix() *ViewMatrix { + return &ViewMatrix{ transform: make([]float32, 3), rotation: make([]float32, 3), scale: make([]float32, 3), @@ -280,8 +280,8 @@ func NewHumanReadableMatrix() *HumanReadableMatrix { } } -func IdentityMatrix() *HumanReadableMatrix { - r := NewHumanReadableMatrix() +func IdentityMatrix() *ViewMatrix { + r := NewViewMatrix() r.matrix = []float32{ 1, 0, 0, 0, 0, 1, 0, 0, @@ -295,7 +295,7 @@ func IdentityMatrix() *HumanReadableMatrix { return r } -func (m *HumanReadableMatrix) Transform(x, y, z float32) *HumanReadableMatrix { +func (m *ViewMatrix) Transform(x, y, z float32) *ViewMatrix { m.transform[0] = x m.transform[1] = y m.transform[2] = z @@ -303,7 +303,7 @@ func (m *HumanReadableMatrix) Transform(x, y, z float32) *HumanReadableMatrix { return m } -func (m *HumanReadableMatrix) Rotation(x, y, z float32) *HumanReadableMatrix { +func (m *ViewMatrix) Rotation(x, y, z float32) *ViewMatrix { m.rotation[0] = x m.rotation[1] = y m.rotation[2] = z @@ -311,7 +311,7 @@ func (m *HumanReadableMatrix) Rotation(x, y, z float32) *HumanReadableMatrix { return m } -func (m *HumanReadableMatrix) Scale(x, y, z float32) *HumanReadableMatrix { +func (m *ViewMatrix) Scale(x, y, z float32) *ViewMatrix { m.scale[0] = x m.scale[1] = y m.scale[2] = z @@ -319,7 +319,7 @@ func (m *HumanReadableMatrix) Scale(x, y, z float32) *HumanReadableMatrix { return m } -func (m *HumanReadableMatrix) SetMatrix(f []float32) *HumanReadableMatrix { +func (m *ViewMatrix) SetMatrix(f []float32) *ViewMatrix { m.matrix = f m.Decompile() m.dirty = false @@ -328,7 +328,7 @@ func (m *HumanReadableMatrix) SetMatrix(f []float32) *HumanReadableMatrix { // Compile updates m.Matrix // NOTE: this supposes matrix was allocated correctly! -func (m *HumanReadableMatrix) Compile() { +func (m *ViewMatrix) Compile() { imguizmo.RecomposeMatrixFromComponents( utils.SliceToPtr(m.transform), utils.SliceToPtr(m.rotation), @@ -339,7 +339,7 @@ func (m *HumanReadableMatrix) Compile() { m.dirty = false } -func (m *HumanReadableMatrix) Decompile() { +func (m *ViewMatrix) Decompile() { imguizmo.DecomposeMatrixToComponents( utils.SliceToPtr(m.matrix), utils.SliceToPtr(m.transform), @@ -348,7 +348,7 @@ func (m *HumanReadableMatrix) Decompile() { ) } -func (m *HumanReadableMatrix) GetTransform() []float32 { +func (m *ViewMatrix) GetTransform() []float32 { if m.dirty { m.Compile() } @@ -356,7 +356,7 @@ func (m *HumanReadableMatrix) GetTransform() []float32 { return m.transform } -func (m *HumanReadableMatrix) GetRotation() []float32 { +func (m *ViewMatrix) GetRotation() []float32 { if m.dirty { m.Compile() } @@ -364,7 +364,7 @@ func (m *HumanReadableMatrix) GetRotation() []float32 { return m.rotation } -func (m *HumanReadableMatrix) GetScale() []float32 { +func (m *ViewMatrix) GetScale() []float32 { if m.dirty { m.Compile() } @@ -374,7 +374,7 @@ func (m *HumanReadableMatrix) GetScale() []float32 { // Matrix returns current matrix compatible with ImGuizmo (pointer to 4x4m). // It recompiles as necessary. -func (m *HumanReadableMatrix) Matrix() *float32 { +func (m *ViewMatrix) Matrix() *float32 { if m.dirty { m.Compile() } @@ -382,7 +382,7 @@ func (m *HumanReadableMatrix) Matrix() *float32 { return utils.SliceToPtr(m.matrix) } -func (m *HumanReadableMatrix) MatrixSlice() []float32 { +func (m *ViewMatrix) MatrixSlice() []float32 { if m.dirty { m.Compile() } From fcc0bb470c5b04e167e64210cd171c83387ad8cc Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 07:46:25 +0100 Subject: [PATCH 15/26] gizmo: update example --- examples/gizmo/main.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/gizmo/main.go b/examples/gizmo/main.go index 0d028d88..512124de 100644 --- a/examples/gizmo/main.go +++ b/examples/gizmo/main.go @@ -8,7 +8,7 @@ import ( ) var ( - view = giu.NewHumanReadableMatrix(). + view = giu.NewViewMatrix(). Transform(0, 0, -7). Rotation(10, 5, 0). Scale(1, 1, 1) @@ -17,10 +17,10 @@ var ( FOV(giu.Deg2Rad(30)). Aspect(1280.0 / 720.0) - cube = giu.NewHumanReadableMatrix(). + cube = giu.NewViewMatrix(). Transform(0.5, 0.5, 0.5). Rotation(0, 0, 0). - Scale(1, 1, 1) + Scale(1, 2, 1) zmoOP = int32(imguizmo.TRANSLATE) zmoMODE = int32(imguizmo.LOCAL) From 0efc5d6d919d6e0a0821ce2ffea18b72ed21b54f Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 09:58:06 +0100 Subject: [PATCH 16/26] Gizmo: update matrices api --- Gizmo.go | 97 +++++++++++++++++++++++++++----------------------------- 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/Gizmo.go b/Gizmo.go index 862ff196..f24632d3 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -136,9 +136,9 @@ func (g *GridGizmo) Thickness(t float32) *GridGizmo { // Gizmo implements GizmoI interface. func (g *GridGizmo) Gizmo(view *ViewMatrix, projection *ProjectionMatrix) { imguizmo.DrawGrid( - view.Matrix(), - projection.Matrix(), - g.matrix.Matrix(), + view.getMatrix(), + projection.getMatrix(), + g.matrix.getMatrix(), g.thickness, ) } @@ -168,9 +168,9 @@ func (c *CubeGizmo) Manipulate() *CubeGizmo { // Gizmo implements GizmoI interface. func (c *CubeGizmo) Gizmo(view *ViewMatrix, projection *ProjectionMatrix) { imguizmo.DrawCubes( - view.Matrix(), - projection.Matrix(), - c.matrix.Matrix(), + view.getMatrix(), + projection.getMatrix(), + c.matrix.getMatrix(), 1, ) @@ -202,11 +202,11 @@ func Manipulate(matrix *ViewMatrix) *ManipulateGizmo { // Gizmo implements GizmoI interface. func (m *ManipulateGizmo) Gizmo(view *ViewMatrix, projection *ProjectionMatrix) { imguizmo.ManipulateV( - view.Matrix(), - projection.Matrix(), + view.getMatrix(), + projection.getMatrix(), imguizmo.OPERATION(m.operation), imguizmo.MODE(m.mode), - m.matrix.Matrix(), + m.matrix.getMatrix(), nil, // this is deltaMatrix (Can't see usecase for now) nil, // snap idk what is this nil, // localBounds idk what is this @@ -215,12 +215,14 @@ func (m *ManipulateGizmo) Gizmo(view *ViewMatrix, projection *ProjectionMatrix) var _ GizmoI = &ViewManipulateGizmo{} +// ViewManipulateGizmo is a gizmo that allows you to manipulate world rotation visualy. type ViewManipulateGizmo struct { position imgui.Vec2 size imgui.Vec2 color uint32 } +// ViewManipulate creates a new ViewManipulateGizmo. func ViewManipulate() *ViewManipulateGizmo { return &ViewManipulateGizmo{ position: imgui.Vec2{128, 128}, @@ -240,6 +242,7 @@ func (v *ViewManipulateGizmo) Size(x, y float32) *ViewManipulateGizmo { return v } +// Color sets the color of the gizmo. func (v *ViewManipulateGizmo) Color(c color.Color) *ViewManipulateGizmo { v.color = ColorToUint(c) return v @@ -248,7 +251,7 @@ func (v *ViewManipulateGizmo) Color(c color.Color) *ViewManipulateGizmo { // Gizmo implements GizmoI interface. func (v *ViewManipulateGizmo) Gizmo(view *ViewMatrix, projection *ProjectionMatrix) { imguizmo.ViewManipulateFloat( - view.Matrix(), + view.getMatrix(), 1, v.position, v.size, @@ -258,9 +261,10 @@ func (v *ViewManipulateGizmo) Gizmo(view *ViewMatrix, projection *ProjectionMatr // [Gizmo helpers] -// ViewMatrix is a suitable thing here. -// It makes it even possible to use gizmos. -// Recommended use is presented in examples/gizmo +// ViewMatrix allows to generate a "view" matrix: +// - position +// - rotation +// - scale // NOTE: You are supposed to allocate this with NewViewMatrix (do not use zero value)!!! type ViewMatrix struct { transform []float32 // supposed len is 3 @@ -270,6 +274,7 @@ type ViewMatrix struct { dirty bool } +// NewViewMatrix creates a new ViewMatrix. func NewViewMatrix() *ViewMatrix { return &ViewMatrix{ transform: make([]float32, 3), @@ -280,6 +285,7 @@ func NewViewMatrix() *ViewMatrix { } } +// IdentityMatrix creates a new ViewMatrix with identity matrix. func IdentityMatrix() *ViewMatrix { r := NewViewMatrix() r.matrix = []float32{ @@ -289,12 +295,13 @@ func IdentityMatrix() *ViewMatrix { 0, 0, 0, 1, } - r.Decompile() + r.decompile() r.dirty = false return r } +// Transorm sets the position of the matrix. func (m *ViewMatrix) Transform(x, y, z float32) *ViewMatrix { m.transform[0] = x m.transform[1] = y @@ -303,6 +310,7 @@ func (m *ViewMatrix) Transform(x, y, z float32) *ViewMatrix { return m } +// Rotation sets the rotation of the matrix. func (m *ViewMatrix) Rotation(x, y, z float32) *ViewMatrix { m.rotation[0] = x m.rotation[1] = y @@ -311,6 +319,7 @@ func (m *ViewMatrix) Rotation(x, y, z float32) *ViewMatrix { return m } +// Scale sets the scale of the matrix. func (m *ViewMatrix) Scale(x, y, z float32) *ViewMatrix { m.scale[0] = x m.scale[1] = y @@ -319,16 +328,19 @@ func (m *ViewMatrix) Scale(x, y, z float32) *ViewMatrix { return m } +// SetMatrix allows you to set the matrix directly. +// NOTE: f is supposed to be 16 elements long. +// NOTE: it is not recommended - use components functions func (m *ViewMatrix) SetMatrix(f []float32) *ViewMatrix { m.matrix = f - m.Decompile() + m.decompile() m.dirty = false return m } -// Compile updates m.Matrix +// Compile updates m.matrix // NOTE: this supposes matrix was allocated correctly! -func (m *ViewMatrix) Compile() { +func (m *ViewMatrix) compile() { imguizmo.RecomposeMatrixFromComponents( utils.SliceToPtr(m.transform), utils.SliceToPtr(m.rotation), @@ -339,7 +351,8 @@ func (m *ViewMatrix) Compile() { m.dirty = false } -func (m *ViewMatrix) Decompile() { +// decompile updates m.transform, m.rotation, m.scale from m.matrix +func (m *ViewMatrix) decompile() { imguizmo.DecomposeMatrixToComponents( utils.SliceToPtr(m.matrix), utils.SliceToPtr(m.transform), @@ -348,35 +361,11 @@ func (m *ViewMatrix) Decompile() { ) } -func (m *ViewMatrix) GetTransform() []float32 { - if m.dirty { - m.Compile() - } - - return m.transform -} - -func (m *ViewMatrix) GetRotation() []float32 { - if m.dirty { - m.Compile() - } - - return m.rotation -} - -func (m *ViewMatrix) GetScale() []float32 { - if m.dirty { - m.Compile() - } - - return m.scale -} - -// Matrix returns current matrix compatible with ImGuizmo (pointer to 4x4m). +// matrix returns current matrix compatible with ImGuizmo (pointer to 4x4m). // It recompiles as necessary. -func (m *ViewMatrix) Matrix() *float32 { +func (m *ViewMatrix) getMatrix() *float32 { if m.dirty { - m.Compile() + m.compile() } return utils.SliceToPtr(m.matrix) @@ -384,16 +373,17 @@ func (m *ViewMatrix) Matrix() *float32 { func (m *ViewMatrix) MatrixSlice() []float32 { if m.dirty { - m.Compile() + m.compile() } return m.matrix } +// ProjectionMatrix represents a matrix for Gizmo projection. // ref: https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/#the-projection-matrix type ProjectionMatrix struct { // The vertical Field of View, in radians: the amount of "zoom". Think "camera lens". Usually between 90° (extra wide) and 30° (quite zoomed in) - // This value is in radians! + // This value is in radians! See Deg2Rad. fov float32 // Aspect Ratio. Depends on the size of your window. Notice that 4/3 == 800/600 == 1280/960, sounds familiar? aspect float32 @@ -406,6 +396,7 @@ type ProjectionMatrix struct { matrix []float32 } +// NewProjectionMatrix creates a new ProjectionMatrix. func NewProjectionMatrix() *ProjectionMatrix { return &ProjectionMatrix{ fov: Deg2Rad(45), @@ -417,39 +408,45 @@ func NewProjectionMatrix() *ProjectionMatrix { } } +// FOV sets the Field of View. func (p *ProjectionMatrix) FOV(fov float32) *ProjectionMatrix { p.fov = fov p.dirty = true return p } +// Aspect sets the Aspect Ratio. func (p *ProjectionMatrix) Aspect(aspect float32) *ProjectionMatrix { p.aspect = aspect p.dirty = true return p } +// NearClipping sets the Near Clipping plane. func (p *ProjectionMatrix) NearClipping(near float32) *ProjectionMatrix { p.nearClipping = near p.dirty = true return p } +// FarClipping sets the Far Clipping plane. func (p *ProjectionMatrix) FarClipping(far float32) *ProjectionMatrix { p.farClipping = far p.dirty = true return p } -func (p *ProjectionMatrix) Matrix() *float32 { +// getMatrix returns the matrix compatible with ImGuizmo (pointer to 4x4m). +func (p *ProjectionMatrix) getMatrix() *float32 { if p.dirty { - p.Compile() + p.compile() } return utils.SliceToPtr(p.matrix) } -func (p *ProjectionMatrix) Compile() { +// compile updates p.matrix. +func (p *ProjectionMatrix) compile() { p.matrix = glm.MatrixPerspective(p.fov, p.aspect, p.nearClipping, p.farClipping) p.dirty = false } From be881f0d6367ac6d0e7e322a831c016d8981d730 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 10:17:45 +0100 Subject: [PATCH 17/26] gizmo: implement imguizmo ID mechanism also add Copy method for matrices --- Gizmo.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Gizmo.go b/Gizmo.go index f24632d3..92ff9e31 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -66,6 +66,7 @@ type GizmoWidget struct { gizmos []GizmoI view *ViewMatrix projection *ProjectionMatrix + id ID } // Gizmo creates a new GizmoWidget. @@ -74,9 +75,16 @@ func Gizmo(view *ViewMatrix, projection *ProjectionMatrix) *GizmoWidget { gizmos: []GizmoI{}, view: view, projection: projection, + id: GenAutoID("gizmo"), } } +// ID sets the ID of the GizmoWidget. (useful if you use multiple gizmo widgets. It is set by AutoID anyway) +func (g *GizmoWidget) ID(id ID) *GizmoWidget { + g.id = id + return g +} + // Gizmos adds GizmoI elements to the GizmoWidget area. func (g *GizmoWidget) Gizmos(gizmos ...GizmoI) *GizmoWidget { g.gizmos = append(g.gizmos, gizmos...) @@ -86,9 +94,13 @@ func (g *GizmoWidget) Gizmos(gizmos ...GizmoI) *GizmoWidget { // build is a local build function. // Just to separate Global() and Build() methods. func (g *GizmoWidget) build() { + imguizmo.PushIDStr(string(g.id)) + for _, gizmo := range g.gizmos { gizmo.Gizmo(g.view, g.projection) } + + imguizmo.PopID() } // Build implements Widget interface. @@ -338,6 +350,15 @@ func (m *ViewMatrix) SetMatrix(f []float32) *ViewMatrix { return m } +// Copies returns a copy of the matrix. +// Useful e.g. in exaples/ to duplicate the matrix. +func (m *ViewMatrix) Copy() *ViewMatrix { + return NewViewMatrix(). + Transform(m.transform[0], m.transform[1], m.transform[2]). + Rotation(m.rotation[0], m.rotation[1], m.rotation[2]). + Scale(m.scale[0], m.scale[1], m.scale[2]) +} + // Compile updates m.matrix // NOTE: this supposes matrix was allocated correctly! func (m *ViewMatrix) compile() { @@ -436,6 +457,15 @@ func (p *ProjectionMatrix) FarClipping(far float32) *ProjectionMatrix { return p } +// Copy returns a copy of the matrix. +func (p *ProjectionMatrix) Copy() *ProjectionMatrix { + return NewProjectionMatrix(). + FOV(p.fov). + Aspect(p.aspect). + NearClipping(p.nearClipping). + FarClipping(p.farClipping) +} + // getMatrix returns the matrix compatible with ImGuizmo (pointer to 4x4m). func (p *ProjectionMatrix) getMatrix() *float32 { if p.dirty { From da0b8d2495e91b0ac082e7b45bf4af8a0d9110b7 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 10:19:55 +0100 Subject: [PATCH 18/26] examples/gizmo: remove unused globals --- examples/gizmo/main.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/examples/gizmo/main.go b/examples/gizmo/main.go index 512124de..d70a145c 100644 --- a/examples/gizmo/main.go +++ b/examples/gizmo/main.go @@ -3,7 +3,6 @@ package main import ( "image/color" - "github.com/AllenDang/cimgui-go/imguizmo" "github.com/AllenDang/giu" ) @@ -22,14 +21,7 @@ var ( Rotation(0, 0, 0). Scale(1, 2, 1) - zmoOP = int32(imguizmo.TRANSLATE) - zmoMODE = int32(imguizmo.LOCAL) - Bounds = []float32{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5} - - // GizmoControls can be enabled in editor and allows mouse control over gizmo - GizmoControls bool - UsingGizmo bool ) func gizmos() []giu.GizmoI { From 82d6fc9bd3198e91b2928d4b083752441cf214aa Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 10:24:36 +0100 Subject: [PATCH 19/26] examples/gizmo: final updates --- examples/gizmo/main.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/gizmo/main.go b/examples/gizmo/main.go index d70a145c..d05d937d 100644 --- a/examples/gizmo/main.go +++ b/examples/gizmo/main.go @@ -20,8 +20,6 @@ var ( Transform(0.5, 0.5, 0.5). Rotation(0, 0, 0). Scale(1, 2, 1) - - Bounds = []float32{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5} ) func gizmos() []giu.GizmoI { @@ -42,11 +40,14 @@ func gizmos() []giu.GizmoI { func loop() { giu.Gizmo(view, projection).Gizmos(gizmos()...).Global() - giu.Window("Gizmo demo").Layout( - giu.Gizmo(view, projection).Gizmos( - gizmos()..., - ), - ) + giu.Window("Gizmo demo"). + Size(300, 300). + Pos(50, 300). + Layout( + giu.Gizmo(view, projection).Gizmos( + gizmos()..., + ), + ) } func main() { From 0ba6bb4e30e0283b175d0570a875edbbc175decd Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 10:28:17 +0100 Subject: [PATCH 20/26] gizmo: add Disabled --- Gizmo.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Gizmo.go b/Gizmo.go index 92ff9e31..4f7d2e75 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -67,6 +67,7 @@ type GizmoWidget struct { view *ViewMatrix projection *ProjectionMatrix id ID + disabled bool } // Gizmo creates a new GizmoWidget. @@ -76,6 +77,7 @@ func Gizmo(view *ViewMatrix, projection *ProjectionMatrix) *GizmoWidget { view: view, projection: projection, id: GenAutoID("gizmo"), + disabled: false, } } @@ -85,6 +87,12 @@ func (g *GizmoWidget) ID(id ID) *GizmoWidget { return g } +// Disable disables the GizmoWidget. +func (g *GizmoWidget) Disabled(b bool) *GizmoWidget { + g.disabled = b + return g +} + // Gizmos adds GizmoI elements to the GizmoWidget area. func (g *GizmoWidget) Gizmos(gizmos ...GizmoI) *GizmoWidget { g.gizmos = append(g.gizmos, gizmos...) @@ -95,6 +103,7 @@ func (g *GizmoWidget) Gizmos(gizmos ...GizmoI) *GizmoWidget { // Just to separate Global() and Build() methods. func (g *GizmoWidget) build() { imguizmo.PushIDStr(string(g.id)) + imguizmo.Enable(!g.disabled) for _, gizmo := range g.gizmos { gizmo.Gizmo(g.view, g.projection) From 2d77525f3081f34883f474c8c39f8c082de48bf3 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 10:28:31 +0100 Subject: [PATCH 21/26] examples/gizmo: implement disabled --- examples/gizmo/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gizmo/main.go b/examples/gizmo/main.go index d05d937d..79f006da 100644 --- a/examples/gizmo/main.go +++ b/examples/gizmo/main.go @@ -46,7 +46,7 @@ func loop() { Layout( giu.Gizmo(view, projection).Gizmos( gizmos()..., - ), + ).Disabled(true), ) } From 62ea34f80b8583cb1dbc1efda962f883a9d3bfd0 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 10:31:00 +0100 Subject: [PATCH 22/26] gizmo: add orthographic method --- Gizmo.go | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/Gizmo.go b/Gizmo.go index 4f7d2e75..77e7f8b9 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -63,21 +63,23 @@ var _ Widget = &GizmoWidget{} // If you wnat to have more understanding about what is going on here, read this: // https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ (DISCLAIMER: giu authors are not responsible if you go mad or something!) type GizmoWidget struct { - gizmos []GizmoI - view *ViewMatrix - projection *ProjectionMatrix - id ID - disabled bool + gizmos []GizmoI + view *ViewMatrix + projection *ProjectionMatrix + id ID + disabled bool + orthographic bool } // Gizmo creates a new GizmoWidget. func Gizmo(view *ViewMatrix, projection *ProjectionMatrix) *GizmoWidget { return &GizmoWidget{ - gizmos: []GizmoI{}, - view: view, - projection: projection, - id: GenAutoID("gizmo"), - disabled: false, + gizmos: []GizmoI{}, + view: view, + projection: projection, + id: GenAutoID("gizmo"), + disabled: false, + orthographic: false, } } @@ -93,6 +95,12 @@ func (g *GizmoWidget) Disabled(b bool) *GizmoWidget { return g } +// Orthographic sets the projection matrix to orthographic. +func (g *GizmoWidget) Orthographic(b bool) *GizmoWidget { + g.orthographic = b + return g +} + // Gizmos adds GizmoI elements to the GizmoWidget area. func (g *GizmoWidget) Gizmos(gizmos ...GizmoI) *GizmoWidget { g.gizmos = append(g.gizmos, gizmos...) @@ -104,6 +112,7 @@ func (g *GizmoWidget) Gizmos(gizmos ...GizmoI) *GizmoWidget { func (g *GizmoWidget) build() { imguizmo.PushIDStr(string(g.id)) imguizmo.Enable(!g.disabled) + imguizmo.SetOrthographic(g.orthographic) for _, gizmo := range g.gizmos { gizmo.Gizmo(g.view, g.projection) From de8e1b927c1a5d43d42c4421d5b18f539aec637b Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 10:34:45 +0100 Subject: [PATCH 23/26] gizmo: add possibility to set gird matrix --- Gizmo.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Gizmo.go b/Gizmo.go index 77e7f8b9..da506f92 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -163,6 +163,12 @@ func (g *GridGizmo) Thickness(t float32) *GridGizmo { return g } +// Matrix allows to set grid matrix. Default to IdentityMatrix. +func (g *GridGizmo) Matrix(matrix *ViewMatrix) *GridGizmo { + g.matrix = matrix + return g +} + // Gizmo implements GizmoI interface. func (g *GridGizmo) Gizmo(view *ViewMatrix, projection *ProjectionMatrix) { imguizmo.DrawGrid( From c24ac3b0a7c454131ab9ae25d1b4ad1183f6eb37 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 10:35:33 +0100 Subject: [PATCH 24/26] golangci-lin run --fix --- Gizmo.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Gizmo.go b/Gizmo.go index da506f92..e86e8d75 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -12,7 +12,7 @@ import ( // GizmoOperation specifies the operation of Gizmo (used by manipulate). type GizmoOperation int -// Possible Operations +// Possible Operations. const ( OperationTranslateX GizmoOperation = GizmoOperation(imguizmo.TRANSLATEX) OperationTranslateY GizmoOperation = GizmoOperation(imguizmo.TRANSLATEY) @@ -44,7 +44,7 @@ const ( // GizmoMode specifies the mode of Gizmo (used by manipulate). type GizmoMode int -// values are not explained in source code +// values are not explained in source code. const ( ModeLocal GizmoMode = GizmoMode(imguizmo.LOCAL) ModeWorld GizmoMode = GizmoMode(imguizmo.WORLD) @@ -60,7 +60,7 @@ var _ Widget = &GizmoWidget{} // GizmoWidget implements ImGuizmo features. // It is designed just like PlotWidget. // This structure provides an "area" where you can put Gizmos (see (*GizmoWidget).Gizmos). -// If you wnat to have more understanding about what is going on here, read this: +// If you want to have more understanding about what is going on here, read this: // https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ (DISCLAIMER: giu authors are not responsible if you go mad or something!) type GizmoWidget struct { gizmos []GizmoI @@ -83,7 +83,7 @@ func Gizmo(view *ViewMatrix, projection *ProjectionMatrix) *GizmoWidget { } } -// ID sets the ID of the GizmoWidget. (useful if you use multiple gizmo widgets. It is set by AutoID anyway) +// ID sets the ID of the GizmoWidget. (useful if you use multiple gizmo widgets. It is set by AutoID anyway). func (g *GizmoWidget) ID(id ID) *GizmoWidget { g.id = id return g @@ -366,7 +366,7 @@ func (m *ViewMatrix) Scale(x, y, z float32) *ViewMatrix { // SetMatrix allows you to set the matrix directly. // NOTE: f is supposed to be 16 elements long. -// NOTE: it is not recommended - use components functions +// NOTE: it is not recommended - use components functions. func (m *ViewMatrix) SetMatrix(f []float32) *ViewMatrix { m.matrix = f m.decompile() @@ -396,7 +396,7 @@ func (m *ViewMatrix) compile() { m.dirty = false } -// decompile updates m.transform, m.rotation, m.scale from m.matrix +// decompile updates m.transform, m.rotation, m.scale from m.matrix. func (m *ViewMatrix) decompile() { imguizmo.DecomposeMatrixToComponents( utils.SliceToPtr(m.matrix), From 5700c603bb0c4b4d82a0cda2ffaff26b9004fe84 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 10:46:11 +0100 Subject: [PATCH 25/26] linting(Gizmo) --- ExtraWidgets.go | 1 + Gizmo.go | 30 ++++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/ExtraWidgets.go b/ExtraWidgets.go index a991dae1..1440d04b 100644 --- a/ExtraWidgets.go +++ b/ExtraWidgets.go @@ -146,6 +146,7 @@ func (c *CustomWidget) Plot() { c.Build() } +// Gizmo implements GizmoI interface. func (c *CustomWidget) Gizmo(_ *ViewMatrix, _ *ProjectionMatrix) { c.Build() } diff --git a/Gizmo.go b/Gizmo.go index e86e8d75..f9ebb754 100644 --- a/Gizmo.go +++ b/Gizmo.go @@ -89,7 +89,7 @@ func (g *GizmoWidget) ID(id ID) *GizmoWidget { return g } -// Disable disables the GizmoWidget. +// Disabled sets GizmoWidget's disabled state. func (g *GizmoWidget) Disabled(b bool) *GizmoWidget { g.disabled = b return g @@ -124,8 +124,10 @@ func (g *GizmoWidget) build() { // Build implements Widget interface. func (g *GizmoWidget) Build() { imguizmo.SetDrawlist() + displaySize := imgui.ContentRegionAvail() pos0 := imgui.CursorScreenPos() + imguizmo.SetRect(pos0.X, pos0.Y, displaySize.X, displaySize.Y) g.build() } @@ -261,31 +263,34 @@ type ViewManipulateGizmo struct { // ViewManipulate creates a new ViewManipulateGizmo. func ViewManipulate() *ViewManipulateGizmo { return &ViewManipulateGizmo{ - position: imgui.Vec2{128, 128}, - size: imgui.Vec2{128, 128}, + position: imgui.Vec2{X: 128, Y: 128}, + size: imgui.Vec2{X: 128, Y: 128}, } } // Position sets the position of the gizmo. func (v *ViewManipulateGizmo) Position(x, y float32) *ViewManipulateGizmo { - v.position = imgui.Vec2{x, y} + v.position = imgui.Vec2{X: x, Y: y} + return v } // Size sets the size of the gizmo. func (v *ViewManipulateGizmo) Size(x, y float32) *ViewManipulateGizmo { - v.size = imgui.Vec2{x, y} + v.size = imgui.Vec2{X: x, Y: y} + return v } // Color sets the color of the gizmo. func (v *ViewManipulateGizmo) Color(c color.Color) *ViewManipulateGizmo { v.color = ColorToUint(c) + return v } // Gizmo implements GizmoI interface. -func (v *ViewManipulateGizmo) Gizmo(view *ViewMatrix, projection *ProjectionMatrix) { +func (v *ViewManipulateGizmo) Gizmo(view *ViewMatrix, _ *ProjectionMatrix) { imguizmo.ViewManipulateFloat( view.getMatrix(), 1, @@ -337,12 +342,13 @@ func IdentityMatrix() *ViewMatrix { return r } -// Transorm sets the position of the matrix. +// Transform sets the position of the matrix. func (m *ViewMatrix) Transform(x, y, z float32) *ViewMatrix { m.transform[0] = x m.transform[1] = y m.transform[2] = z m.dirty = true + return m } @@ -352,6 +358,7 @@ func (m *ViewMatrix) Rotation(x, y, z float32) *ViewMatrix { m.rotation[1] = y m.rotation[2] = z m.dirty = true + return m } @@ -361,6 +368,7 @@ func (m *ViewMatrix) Scale(x, y, z float32) *ViewMatrix { m.scale[1] = y m.scale[2] = z m.dirty = true + return m } @@ -371,10 +379,11 @@ func (m *ViewMatrix) SetMatrix(f []float32) *ViewMatrix { m.matrix = f m.decompile() m.dirty = false + return m } -// Copies returns a copy of the matrix. +// Copy copies returns a copy of the matrix. // Useful e.g. in exaples/ to duplicate the matrix. func (m *ViewMatrix) Copy() *ViewMatrix { return NewViewMatrix(). @@ -416,6 +425,7 @@ func (m *ViewMatrix) getMatrix() *float32 { return utils.SliceToPtr(m.matrix) } +// MatrixSlice returns ViewMatrix as a slice (for debugging purposes). func (m *ViewMatrix) MatrixSlice() []float32 { if m.dirty { m.compile() @@ -457,6 +467,7 @@ func NewProjectionMatrix() *ProjectionMatrix { func (p *ProjectionMatrix) FOV(fov float32) *ProjectionMatrix { p.fov = fov p.dirty = true + return p } @@ -464,6 +475,7 @@ func (p *ProjectionMatrix) FOV(fov float32) *ProjectionMatrix { func (p *ProjectionMatrix) Aspect(aspect float32) *ProjectionMatrix { p.aspect = aspect p.dirty = true + return p } @@ -471,6 +483,7 @@ func (p *ProjectionMatrix) Aspect(aspect float32) *ProjectionMatrix { func (p *ProjectionMatrix) NearClipping(near float32) *ProjectionMatrix { p.nearClipping = near p.dirty = true + return p } @@ -478,6 +491,7 @@ func (p *ProjectionMatrix) NearClipping(near float32) *ProjectionMatrix { func (p *ProjectionMatrix) FarClipping(far float32) *ProjectionMatrix { p.farClipping = far p.dirty = true + return p } From 9099cfdc1f1fc390ffe264feacd7a5a65ce79395 Mon Sep 17 00:00:00 2001 From: gucio321 Date: Wed, 30 Oct 2024 10:46:27 +0100 Subject: [PATCH 26/26] lint(examples/gizmo) --- examples/gizmo/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/gizmo/main.go b/examples/gizmo/main.go index 79f006da..edbd602f 100644 --- a/examples/gizmo/main.go +++ b/examples/gizmo/main.go @@ -1,3 +1,4 @@ +// Package main shows usage of GizmoWidget. package main import (