Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

finished mocked create renderer impl and first test cases #6

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions fakes/opengl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package fakes

import "github.com/leedenison/gologo/opengl"

// CreateVerticesOnlyMeshRendererImpl : Creates a MeshRenderer that only
// contains vertices and a vertexCount. All other values are nil or 0
func CreateVerticesOnlyMeshRendererImpl(
vertexShader string,
fragmentShader string,
uniforms []int,
uniformValues map[int]interface{},
meshVertices []float32) (*opengl.MeshRenderer, error) {
return &opengl.MeshRenderer{
Shader: nil,
Mesh: 0,
Uniforms: nil,
MeshVertices: meshVertices,
VertexCount: int32(len(meshVertices) / opengl.GlMeshStride),
}, nil
}
2 changes: 1 addition & 1 deletion opengl/opengl.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ func (r *MeshRenderer) Clone() render.Renderer {
}
}

// CreateMeshRenderer : Creates a MeshRenderer. uniforms specifies all uniform variable locations that
// CreateMeshRendererImpl : Creates a MeshRenderer. uniforms specifies all uniform variable locations that
// should be bound in the shader program, including both uniforms with a statically
// defined value and those supplied in each call to RenderAt. uniformValues
// specifies static values for some or all of the uniforms.
Expand Down
141 changes: 111 additions & 30 deletions physics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,130 @@ import (
"testing"

"github.com/go-gl/mathgl/mgl32"
"github.com/leedenison/gologo/fakes"
"github.com/leedenison/gologo/opengl"
)

// Need to decide on corner cases like all 0s
var simplePrimTests = []struct {
var circleContainedInTests = []struct {
name string
botX, topX, botY, topY, radius, posX, posY float32
contExp, overlExp bool
expResult bool
}{
{0, 400, 0, 400, 50, 200, 200, true, true},
{0, 400, 0, 400, 50, 380, 380, false, true},
{0, 400, 0, 400, 50, 425, 425, false, true},
{0, 400, 0, 400, 50, 475, 475, false, false},
{0, 400, 0, 400, 20, 425, 425, false, false},
{0, 400, 0, 400, 100, 500, 400, false, true},
{0, 400, 0, 400, 100, 501, 400, false, false},
{"contained in middle", 0, 400, 0, 400, 50, 200, 200, true},
{"inside and overlap top right", 0, 400, 0, 400, 50, 380, 380, false},
{"outside and overlap top right", 0, 400, 0, 400, 50, 425, 425, false},
{"outside and non-overlap top right", 0, 400, 0, 400, 50, 475, 475, false},
{"outside and non-overlap top right small", 0, 400, 0, 400, 20, 425, 425, false},
{"touching right", 0, 400, 0, 400, 100, 500, 400, false},
{"one unit non-overlap right", 0, 400, 0, 400, 100, 501, 400, false},
}

// TestSimplePrimitive : Test basic primitive creation and
// functionality
func TestSimplePrimitive(t *testing.T) {
// TestCircleContainedIn : Test circle contained in rect
func TestCircleContainedIn(t *testing.T) {
var x, y float32
var rect Rect
var position mgl32.Vec3
var circle Circle
var isContained, overlaps bool
var isContained bool

obj := CreateObject(position)

for _, tt := range simplePrimTests {
obj.SetPosition(tt.posX, tt.posY)
circle.Radius = tt.radius
x, y = obj.GetPosition()
rect = Rect{{tt.botX, tt.botY}, {tt.topX, tt.topY}}

isContained = circle.IsContainedInRect(*obj, rect)
if isContained != tt.contExp {
t.Errorf("IsContInRect %v (exp: %v) with x (%v), y (%v), rad (%v) in x (%v-%v) and y (%v-%v)",
isContained, tt.contExp, x, y, circle.Radius, tt.botX, tt.topX, tt.botY, tt.topY)
}

overlaps = circle.OverlapsWithRect(*obj, rect)
if overlaps != tt.overlExp {
t.Errorf("overlapWithRect %v (exp: %v) with x (%v), y (%v), rad (%v) in x (%v-%v) and y (%v-%v)",
overlaps, tt.overlExp, x, y, circle.Radius, tt.botX, tt.topX, tt.botY, tt.topY)
}
for _, tc := range circleContainedInTests {
t.Run(tc.name, func(t *testing.T) {
obj.SetPosition(tc.posX, tc.posY)
circle.Radius = tc.radius
x, y = obj.GetPosition()
rect = Rect{{tc.botX, tc.botY}, {tc.topX, tc.topY}}

isContained = circle.IsContainedInRect(*obj, rect)
if isContained != tc.expResult {
t.Errorf("IsContInRect %v (exp: %v) with x (%v), y (%v), rad (%v) in x (%v-%v) and y (%v-%v)",
isContained, tc.expResult, x, y, circle.Radius, tc.botX, tc.topX, tc.botY, tc.topY)
}
})
}
}

var circleOverlapTests = []struct {
name string
botX, topX, botY, topY, radius, posX, posY float32
expResult bool
}{
{"contained in middle", 0, 400, 0, 400, 50, 200, 200, true},
{"inside and overlap top right", 0, 400, 0, 400, 50, 380, 380, true},
{"outside and overlap top right", 0, 400, 0, 400, 50, 425, 425, true},
{"outside and non-overlap top right", 0, 400, 0, 400, 50, 475, 475, false},
{"outside and non-overlap top right small", 0, 400, 0, 400, 20, 425, 425, false},
{"touching right", 0, 400, 0, 400, 100, 500, 400, true},
{"one unit non-overlap right", 0, 400, 0, 400, 100, 501, 400, false},
}

// TestCircleOverlap : Test circle overlaps with rect
func TestCircleOverlap(t *testing.T) {
var x, y float32
var rect Rect
var position mgl32.Vec3
var circle Circle
var overlaps bool

obj := CreateObject(position)

for _, tc := range circleOverlapTests {
t.Run(tc.name, func(t *testing.T) {
obj.SetPosition(tc.posX, tc.posY)
circle.Radius = tc.radius
x, y = obj.GetPosition()
rect = Rect{{tc.botX, tc.botY}, {tc.topX, tc.topY}}

overlaps = circle.OverlapsWithRect(*obj, rect)
if overlaps != tc.expResult {
t.Errorf("overlapWithRect %v (exp: %v) with x (%v), y (%v), rad (%v) in x (%v-%v) and y (%v-%v)",
overlaps, tc.expResult, x, y, circle.Radius, tc.botX, tc.topX, tc.botY, tc.topY)
}
})
}
}

var circleFromRendererTests = []struct {
name string
vertices []float32
expRadius float32
}{
{"200 square at origin", []float32{-100, -100, 0, 0, 1, 100, 100, 0, 1, 0,
-100, 100, 0, 0, 0, -100, -100, 0, 0, 1,
100, -100, 0, 1, 1, 100, 100, 0, 1, 0}, 65,
},
{"50 triangle top right of origin", []float32{0, 0, 0, 0, 1, 50, 50, 0, 1, 0,
0, 50, 0, 0, 0, 0, 0, 0, 0, 1}, 16.25,
},
{"1 square", []float32{0, 0, 0, 0, 1, 1, 1, 0, 1, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 1, 1, 1, 1, 0, 1, 0}, 0.325,
},
{"0 square", []float32{0, 0, 0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 1, 1, 0, 0, 0, 1, 0}, 0,
},
}

// TestCircleFromRenderer : generates circle primitives from
// a mocked renderer which only contains vertices
func TestCircleFromRenderer(t *testing.T) {
var circle Circle
var renderer *opengl.MeshRenderer
var err error

opengl.CreateMeshRenderer = fakes.CreateVerticesOnlyMeshRendererImpl

for _, tc := range circleFromRendererTests {
t.Run(tc.name, func(t *testing.T) {
renderer, err = opengl.CreateMeshRenderer("", "", []int{}, map[int]interface{}{}, tc.vertices)
circle.InitFromRenderer(renderer)

if circle.Radius != tc.expRadius {
t.Errorf("Circle radius is (%v) should be (%v)", circle.Radius, tc.expRadius)
}
})
}
}
82 changes: 46 additions & 36 deletions templates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,63 +5,73 @@ import (
"testing"

"github.com/go-gl/mathgl/mgl32"
"github.com/go-test/deep"
"github.com/leedenison/gologo/fakes"
"github.com/leedenison/gologo/opengl"
"github.com/leedenison/gologo/render"
)

var createTOTests = []struct {
templateType string
posX, posY float32
primitiveExp Primitive
rendererExp render.Renderer
name, templateType string
posX, posY float32
primitiveExp Primitive
rendererExp render.Renderer
errExp error
}{
{"SIMPLE_OBJECT", 200, 300, nil, nil},
{"PRIM_OBJECT", 200, 300, &Circle{Radius: 50}, nil},
{"simple object", "SIMPLE_OBJECT", 200, 300, nil, nil, nil},
{"defined circle", "CIRCLE_OBJECT", 200, 300, &Circle{Radius: 50}, nil, nil},
{"undefined circle and renderer", "UNDEF_CIRCLE_REND_OBJECT", 200, 300,
&Circle{Radius: 65},
&opengl.MeshRenderer{Shader: nil, Mesh: 0, Uniforms: nil,
MeshVertices: []float32{-100, -100, 0, 0, 1, 100, 100, 0, 1, 0,
-100, 100, 0, 0, 0, -100, -100, 0, 0, 1,
100, -100, 0, 1, 1, 100, 100, 0, 1, 0},
VertexCount: 6}, nil},
}

// TestCreateTemplateObject : Test basic Object creation by building the object
// TestCreateTemplateObject : Test Object creation by building the object
// from a template then reading values back out to confirm
// A simple object has no renderer
func TestCreateTemplateObject(t *testing.T) {
var position mgl32.Vec3
var obj *Object
var prim Primitive
var rend render.Renderer
var err error
var age int
var x, y float32
var diff []string

LoadObjectTemplates("testdata" + pathSeparator + "res")

for _, tt := range createTOTests {
position = mgl32.Vec3{tt.posX, tt.posY, 0.0}
obj, err = CreateTemplateObject(tt.templateType, position)
if err != nil {
t.Errorf("Obj (%v) create failed with error: %v", tt.templateType, err)
}
opengl.CreateMeshRenderer = fakes.CreateVerticesOnlyMeshRendererImpl

// Test object has age
age = obj.GetAge()
if age < 0 {
t.Errorf("Age was (%v) should not be negative", age)
}
for _, tc := range createTOTests {
t.Run(tc.name, func(t *testing.T) {
position = mgl32.Vec3{tc.posX, tc.posY, 0.0}
obj, err = CreateTemplateObject(tc.templateType, position)
if err != tc.errExp {
t.Errorf("Create object error was (%v) error should have been (%v)", err, tc.errExp)
}

// Test position
x, y = obj.GetPosition()
if x != tt.posX || y != tt.posY {
t.Errorf("Location was x (%v), y (%v) should be x (%v), y (%v)",
x, y, tt.posX, tt.posY)
}
// Test position
x, y = obj.GetPosition()
if x != tc.posX || y != tc.posY {
t.Errorf("Location was x (%v), y (%v) should be x (%v), y (%v)",
x, y, tc.posX, tc.posY)
}

// Check primitive
prim = obj.GetPrimitive()
if !reflect.DeepEqual(prim, tt.primitiveExp) {
t.Errorf("Primitive is (%+v) should be (%+v)", prim, tt.primitiveExp)
}
// Check primitive
prim = obj.GetPrimitive()
if !reflect.DeepEqual(prim, tc.primitiveExp) {
t.Errorf("Primitive is (%+v) should be (%+v)", prim, tc.primitiveExp)
}

// Check renderer
rend = obj.GetRenderer()
if !reflect.DeepEqual(rend, tt.rendererExp) {
t.Errorf("Renderer is (%+v) should be (%+v)", rend, tt.rendererExp)
}
// Check renderer
rend = obj.GetRenderer()

diff = deep.Equal(rend, tc.rendererExp)
if diff != nil {
t.Error("Generated renderer is different:", diff)
}
})
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"Name": "PRIM_OBJECT",
"Name": "CIRCLE_OBJECT",
"PhysicsPrimitiveType": "CIRCLE",
"PhysicsPrimitive": {
"Radius": 50.0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"Name": "ZEROPRIM_OBJECT",
"Name": "UNDEF_CIRCLE_OBJECT",
"PhysicsPrimitiveType": "CIRCLE",
"RendererType": "NONE"
}
18 changes: 18 additions & 0 deletions testdata/res/undef_circle_rend_object.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"Name": "UNDEF_CIRCLE_REND_OBJECT",
"PhysicsPrimitiveType": "CIRCLE",
"RendererType": "MESH_RENDERER",
"Renderer": {
"VertexShader": "ORTHO_VERTEX_SHADER",
"FragmentShader": "COLOR_FRAGMENT_SHADER",
"Color": [ 0, 0, 1, 1 ],
"MeshVertices": [
-100, -100, 0, 0, 1,
100, 100, 0, 1, 0,
-100, 100, 0, 0, 0,
-100, -100, 0, 0, 1,
100, -100, 0, 1, 1,
100, 100, 0, 1, 0
]
}
}