Skip to content

Commit

Permalink
Fix coordinate mapping in ScreenToGLCoords and GLToScreenCoords
Browse files Browse the repository at this point in the history
Fixes #64.
  • Loading branch information
db47h authored and UserAB1236872 committed Mar 9, 2018
1 parent 0626298 commit 400add2
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 20 deletions.
21 changes: 11 additions & 10 deletions mgl32/shapes.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,29 +263,30 @@ func ReticulateSplines(ranges [][][2]float32, cPoints [][][]Vec2, withLlamas boo
// Transform from pixel coordinates to GL coordinates.
//
// This assumes that your pixel coordinate system considers its origin to be in the top left corner (GL's is in the bottom left).
// The coordinates x and y may be out of the range [0,screenWidth] and [0,screeneHeight].
// The coordinates x and y may be out of the range [0,screenWidth-1] and [0,screeneHeight-1].
//
// GL's coordinate system maps [screenWidth,0] to [1.0,1.0] and [0,screenHeight] to [-1.0,-1.0]. If x and y are out of the range, they'll still
// be mapped correctly, just off the screen. (e.g. if y = 2*screenHeight you'll get -2.0 for yOut)
// GL's coordinate system maps [screenWidth-1,0] to [1.0,1.0] and [0,screenHeight-1] to [-1.0,-1.0]. If x and y are out of the range, they'll still
// be mapped correctly, just off the screen. (e.g. if y = 2*(screenHeight-1) you'll get -3.0 for yOut)
//
// This is similar to Unproject, except for 2D cases and much simpler (especially since an inverse may always be found)
func ScreenToGLCoords(x, y int, screenWidth, screenHeight int) (xOut, yOut float32) {
xOut = 2.0*float32(x)/float32(screenWidth) - 1.0
yOut = -2.0*float32(y)/float32(screenHeight) + 1.0
xOut = 2.0*float32(x)/float32(screenWidth-1) - 1.0
yOut = -2.0*float32(y)/float32(screenHeight-1) + 1.0

return
}

// Transform from GL's proportional system to pixel coordinates
// Transform from GL's proportional system to pixel coordinates.
//
// Assumes the pixel coordinate system has its origin in the top left corner. (GL's is in the bottom left)
//
// GL's coordinate system maps [screenWidth,0] to [1.0,1.0] and [0,screenHeight] to [-1.0,-1.0]. If x and y are out of the range, they'll still
// be mapped correctly, just off the screen. (e.g. if y=-2.0, you'll get 2*screenHeight for yOut)
// GL's coordinate system maps [screenWidth-1,0] to [1.0,1.0] and [0,screenHeight-1] to [-1.0,-1.0]. If x and y are out of the range, they'll still
// be mapped correctly, just off the screen. (e.g. if y=-3.0, you'll get 2*(screenHeight-1) for yOut)
//
// This is similar to Project, except for 2D cases and much simpler
func GLToScreenCoords(x, y float32, screenWidth, screenHeight int) (xOut, yOut int) {
xOut = int((x + 1.0) * float32(screenWidth) / 2.0)
yOut = int((y - 1.0) * float32(screenHeight) / 2.0)
xOut = int((x + 1.0) * float32(screenWidth-1) / 2.0)
yOut = int((1.0 - y) * float32(screenHeight-1) / 2.0)

return
}
Expand Down
54 changes: 54 additions & 0 deletions mgl32/shapes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2018 The go-gl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.package mgl64_test

package mgl32

import (
"testing"
)

func TestScreenToGLCoords(t *testing.T) {
// use a small screen size in order to minimize errors due to fp rounding.
const (
sw = 100
sh = 100
)
x, y := ScreenToGLCoords(0, sh-1, sw, sh)
if x != -1 {
t.Errorf("x = %f, expected -1.0", x)
}
if y != -1 {
t.Errorf("y = %f, expected -1.0", y)
}

x, y = ScreenToGLCoords(sw-1, 0, sw, sh)
if x != 1 {
t.Errorf("x = %f, expected 1.0", x)
}
if y != 1 {
t.Errorf("y = %f, expected 1.0", y)
}
}

func TestGLToScreenCoords(t *testing.T) {
const (
sw = 100
sh = 100
)
x, y := GLToScreenCoords(-1, -1, sw, sh)
if x != 0 {
t.Errorf("x = %d, expected 0", x)
}
if y != sh-1 {
t.Errorf("y = %d, expected %d", y, sh-1)
}

x, y = GLToScreenCoords(1, 1, sw, sh)
if x != sw-1 {
t.Errorf("x = %d, expected %d", x, sw-1)
}
if y != 0 {
t.Errorf("y = %d, expected 0", y)
}
}
21 changes: 11 additions & 10 deletions mgl64/shapes.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,29 +265,30 @@ func ReticulateSplines(ranges [][][2]float64, cPoints [][][]Vec2, withLlamas boo
// Transform from pixel coordinates to GL coordinates.
//
// This assumes that your pixel coordinate system considers its origin to be in the top left corner (GL's is in the bottom left).
// The coordinates x and y may be out of the range [0,screenWidth] and [0,screeneHeight].
// The coordinates x and y may be out of the range [0,screenWidth-1] and [0,screeneHeight-1].
//
// GL's coordinate system maps [screenWidth,0] to [1.0,1.0] and [0,screenHeight] to [-1.0,-1.0]. If x and y are out of the range, they'll still
// be mapped correctly, just off the screen. (e.g. if y = 2*screenHeight you'll get -2.0 for yOut)
// GL's coordinate system maps [screenWidth-1,0] to [1.0,1.0] and [0,screenHeight-1] to [-1.0,-1.0]. If x and y are out of the range, they'll still
// be mapped correctly, just off the screen. (e.g. if y = 2*(screenHeight-1) you'll get -3.0 for yOut)
//
// This is similar to Unproject, except for 2D cases and much simpler (especially since an inverse may always be found)
func ScreenToGLCoords(x, y int, screenWidth, screenHeight int) (xOut, yOut float64) {
xOut = 2.0*float64(x)/float64(screenWidth) - 1.0
yOut = -2.0*float64(y)/float64(screenHeight) + 1.0
xOut = 2.0*float64(x)/float64(screenWidth-1) - 1.0
yOut = -2.0*float64(y)/float64(screenHeight-1) + 1.0

return
}

// Transform from GL's proportional system to pixel coordinates
// Transform from GL's proportional system to pixel coordinates.
//
// Assumes the pixel coordinate system has its origin in the top left corner. (GL's is in the bottom left)
//
// GL's coordinate system maps [screenWidth,0] to [1.0,1.0] and [0,screenHeight] to [-1.0,-1.0]. If x and y are out of the range, they'll still
// be mapped correctly, just off the screen. (e.g. if y=-2.0, you'll get 2*screenHeight for yOut)
// GL's coordinate system maps [screenWidth-1,0] to [1.0,1.0] and [0,screenHeight-1] to [-1.0,-1.0]. If x and y are out of the range, they'll still
// be mapped correctly, just off the screen. (e.g. if y=-3.0, you'll get 2*(screenHeight-1) for yOut)
//
// This is similar to Project, except for 2D cases and much simpler
func GLToScreenCoords(x, y float64, screenWidth, screenHeight int) (xOut, yOut int) {
xOut = int((x + 1.0) * float64(screenWidth) / 2.0)
yOut = int((y - 1.0) * float64(screenHeight) / 2.0)
xOut = int((x + 1.0) * float64(screenWidth-1) / 2.0)
yOut = int((1.0 - y) * float64(screenHeight-1) / 2.0)

return
}
Expand Down
56 changes: 56 additions & 0 deletions mgl64/shapes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// This file is generated from mgl32/shapes_test.go; DO NOT EDIT

// Copyright 2018 The go-gl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.package mgl64_test

package mgl64

import (
"testing"
)

func TestScreenToGLCoords(t *testing.T) {
// use a small screen size in order to minimize errors due to fp rounding.
const (
sw = 100
sh = 100
)
x, y := ScreenToGLCoords(0, sh-1, sw, sh)
if x != -1 {
t.Errorf("x = %f, expected -1.0", x)
}
if y != -1 {
t.Errorf("y = %f, expected -1.0", y)
}

x, y = ScreenToGLCoords(sw-1, 0, sw, sh)
if x != 1 {
t.Errorf("x = %f, expected 1.0", x)
}
if y != 1 {
t.Errorf("y = %f, expected 1.0", y)
}
}

func TestGLToScreenCoords(t *testing.T) {
const (
sw = 100
sh = 100
)
x, y := GLToScreenCoords(-1, -1, sw, sh)
if x != 0 {
t.Errorf("x = %d, expected 0", x)
}
if y != sh-1 {
t.Errorf("y = %d, expected %d", y, sh-1)
}

x, y = GLToScreenCoords(1, 1, sw, sh)
if x != sw-1 {
t.Errorf("x = %d, expected %d", x, sw-1)
}
if y != 0 {
t.Errorf("y = %d, expected 0", y)
}
}

0 comments on commit 400add2

Please sign in to comment.