Browse Source

Merge branch 'master' into ffmpeg_encoding

legacy
Sam Hocevar 7 years ago
parent
commit
f42fda8281
86 changed files with 2576 additions and 2870 deletions
  1. +28
    -0
      .vscode/c_cpp_properties.json
  2. +15
    -0
      build/Lol (vs2015).sln
  3. +1
    -1
      doc/samples/btphystest.cpp
  4. +10
    -0
      doc/samples/meshviewer/imgui.ini
  5. +1
    -2
      doc/samples/meshviewer/meshviewer.cpp
  6. +39
    -49
      doc/samples/meshviewer/scenesetup.cpp
  7. +1
    -3
      doc/samples/meshviewer/scenesetup.h
  8. +5
    -5
      doc/samples/simplex.cpp
  9. +36
    -0
      doc/tutorial/02_cube.cpp
  10. +66
    -38
      doc/tutorial/14_lol_lua.cpp
  11. +1
    -1
      doc/tutorial/14_lol_lua.lua
  12. +11
    -13
      doc/tutorial/16_movie.cpp
  13. +2
    -2
      doc/tutorial/imgui.ini
  14. +1
    -1
      src/3rdparty/pegtl
  15. +3
    -2
      src/Makefile.am
  16. +3
    -3
      src/audio/audio.cpp
  17. +136
    -181
      src/debug/lines.cpp
  18. +5
    -1
      src/easymesh/easymesh.h
  19. +10
    -8
      src/easymesh/easymeshlua.cpp
  20. +84
    -603
      src/easymesh/easymeshlua.h
  21. +12
    -10
      src/gpu/framebuffer.cpp
  22. +31
    -0
      src/gpu/rendercontext.cpp
  23. +42
    -0
      src/gpu/renderer.cpp
  24. +8
    -8
      src/image/codec/android-image.cpp
  25. +22
    -19
      src/image/codec/dummy-image.cpp
  26. +23
    -17
      src/image/codec/gdiplus-image.cpp
  27. +23
    -16
      src/image/codec/imlib2-image.cpp
  28. +9
    -9
      src/image/codec/ios-image.cpp
  29. +38
    -30
      src/image/codec/oric-image.cpp
  30. +23
    -17
      src/image/codec/sdl-image.cpp
  31. +39
    -41
      src/image/codec/zed-image.cpp
  32. +26
    -21
      src/image/codec/zed-palette-image.cpp
  33. +47
    -45
      src/image/combine.cpp
  34. +17
    -15
      src/image/crop.cpp
  35. +37
    -35
      src/image/dither/dbs.cpp
  36. +24
    -22
      src/image/dither/ediff.cpp
  37. +28
    -26
      src/image/dither/ordered.cpp
  38. +14
    -12
      src/image/dither/ostromoukhov.cpp
  39. +13
    -11
      src/image/dither/random.cpp
  40. +50
    -48
      src/image/filter/colors.cpp
  41. +53
    -51
      src/image/filter/convolution.cpp
  42. +76
    -74
      src/image/filter/dilate.cpp
  43. +54
    -52
      src/image/filter/median.cpp
  44. +18
    -16
      src/image/filter/yuv.cpp
  45. +3
    -36
      src/image/image-private.h
  46. +63
    -143
      src/image/image.cpp
  47. +15
    -13
      src/image/kernel.cpp
  48. +1
    -1
      src/image/movie.cpp
  49. +12
    -10
      src/image/noise.cpp
  50. +33
    -33
      src/image/pixel.cpp
  51. +25
    -23
      src/image/resample.cpp
  52. +57
    -0
      src/image/resource-private.h
  53. +121
    -0
      src/image/resource.cpp
  54. +11
    -1
      src/input/input.cpp
  55. +6
    -1
      src/input/input.h
  56. +4
    -1
      src/lol-core.vcxproj
  57. +150
    -89
      src/lol/debug/lines.h
  58. +1
    -0
      src/lol/engine-internal.h
  59. +1
    -0
      src/lol/engine.h
  60. +1
    -1
      src/lol/gpu/framebuffer.h
  61. +4
    -0
      src/lol/gpu/rendercontext.h
  62. +12
    -0
      src/lol/gpu/renderer.h
  63. +1
    -0
      src/lol/image/all.h
  64. +74
    -71
      src/lol/image/image.h
  65. +1
    -1
      src/lol/image/movie.h
  66. +74
    -0
      src/lol/image/resource.h
  67. +26
    -0
      src/lol/legacy.h
  68. +9
    -7
      src/lol/sys/file.h
  69. +5
    -5
      src/lol/sys/threadtypes.h
  70. +78
    -2
      src/lolimgui.cpp
  71. +39
    -1
      src/lolimgui.h
  72. +8
    -6
      src/lolua/baselua.cpp
  73. +378
    -781
      src/lolua/baselua.h
  74. +18
    -13
      src/platform/sdl/sdlinput.cpp
  75. +12
    -51
      src/scene.cpp
  76. +1
    -7
      src/scene.h
  77. +11
    -9
      src/sys/file.cpp
  78. +7
    -0
      src/sys/init.cpp
  79. +2
    -2
      src/sys/threadtypes.cpp
  80. +7
    -7
      src/t/image/image.cpp
  81. +40
    -20
      src/textureimage.cpp
  82. +8
    -5
      src/textureimage.h
  83. +4
    -4
      src/tiler.h
  84. +52
    -11
      src/tileset.cpp
  85. +10
    -3
      src/tileset.h
  86. +6
    -4
      src/utils.h

+ 28
- 0
.vscode/c_cpp_properties.json View File

@@ -0,0 +1,28 @@
{
"configurations": [
{
"name": "Mac",
"includePath": ["/usr/include"],
"browse" : {
"limitSymbolsToIncludedHeaders" : true,
"databaseFilename" : ""
}
},
{
"name": "Linux",
"includePath": ["/usr/include"],
"browse" : {
"limitSymbolsToIncludedHeaders" : true,
"databaseFilename" : ""
}
},
{
"name": "Win32",
"includePath": ["c:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include", "src"],
"browse" : {
"limitSymbolsToIncludedHeaders" : true,
"databaseFilename" : ""
}
}
]
}

+ 15
- 0
build/Lol (vs2015).sln View File

@@ -66,6 +66,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{B629
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "15_lolimgui", "..\doc\tutorial\15_lolimgui.vcxproj", "{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "15_lolimgui", "..\doc\tutorial\15_lolimgui.vcxproj", "{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "14_lol_lua", "..\doc\tutorial\14_lol_lua.vcxproj", "{31B96262-1C41-43B9-BA38-27AA385B05DB}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ORBIS = Debug|ORBIS Debug|ORBIS = Debug|ORBIS
@@ -308,6 +310,18 @@ Global
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|Win32.Build.0 = Release|Win32 {81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|Win32.Build.0 = Release|Win32
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|x64.ActiveCfg = Release|x64 {81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|x64.ActiveCfg = Release|x64
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|x64.Build.0 = Release|x64 {81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|x64.Build.0 = Release|x64
{31B96262-1C41-43B9-BA38-27AA385B05DB}.Debug|ORBIS.ActiveCfg = Debug|ORBIS
{31B96262-1C41-43B9-BA38-27AA385B05DB}.Debug|ORBIS.Build.0 = Debug|ORBIS
{31B96262-1C41-43B9-BA38-27AA385B05DB}.Debug|Win32.ActiveCfg = Debug|Win32
{31B96262-1C41-43B9-BA38-27AA385B05DB}.Debug|Win32.Build.0 = Debug|Win32
{31B96262-1C41-43B9-BA38-27AA385B05DB}.Debug|x64.ActiveCfg = Debug|x64
{31B96262-1C41-43B9-BA38-27AA385B05DB}.Debug|x64.Build.0 = Debug|x64
{31B96262-1C41-43B9-BA38-27AA385B05DB}.Release|ORBIS.ActiveCfg = Release|ORBIS
{31B96262-1C41-43B9-BA38-27AA385B05DB}.Release|ORBIS.Build.0 = Release|ORBIS
{31B96262-1C41-43B9-BA38-27AA385B05DB}.Release|Win32.ActiveCfg = Release|Win32
{31B96262-1C41-43B9-BA38-27AA385B05DB}.Release|Win32.Build.0 = Release|Win32
{31B96262-1C41-43B9-BA38-27AA385B05DB}.Release|x64.ActiveCfg = Release|x64
{31B96262-1C41-43B9-BA38-27AA385B05DB}.Release|x64.Build.0 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -341,5 +355,6 @@ Global
{73F1A804-1116-46C3-922A-9C0ADEB33F52} = {4C4BD478-3767-4C27-BD91-DAAFE7CD03A2} {73F1A804-1116-46C3-922A-9C0ADEB33F52} = {4C4BD478-3767-4C27-BD91-DAAFE7CD03A2}
{B6297FF2-63D0-41EE-BE13-EFF720C9B0FA} = {1AFD580B-98B8-4689-B661-38C41132C60E} {B6297FF2-63D0-41EE-BE13-EFF720C9B0FA} = {1AFD580B-98B8-4689-B661-38C41132C60E}
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} {81C83B42-D00A-4FA3-9A3D-80F9D46524BF} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04}
{31B96262-1C41-43B9-BA38-27AA385B05DB} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

+ 1
- 1
doc/samples/btphystest.cpp View File

@@ -414,7 +414,7 @@ void BtPhysTest::TickGame(float seconds)
return; return;
} }


Debug::DrawSetupSegment(1.f);
auto context = Debug::DrawContext::New(Color::white, 1.f);
Debug::DrawGrid(vec3::zero, vec3::axis_x, vec3::axis_y, vec3::axis_z, 10.f); Debug::DrawGrid(vec3::zero, vec3::axis_x, vec3::axis_y, vec3::axis_z, 10.f);


if (m_controller->WasKeyReleasedThisFrame(BtPhysTestKeyInput::KEY_QUIT)) if (m_controller->WasKeyReleasedThisFrame(BtPhysTestKeyInput::KEY_QUIT))


+ 10
- 0
doc/samples/meshviewer/imgui.ini View File

@@ -0,0 +1,10 @@
[Debug]
Pos=60,60
Size=400,400
Collapsed=0

[Camera Setup]
Pos=60,60
Size=307,314
Collapsed=0


+ 1
- 2
doc/samples/meshviewer/meshviewer.cpp View File

@@ -384,8 +384,7 @@ void MeshViewer::TickDraw(float seconds, Scene &scene)


//Draw gizmos & grid //Draw gizmos & grid
Debug::DrawGizmo(vec3::zero, vec3::axis_x, vec3::axis_y, vec3::axis_z, 10.f); Debug::DrawGizmo(vec3::zero, vec3::axis_x, vec3::axis_y, vec3::axis_z, 10.f);
Debug::DrawSetupColor(Color::white);
Debug::DrawSetupSegment(1.f);
auto context = Debug::DrawContext::New(Color::white);
Debug::DrawGrid(vec3::zero, vec3::axis_x, vec3::axis_y, vec3::axis_z, 10.f); Debug::DrawGrid(vec3::zero, vec3::axis_x, vec3::axis_y, vec3::axis_z, 10.f);


/** OLD STUFF **/ /** OLD STUFF **/


+ 39
- 49
doc/samples/meshviewer/scenesetup.cpp View File

@@ -159,93 +159,83 @@ SceneSetupLuaObject::~SceneSetupLuaObject()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
SceneSetupLuaObject* SceneSetupLuaObject::New(lua_State* l, int arg_nb) SceneSetupLuaObject* SceneSetupLuaObject::New(lua_State* l, int arg_nb)
{ {
UNUSED(l);
UNUSED(arg_nb); UNUSED(arg_nb);
LuaStack s(l);
LuaString n;
s >> n;
return new SceneSetupLuaObject(n());
auto s = LuaStack::Begin(l);
auto n = s.Get<String>();
return new SceneSetupLuaObject(n);
} }


//-- Setup command ------------------------------------------------------------ //-- Setup command ------------------------------------------------------------
int SceneSetupLuaObject::AddLight(lua_State* l) int SceneSetupLuaObject::AddLight(lua_State* l)
{ {
LuaStack s(l);
LuaSSetupPtr o;
LuaString t;
s >> o >> t;
o->m_setup->AddLight(FindValue<LightType>(t().C()));
return 0;
auto s = LuaStack::Begin(l);
auto o = s.GetPtr<SceneSetupLuaObject>();
auto t = s.Get<String>();
o->m_setup->AddLight(FindValue<LightType>(t.C()));
return s.End();
} }
int SceneSetupLuaObject::SetupScene(lua_State* l) int SceneSetupLuaObject::SetupScene(lua_State* l)
{ {
LuaStack s(l);
LuaSSetupPtr o;
s >> o;
auto s = LuaStack::Begin(l);
auto o = s.GetPtr<SceneSetupLuaObject>();
o->m_setup->SetupScene(); o->m_setup->SetupScene();
return 0;
return s.End();
} }
//-- main funcs --------------------------------------------------------------- //-- main funcs ---------------------------------------------------------------
int SceneSetupLuaObject::SetPosition(lua_State* l) int SceneSetupLuaObject::SetPosition(lua_State* l)
{ {
LuaStack s(l);
LuaSSetupPtr o;
LuaVec3 c;
s >> o >> c;
auto s = LuaStack::Begin(l);
auto o = s.GetPtr<SceneSetupLuaObject>();
auto c = s.Get<vec3>();
o->m_setup->SetPosition(c); o->m_setup->SetPosition(c);
return 0;
return s.End();
} }
int SceneSetupLuaObject::SetLookAt(lua_State* l) int SceneSetupLuaObject::SetLookAt(lua_State* l)
{ {
LuaStack s(l);
LuaSSetupPtr o;
LuaVec3 c;
s >> o >> c;
auto s = LuaStack::Begin(l);
auto o = s.GetPtr<SceneSetupLuaObject>();
auto c = s.Get<vec3>();
o->m_setup->SetLookAt(c); o->m_setup->SetLookAt(c);
return 0;
return s.End();
} }
int SceneSetupLuaObject::SetColor(lua_State* l) int SceneSetupLuaObject::SetColor(lua_State* l)
{ {
LuaStack s(l);
LuaSSetupPtr o;
LuaColor c;
s >> o >> c;
auto s = LuaStack::Begin(l);
auto o = s.GetPtr<SceneSetupLuaObject>();
auto c = s.Get<vec4>();
o->m_setup->SetColor(c); o->m_setup->SetColor(c);
return 0;
return s.End();
} }
int SceneSetupLuaObject::Show(lua_State* l) int SceneSetupLuaObject::Show(lua_State* l)
{ {
LuaStack s(l);
LuaSSetupPtr o;
LuaDisplay e;
s >> o >> e;
auto s = LuaStack::Begin(l);
auto o = s.GetPtr<SceneSetupLuaObject>();
auto e = s.GetEnum<SceneSetup::DisplayBase>();
o->m_setup->Show(e); o->m_setup->Show(e);
return 0;
return s.End();
} }
int SceneSetupLuaObject::Hide(lua_State* l) int SceneSetupLuaObject::Hide(lua_State* l)
{ {
LuaStack s(l);
LuaSSetupPtr o;
LuaDisplay e;
s >> o >> e;
auto s = LuaStack::Begin(l);
auto o = s.GetPtr<SceneSetupLuaObject>();
auto e = s.GetEnum<SceneSetup::DisplayBase>();
o->m_setup->Hide(e); o->m_setup->Hide(e);
return 0;
return s.End();
} }
int SceneSetupLuaObject::Toggle(lua_State* l) int SceneSetupLuaObject::Toggle(lua_State* l)
{ {
LuaStack s(l);
LuaSSetupPtr o;
LuaDisplay e;
s >> o >> e;
auto s = LuaStack::Begin(l);
auto o = s.GetPtr<SceneSetupLuaObject>();
auto e = s.GetEnum<SceneSetup::DisplayBase>();
o->m_setup->Toggle(e); o->m_setup->Toggle(e);
return 0;
return s.End();
} }


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
const LuaObjectLib* SceneSetupLuaObject::GetLib()
const LuaObjectLibrary* SceneSetupLuaObject::GetLib()
{ {
typedef SceneSetupLuaObject SSLO; typedef SceneSetupLuaObject SSLO;
static const LuaObjectLib lib = LuaObjectLib(
static const LuaObjectLibrary lib = LuaObjectLibrary(
"SceneSetup", "SceneSetup",
//Statics //Statics
{ { nullptr, nullptr } }, { { nullptr, nullptr } },
@@ -264,7 +254,7 @@ const LuaObjectLib* SceneSetupLuaObject::GetLib()
}, },
//Variables //Variables
{ { nullptr, nullptr, nullptr } }); { { nullptr, nullptr, nullptr } });
return &lib;
return &lib;
} }


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -273,7 +263,7 @@ SceneSetupLuaLoader::SceneSetupLuaLoader() : LuaLoader()
{ {
lua_State* l = GetLuaState(); lua_State* l = GetLuaState();


LuaObjectDef::Register<SceneSetupLuaObject>(l);
LuaObjectHelper::Register<SceneSetupLuaObject>(l);
} }


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------


+ 1
- 3
doc/samples/meshviewer/scenesetup.h View File

@@ -103,12 +103,10 @@ public:
bool m_show_gizmo; bool m_show_gizmo;
bool m_show_lights; bool m_show_lights;
}; };
typedef Lolua::VarEnum<SceneSetup::DisplayBase> LuaDisplay;


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class SceneSetupLuaObject : public LuaObject class SceneSetupLuaObject : public LuaObject
{ {
typedef Lolua::VarPtr<SceneSetupLuaObject> LuaSSetupPtr;
public: public:
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
SceneSetupLuaObject(String& name); SceneSetupLuaObject(String& name);
@@ -116,7 +114,7 @@ public:


//------------------------------------------------------------------------- //-------------------------------------------------------------------------
static SceneSetupLuaObject* New(lua_State* l, int arg_nb); static SceneSetupLuaObject* New(lua_State* l, int arg_nb);
static const LuaObjectLib* GetLib();
static const LuaObjectLibrary* GetLib();


//------------------------------------------------------------------------- //-------------------------------------------------------------------------
public: public:


+ 5
- 5
doc/samples/simplex.cpp View File

@@ -1,7 +1,7 @@
// //
// Lol Engine — Simplex Noise tutorial // Lol Engine — Simplex Noise tutorial
// //
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
// © 2013-2014 Guillaume Bittoun <guillaume.bittoun@gmail.com> // © 2013-2014 Guillaume Bittoun <guillaume.bittoun@gmail.com>
// //
// Lol Engine is free software. It comes without any warranty, to // Lol Engine is free software. It comes without any warranty, to
@@ -31,8 +31,8 @@ int main(int argc, char **argv)
srand(time(nullptr)); srand(time(nullptr));


/* Create an image */ /* Create an image */
Image img(size);
array2d<vec4> &data = img.Lock2D<PixelFormat::RGBA_F32>();
image img(size);
array2d<vec4> &data = img.lock2d<PixelFormat::RGBA_F32>();


/* Declare plenty of allocators */ /* Declare plenty of allocators */
simplex_noise<2> s2; simplex_noise<2> s2;
@@ -141,7 +141,7 @@ int main(int argc, char **argv)
#endif #endif


/* Save image */ /* Save image */
img.Unlock2D(data);
img.Save("simplex.png");
img.unlock2d(data);
img.save("simplex.png");
} }



+ 36
- 0
doc/tutorial/02_cube.cpp View File

@@ -44,6 +44,22 @@ public:
4, 5, 1, 1, 0, 4, 3, 2, 6, 6, 7, 3, }), 4, 5, 1, 1, 0, 4, 3, 2, 6, 6, 7, 3, }),
m_ready(false) m_ready(false)
{ {
m_camera = new Camera();
m_camera->SetProjection(mat4::perspective(radians(30.f), 960.f, 600.f, .1f, 1000.f));
m_camera->SetView(mat4::lookat(vec3(-15.f, 5.f, 0.f),
vec3(0.f, -1.f, 0.f),
vec3(0.f, 1.f, 0.f)));
Scene& scene = Scene::GetScene();
scene.PushCamera(m_camera);
Ticker::Ref(m_camera);

}

~Cube()
{
Scene& scene = Scene::GetScene();
scene.PopCamera(m_camera);
Ticker::Unref(m_camera);
} }


virtual void TickGame(float seconds) virtual void TickGame(float seconds)
@@ -58,6 +74,25 @@ public:
mat4 proj = mat4::perspective(radians(45.0f), 640.0f, 480.0f, 0.1f, 10.0f); mat4 proj = mat4::perspective(radians(45.0f), 640.0f, 480.0f, 0.1f, 10.0f);


m_matrix = proj * view * model * anim; m_matrix = proj * view * model * anim;

{
auto context0 = Debug::DrawContext::New(Color::red);
{
auto context1 = Debug::DrawContext::New(Color::blue);
Debug::DrawBox(box3(vec3(0.f), vec3(1.2f)));
Debug::DrawGrid(vec3(0.f), vec3::axis_x, vec3::axis_y, vec3::axis_z, 10.0f);
{
auto context2 = Debug::DrawContext::New(context0);
Debug::DrawBox(box3(vec3(0.f), vec3(1.3f)));
}
{
auto context2 = Debug::DrawContext::New(context0);
context2.SetColor(Color::yellow);
Debug::DrawBox(box3(vec3(-1.f), vec3(1.4f)));
}
}
Debug::DrawBox(box3(vec3(0.f), vec3(1.1f)));
}
} }


virtual void TickDraw(float seconds, Scene &scene) virtual void TickDraw(float seconds, Scene &scene)
@@ -115,6 +150,7 @@ public:
} }


private: private:
Camera* m_camera = nullptr;
float m_angle; float m_angle;
mat4 m_matrix; mat4 m_matrix;
array<vec3,vec3> m_mesh; array<vec3,vec3> m_mesh;


+ 66
- 38
doc/tutorial/14_lol_lua.cpp View File

@@ -1,7 +1,7 @@
// //
// Lol Engine — Lua tutorial // Lol Engine — Lua tutorial
// //
// Copyright © 2014—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
// Copyright © 2014—2017 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
// //
// Lol Engine is free software. It comes without any warranty, to // Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it // the extent permitted by applicable law. You can redistribute it
@@ -23,7 +23,6 @@ using namespace lol;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class DemoObject : public LuaObject class DemoObject : public LuaObject
{ {
typedef Lolua::VarPtr<DemoObject> LuaDemoObjectPtr;
public: public:
DemoObject() : LuaObject() {} DemoObject() : LuaObject() {}
virtual ~DemoObject() {} virtual ~DemoObject() {}
@@ -37,47 +36,67 @@ public:
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
static int AddFive(lua_State* l) static int AddFive(lua_State* l)
{ {
LuaInt32 i; i.Get(l, 1);
auto stack = LuaStack::Begin(l);
int32_t i = stack.Get<int32_t>();

i += 5; i += 5;
return i.Return(l);

return (stack << i).End();
} }
static int AddTenInstance(lua_State* l)

LOLUA_DECLARE_RETURN_METHOD_ARGS(AddTenInstance, GetPtr<DemoObject>(), AddTenMethod, Get<float>(), Get<int32_t>(), Get<int32_t>());
static int _AddTenInstance(lua_State* l)
{ {
LuaStack stack(l);
LuaDemoObjectPtr obj;
LuaFloat f;
stack >> obj >> f;
f = obj->AddTenMethod(f);
return f.Return(l);
auto stack = LuaStack::Begin(l);
DemoObject* obj = stack.GetPtr<DemoObject>();
float f = stack.Get<float>();
int32_t i = stack.Get<int32_t>();
int32_t i2 = stack.Get<int32_t>();

f = obj->AddTenMethod(f, i, i2);

return (stack << f).End();
} }
float AddTenMethod(float f)

float AddTenMethod(float f, int32_t i, int32_t i2)
{ {
UNUSED(i, i2);
return (f + 10); return (f + 10);
} }


static int GetX(lua_State* l) static int GetX(lua_State* l)
{ {
LuaStack stack(l);
LuaDemoObjectPtr obj;
LuaInt32 i;
stack >> obj;
auto stack = LuaStack::Begin(l);
DemoObject* obj = stack.GetPtr<DemoObject>();
auto i = stack.Get<int32_t>();
i = obj->m_x; i = obj->m_x;
return stack << i;

return (stack << i).End();
} }
static int SetX(lua_State* l)

LOLUA_DECLARE_VOID_METHOD_ARGS(SetX, GetPtr<DemoObject>(), SetXMethod, Get<int32_t>());
static int _SetX(lua_State* l)
{ {
LuaStack stack(l);
LuaDemoObjectPtr obj;
LuaInt32 i;
stack >> obj >> i;
auto stack = LuaStack::Begin(l);
DemoObject* obj = stack.GetPtr<DemoObject>();
auto i = stack.Get<int32_t>();
obj->m_x = i; obj->m_x = i;
return 0;

return stack.End();
}

void SetXMethod(int32_t i)
{
m_x = i;
} }



//------------------------------------------------------------------------- //-------------------------------------------------------------------------
static const LuaObjectLib* GetLib()
static const LuaObjectLibrary* GetLib()
{ {
static const LuaObjectLib lib = LuaObjectLib(
static const LuaObjectLibrary lib = LuaObjectLibrary(
"LoluaDemo", "LoluaDemo",
{ { "AddFive", &DemoObject::AddFive } }, { { "AddFive", &DemoObject::AddFive } },
{ { "AddTenInstance", &DemoObject::AddTenInstance } }, { { "AddTenInstance", &DemoObject::AddTenInstance } },
@@ -91,9 +110,12 @@ public:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static int GlobalAddString(lua_State* l) static int GlobalAddString(lua_State* l)
{ {
LuaString s; s.Get(l, 1);
s() += "_added";
return s.Return(l);
auto stack = LuaStack::Begin(l);
auto s = stack.Get<String>();

s += "_added";

return (stack << s).End();
} }


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -105,7 +127,7 @@ public:
lua_State* l = GetLuaState(); lua_State* l = GetLuaState();


//Registering demo object //Registering demo object
LuaObjectDef::Register<DemoObject>(l);
LuaObjectHelper::Register<DemoObject>(l);


//Registering function //Registering function
LuaFunction add_string(l, "GlobalAddString", &GlobalAddString); LuaFunction add_string(l, "GlobalAddString", &GlobalAddString);
@@ -158,27 +180,33 @@ public:
demo_loader->TestStuff(); demo_loader->TestStuff();


//Grab global test values //Grab global test values
float testvalue_num = demo_loader->GetVar<float>("testvalue_num");
int32_t testvalue_int = demo_loader->GetVar<int32_t>("testvalue_int");
uint32_t testvalue_uint = demo_loader->GetVar<uint32_t>("testvalue_uint");
String testvalue_str = demo_loader->GetVar<String>("testvalue_str");
float testvalue_num = demo_loader->Get<float>("testvalue_num");
int32_t testvalue_int = demo_loader->Get<int32_t>("testvalue_int");
uint32_t testvalue_uint = demo_loader->Get<uint32_t>("testvalue_uint");
String testvalue_str = demo_loader->Get<String>("testvalue_str");


//Grab string modified with function //Grab string modified with function
String function_return = demo_loader->GetVar<String>("function_return");
String function_return = demo_loader->Get<String>("function_return");


//Grab global values modified with DemoObject //Grab global values modified with DemoObject
int32_t loluademo_return = demo_loader->GetVar<int32_t>("loluademo_return");
int32_t loluademo_getx = demo_loader->GetVar<int32_t>("loluademo_getx");
float loluademo_inst_return = demo_loader->GetVar<float>("loluademo_inst_return");
int32_t loluademo_return = demo_loader->Get<int32_t>("loluademo_return");
int32_t loluademo_getx = demo_loader->Get<int32_t>("loluademo_getx");
float loluademo_inst_return = demo_loader->Get<float>("loluademo_inst_return");
DemoObject* loluademo_inst = demo_loader->GetPtr<DemoObject>("loluademo_inst"); DemoObject* loluademo_inst = demo_loader->GetPtr<DemoObject>("loluademo_inst");


msg::info("Lua Vars: \ msg::info("Lua Vars: \
testvalue_num: %.2f, testvalue_int: %i, testvalue_uint: %i, testvalue_str: %s.\n", testvalue_num: %.2f, testvalue_int: %i, testvalue_uint: %i, testvalue_str: %s.\n",
testvalue_num, testvalue_int, testvalue_uint, testvalue_str.C()); testvalue_num, testvalue_int, testvalue_uint, testvalue_str.C());
msg::info("Lua Vars: \ msg::info("Lua Vars: \
function_return: %s, loluademo_return: %i, loluademo_inst_return: %.f, loluademo_getx: %i, loluademo_inst->m_x: %i.\n",
function_return: %s, loluademo_return: %i, loluademo_inst_return: %.2f, loluademo_getx: %i, loluademo_inst->m_x: %i.\n",
function_return.C(), loluademo_return, loluademo_inst_return, loluademo_getx, loluademo_inst->m_x); function_return.C(), loluademo_return, loluademo_inst_return, loluademo_getx, loluademo_inst->m_x);


#define /***/ _LOLUA_ARG_1(a00) (float)a00
#define /***/ _LOLUA_ARG_2(a00, a01) _LOLUA_ARG_1(a00), _LOLUA_ARG_1(a01)
#define /***/ _LOLUA_ARG_3(a00, a01, a02) _LOLUA_ARG_1(a00), _LOLUA_ARG_2(a01, a02)
#define /***/ _LOLUA_ARG_4(a00, a01, a02, a03) _LOLUA_ARG_1(a00), _LOLUA_ARG_3(a01, a02, a03)
msg::info("_LOLUA_ARG_1: %f, %f, %f, %f\n", _LOLUA_ARG_4(0, 1, 2, 3));

delete demo_loader; delete demo_loader;


Ticker::Shutdown(); Ticker::Shutdown();


+ 1
- 1
doc/tutorial/14_lol_lua.lua View File

@@ -13,4 +13,4 @@ loluademo_return = LoluaDemo.AddFive(1);
loluademo_inst = LoluaDemo.New(); loluademo_inst = LoluaDemo.New();
loluademo_inst:SetX(10); loluademo_inst:SetX(10);
loluademo_getx = loluademo_inst:GetX(); loluademo_getx = loluademo_inst:GetX();
loluademo_inst_return = loluademo_inst:AddTenInstance(2.0);
loluademo_inst_return = loluademo_inst:AddTenInstance(2.5, 4, 6);

+ 11
- 13
doc/tutorial/16_movie.cpp View File

@@ -56,14 +56,12 @@ public:


bool open_file(char const *filename) bool open_file(char const *filename)
{ {
avformat_alloc_output_context2(&m_avformat, nullptr, nullptr, filename);
/* Third argument specifies format */
avformat_alloc_output_context2(&m_avformat, nullptr, "gif", filename);
if (!m_avformat) if (!m_avformat)
{ {
msg::debug("could not deduce output format from file extension %s: using GIF\n", filename);
avformat_alloc_output_context2(&m_avformat, nullptr, "gif", filename);

if (!m_avformat)
return false;
msg::debug("could not create output context");
return false;
} }


if (!open_codec()) if (!open_codec())
@@ -89,7 +87,7 @@ public:
return true; return true;
} }


bool push_image(Image &im)
bool push_image(image &im)
{ {
// Make sure the encoder does not hold a reference on our // Make sure the encoder does not hold a reference on our
// frame (GIF does that in order to compress using deltas). // frame (GIF does that in order to compress using deltas).
@@ -97,10 +95,10 @@ public:
return false; return false;


// Convert image to 3:3:2. TODO: add some dithering // Convert image to 3:3:2. TODO: add some dithering
u8vec3 *data = im.Lock<PixelFormat::RGB_8>();
for (int n = 0; n < im.GetSize().x * im.GetSize().y; ++n)
u8vec3 *data = im.lock<PixelFormat::RGB_8>();
for (int n = 0; n < im.size().x * im.size().y; ++n)
m_frame->data[0][n] = (data[n].r & 0xe0) | ((data[n].g & 0xe0) >> 3) | (data[n].b >> 6); m_frame->data[0][n] = (data[n].r & 0xe0) | ((data[n].g & 0xe0) >> 3) | (data[n].b >> 6);
im.Unlock(data);
im.unlock(data);


m_frame->pts = m_index++; m_frame->pts = m_index++;


@@ -234,9 +232,9 @@ int main(int argc, char **argv)


for (int i = 0; i < 256; ++i) for (int i = 0; i < 256; ++i)
{ {
Image im(size);
image im(size);


array2d<u8vec3> &data = im.Lock2D<PixelFormat::RGB_8>();
array2d<u8vec3> &data = im.lock2d<PixelFormat::RGB_8>();
for (int y = 0; y < size.y; ++y) for (int y = 0; y < size.y; ++y)
for (int x = 0; x < size.x; ++x) for (int x = 0; x < size.x; ++x)
{ {
@@ -244,7 +242,7 @@ int main(int argc, char **argv)
data[x][y].g = x / 4 * 4 * y / 16 + i; data[x][y].g = x / 4 * 4 * y / 16 + i;
data[x][y].b = y + i; data[x][y].b = y + i;
} }
im.Unlock2D(data);
im.unlock2d(data);


if (!enc.push_image(im)) if (!enc.push_image(im))
break; break;


+ 2
- 2
doc/tutorial/imgui.ini View File

@@ -4,12 +4,12 @@ Size=400,400
Collapsed=0 Collapsed=0


[testature] [testature]
Pos=266,15
Pos=187,98
Size=494,359 Size=494,359
Collapsed=0 Collapsed=0


[SO FUN !!] [SO FUN !!]
Pos=30,24
Pos=16,24
Size=113,99 Size=113,99
Collapsed=0 Collapsed=0



+ 1
- 1
src/3rdparty/pegtl

@@ -1 +1 @@
Subproject commit e5f8968013e17a41aeed47ee1904c42ab1f452e2
Subproject commit 267e992c17074a1afdc35ac361f7dd7525c37939

+ 3
- 2
src/Makefile.am View File

@@ -28,7 +28,7 @@ liblol_core_a_SOURCES = \
liblol_core_a_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/3rdparty/bullet3/src -I$(srcdir)/3rdparty/lua/src liblol_core_a_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/3rdparty/bullet3/src -I$(srcdir)/3rdparty/lua/src


liblol_core_headers = \ liblol_core_headers = \
lol/engine-internal.h lol/engine.h lol/public.h lol/extras.h \
lol/engine-internal.h lol/engine.h lol/public.h lol/extras.h lol/legacy.h \
\ \
lol/base/all.h \ lol/base/all.h \
lol/base/avl_tree.h lol/base/features.h lol/base/tuple.h lol/base/types.h \ lol/base/avl_tree.h lol/base/features.h lol/base/tuple.h lol/base/types.h \
@@ -54,7 +54,7 @@ liblol_core_headers = \
lol/sys/threadtypes.h lol/sys/timer.h \ lol/sys/threadtypes.h lol/sys/timer.h \
\ \
lol/image/all.h \ lol/image/all.h \
lol/image/pixel.h lol/image/color.h lol/image/image.h lol/image/movie.h \
lol/image/pixel.h lol/image/color.h lol/image/image.h lol/image/resource.h lol/image/movie.h \
\ \
lol/gpu/all.h \ lol/gpu/all.h \
lol/gpu/shader.h lol/gpu/indexbuffer.h lol/gpu/vertexbuffer.h \ lol/gpu/shader.h lol/gpu/indexbuffer.h lol/gpu/vertexbuffer.h \
@@ -115,6 +115,7 @@ liblol_core_sources = \
sys/init.cpp sys/file.cpp sys/hacks.cpp \ sys/init.cpp sys/file.cpp sys/hacks.cpp \
sys/thread.cpp sys/threadtypes.cpp sys/getopt.cpp \ sys/thread.cpp sys/threadtypes.cpp sys/getopt.cpp \
\ \
image/resource.cpp image/resource-private.h \
image/image.cpp image/image-private.h image/kernel.cpp image/pixel.cpp \ image/image.cpp image/image-private.h image/kernel.cpp image/pixel.cpp \
image/crop.cpp image/resample.cpp image/noise.cpp image/combine.cpp \ image/crop.cpp image/resample.cpp image/noise.cpp image/combine.cpp \
image/codec/gdiplus-image.cpp image/codec/imlib2-image.cpp \ image/codec/gdiplus-image.cpp image/codec/imlib2-image.cpp \


+ 3
- 3
src/audio/audio.cpp View File

@@ -33,6 +33,7 @@ struct audio_streamer
int m_channel; int m_channel;
std::function<void(void *, int)> m_callback; std::function<void(void *, int)> m_callback;
#if defined LOL_USE_SDL_MIXER #if defined LOL_USE_SDL_MIXER
array<uint8_t> m_empty; // SDL keeps a reference to this
Mix_Chunk *m_chunk; Mix_Chunk *m_chunk;
#endif #endif
}; };
@@ -95,9 +96,8 @@ int audio::start_streaming(std::function<void(void *, int)> const &f)
audio_streamer *s = new audio_streamer(); audio_streamer *s = new audio_streamer();
g_streamers.push(s); g_streamers.push(s);


array<uint8_t> empty;
empty.resize(1024);
s->m_chunk = Mix_QuickLoad_RAW(empty.data(), empty.bytes());
s->m_empty.resize(1024);
s->m_chunk = Mix_QuickLoad_RAW(s->m_empty.data(), s->m_empty.bytes());
s->m_channel = Mix_PlayChannel(-1, s->m_chunk, -1); s->m_channel = Mix_PlayChannel(-1, s->m_chunk, -1);
s->m_callback = f; s->m_callback = f;
Mix_RegisterEffect(s->m_channel, trampoline, nullptr, s); Mix_RegisterEffect(s->m_channel, trampoline, nullptr, s);


+ 136
- 181
src/debug/lines.cpp View File

@@ -12,60 +12,14 @@


namespace lol namespace lol
{ {
Debug::DrawContext::Data Debug::DrawContext::m_global = Debug::DrawContext::Data(vec4(1.f));


//Resets draw infos
void Debug::DrawSetupReset()
{
Scene& scene = Scene::GetScene();
scene.SetLineTime();
scene.SetLineMask();
}
//Sets draw infos
void Debug::DrawSetupTime(float new_time)
{
Scene& scene = Scene::GetScene();
scene.SetLineTime(new_time);
}

//--
void Debug::DrawSetupMask(int new_mask)
{
Scene& scene = Scene::GetScene();
scene.SetLineMask(new_mask);
}

//--
void Debug::DrawSetupSegment(float new_segment_size)
{
Scene& scene = Scene::GetScene();
scene.SetLineSegmentSize(new_segment_size);
}

//--
void Debug::DrawSetupColor(vec4 color)
{
Scene& scene = Scene::GetScene();
scene.SetLineColor(color);
}

//--
void Debug::DrawSetup(float new_time, int new_mask, float segment_size, vec4 color)
{
Debug::DrawSetupTime(new_time);
Debug::DrawSetupMask(new_mask);
Debug::DrawSetupSegment(segment_size);
Debug::DrawSetupColor(color);
}
typedef Debug::DrawContext DC;
typedef Debug::DrawContext::Data DCD;


//Screen to world conversion //Screen to world conversion
vec3 Debug::WorldToScreen(vec3 pos)
{
return Debug::WorldToScreen(vec4(pos, 1.f));
}
vec3 Debug::WorldToScreen(vec3 pos, mat4 view_proj)
{
return Debug::WorldToScreen(vec4(pos, 1.f), view_proj);
}
vec3 Debug::WorldToScreen(vec3 pos) { return Debug::WorldToScreen(vec4(pos, 1.f)); }
vec3 Debug::WorldToScreen(vec3 pos, mat4 view_proj) { return Debug::WorldToScreen(vec4(pos, 1.f), view_proj); }
vec3 Debug::WorldToScreen(vec4 pos) vec3 Debug::WorldToScreen(vec4 pos)
{ {
Scene& scene = Scene::GetScene(); Scene& scene = Scene::GetScene();
@@ -81,8 +35,7 @@ vec3 Debug::WorldToScreen(vec4 pos, mat4 view_proj)
} }


//-- //--
vec3 Debug::ScreenToWorld(vec2 pos, float z)
{ return Debug::ScreenToWorld(vec3(pos, z)); }
vec3 Debug::ScreenToWorld(vec2 pos, float z) { return Debug::ScreenToWorld(vec3(pos, z)); }
vec3 Debug::ScreenToWorld(vec3 pos) vec3 Debug::ScreenToWorld(vec3 pos)
{ {
Scene& scene = Scene::GetScene(); Scene& scene = Scene::GetScene();
@@ -91,8 +44,7 @@ vec3 Debug::ScreenToWorld(vec3 pos)
mat4 const inv_view_proj = inverse(scene.GetCamera()->GetProjection() * scene.GetCamera()->GetView()); mat4 const inv_view_proj = inverse(scene.GetCamera()->GetProjection() * scene.GetCamera()->GetView());
return Debug::ScreenToWorld(pos, inv_view_proj); return Debug::ScreenToWorld(pos, inv_view_proj);
} }
vec3 Debug::ScreenToWorld(vec2 pos, mat4 inv_view_proj, float z)
{ return Debug::ScreenToWorld(vec3(pos, z), inv_view_proj); }
vec3 Debug::ScreenToWorld(vec2 pos, mat4 inv_view_proj, float z) { return Debug::ScreenToWorld(vec3(pos, z), inv_view_proj); }
vec3 Debug::ScreenToWorld(vec3 pos, mat4 inv_view_proj) vec3 Debug::ScreenToWorld(vec3 pos, mat4 inv_view_proj)
{ {
vec4 screen_pos = inv_view_proj * vec4(pos, 1.f); vec4 screen_pos = inv_view_proj * vec4(pos, 1.f);
@@ -107,12 +59,16 @@ vec3 Debug::ScreenToWorld(vec3 pos, mat4 view, mat4 proj)
//Draw stuff in World //Draw stuff in World
//-- LINE: 3D -2D - 3D_to_2D -------------------------------------------------- //-- LINE: 3D -2D - 3D_to_2D --------------------------------------------------


void Debug::DrawLine(vec3 a, vec3 b) { Scene& scene = Scene::GetScene(); Debug::DrawLine(a, b, scene.GetLineColor()); }
void Debug::DrawLine(vec2 a, vec3 b, float az) { Scene& scene = Scene::GetScene(); Debug::DrawLine(a, b, scene.GetLineColor(), az); }
void Debug::DrawLine(vec2 a, vec2 b, float az, float bz) { Scene& scene = Scene::GetScene(); Debug::DrawLine(a, b, scene.GetLineColor(), az, bz); }
void Debug::DrawLine(vec3 a, vec3 b, vec4 color) { Scene& scene = Scene::GetScene(); scene.AddLine(a, b, color); }
void Debug::DrawLine(vec2 a, vec3 b, vec4 color, float az) { Scene& scene = Scene::GetScene(); scene.AddLine(vec3(a, az), b, color); }
void Debug::DrawLine(vec2 a, vec2 b, vec4 color, float az, float bz){ Scene& scene = Scene::GetScene(); scene.AddLine(vec3(a, az), vec3(b, bz), color); }
//Root func
void Debug::DrawLine(vec3 a, vec3 b, DCD data)
{
Scene::GetScene().AddLine(a, b, data.m_color, data.m_duration, data.m_mask);
}
void Debug::DrawLine(vec2 a, vec3 b, DCD data, float az) { DrawLine(vec3(a, az), b, data); }
void Debug::DrawLine(vec2 a, vec2 b, DCD data, float az, float bz) { DrawLine(vec3(a, az), vec3(b, bz), data); }
void Debug::DrawLine(vec3 a, vec3 b) { DrawLine(a, b, DC::GetGlobalData()); }
void Debug::DrawLine(vec2 a, vec3 b, float az) { DrawLine(a, b, DC::GetGlobalData(), az); }
void Debug::DrawLine(vec2 a, vec2 b, float az, float bz) { DrawLine(a, b, DC::GetGlobalData(), az, bz); }


//-- GIZMO -------------------------------------------------------------------- //-- GIZMO --------------------------------------------------------------------
void Debug::DrawGizmo(vec3 pos, vec3 x, vec3 y, vec3 z, float size) void Debug::DrawGizmo(vec3 pos, vec3 x, vec3 y, vec3 z, float size)
@@ -131,8 +87,7 @@ void Debug::DrawGizmo(vec2 pos, vec3 x, vec3 y, vec3 z, float size, float posz)
//-- GRID --------------------------------------------------------------------- //-- GRID ---------------------------------------------------------------------
void Debug::DrawGrid(vec3 pos, vec3 x, vec3 y, vec3 z, float size, bool draw_3d) void Debug::DrawGrid(vec3 pos, vec3 x, vec3 y, vec3 z, float size, bool draw_3d)
{ {
Scene& scene = Scene::GetScene();
float seg_sz = scene.GetLineSegmentSize();
float seg_sz = DC::GetGlobalData().m_segment_size;
int seg_nb = lol::max((int)(size / seg_sz), 1); int seg_nb = lol::max((int)(size / seg_sz), 1);
seg_sz = size / (float)seg_nb; seg_sz = size / (float)seg_nb;


@@ -165,38 +120,38 @@ void Debug::DrawGrid(vec3 pos, vec3 x, vec3 y, vec3 z, float size, bool draw_3d)
} }


//-- ARROW: 3D -2D - 3D_to_2D ------------------------------------------------- //-- ARROW: 3D -2D - 3D_to_2D -------------------------------------------------
void Debug::DrawArrow(vec3 a, vec3 b, vec2 s) { Debug::DrawArrow(a, b, vec3(s.x, s.y, s.y)); }
void Debug::DrawArrow(vec2 a, vec3 b, vec2 s, float az) { Debug::DrawArrow(a, b.xy, vec3(s.x, s.y, s.y), az, b.z); }
void Debug::DrawArrow(vec2 a, vec2 b, vec2 s, float az, float bz) { Debug::DrawArrow(a, b, vec3(s.x, s.y, s.y), az, bz); }
void Debug::DrawArrow(vec3 a, vec3 b, vec3 s) { Scene& scene = Scene::GetScene(); Debug::DrawArrow(a, b, vec3(s.x, s.y, s.y), scene.GetLineColor()); }
void Debug::DrawArrow(vec2 a, vec3 b, vec3 s, float az) { Scene& scene = Scene::GetScene(); Debug::DrawArrow(a, b.xy, vec3(s.x, s.y, s.y), scene.GetLineColor(), az, b.z); }
void Debug::DrawArrow(vec2 a, vec2 b, vec3 s, float az, float bz) { Scene& scene = Scene::GetScene(); Debug::DrawArrow(a, b, vec3(s.x, s.y, s.y), scene.GetLineColor(), az, bz); }
void Debug::DrawArrow(vec3 a, vec3 b, vec3 s, vec4 color)
void Debug::DrawArrow(vec3 a, vec3 b, vec2 s) { Debug::DrawArrow(a, b, vec3(s.x, s.y, s.y)); }
void Debug::DrawArrow(vec2 a, vec3 b, vec2 s, float az) { Debug::DrawArrow(a, b.xy, vec3(s.x, s.y, s.y), az, b.z); }
void Debug::DrawArrow(vec2 a, vec2 b, vec2 s, float az, float bz) { Debug::DrawArrow(a, b, vec3(s.x, s.y, s.y), az, bz); }
void Debug::DrawArrow(vec3 a, vec3 b, vec3 s) { Debug::DrawArrow(a, b, vec3(s.x, s.y, s.y), DC::GetGlobalData()); }
void Debug::DrawArrow(vec2 a, vec3 b, vec3 s, float az) { Debug::DrawArrow(a, b.xy, vec3(s.x, s.y, s.y), DC::GetGlobalData(), az, b.z); }
void Debug::DrawArrow(vec2 a, vec2 b, vec3 s, float az, float bz) { Debug::DrawArrow(a, b, vec3(s.x, s.y, s.y), DC::GetGlobalData(), az, bz); }
void Debug::DrawArrow(vec3 a, vec3 b, vec3 s, DCD data)
{ {
vec3 z = s.x * normalize(b - a); vec3 z = s.x * normalize(b - a);
vec3 x = s.z * orthonormal(b - a); vec3 x = s.z * orthonormal(b - a);
vec3 y = s.y * cross(normalize(x), normalize(z)); vec3 y = s.y * cross(normalize(x), normalize(z));


Debug::DrawLine(a, b, color);
Debug::DrawLine(b, b - z + x, color);
Debug::DrawLine(b, b - z - x, color);
Debug::DrawLine(b, b - z + y, color);
Debug::DrawLine(b, b - z - y, color);
Debug::DrawLine(a, b, data);
Debug::DrawLine(b, b - z + x, data);
Debug::DrawLine(b, b - z - x, data);
Debug::DrawLine(b, b - z + y, data);
Debug::DrawLine(b, b - z - y, data);


Debug::DrawLine(b - z + x, b - z + y, color);
Debug::DrawLine(b - z + x, b - z - y, color);
Debug::DrawLine(b - z - x, b - z + y, color);
Debug::DrawLine(b - z - x, b - z - y, color);
Debug::DrawLine(b - z + x, b - z + y, data);
Debug::DrawLine(b - z + x, b - z - y, data);
Debug::DrawLine(b - z - x, b - z + y, data);
Debug::DrawLine(b - z - x, b - z - y, data);


Debug::DrawLine(b - z + x, b - z - x, color);
Debug::DrawLine(b - z + y, b - z - y, color);
Debug::DrawLine(b - z + x, b - z - x, data);
Debug::DrawLine(b - z + y, b - z - y, data);
} }
void Debug::DrawArrow(vec2 a, vec3 b, vec3 s, vec4 color, float az)
void Debug::DrawArrow(vec2 a, vec3 b, vec3 s, DCD data, float az)
{ {
vec3 bn = Debug::WorldToScreen(b); vec3 bn = Debug::WorldToScreen(b);
DrawArrow(a, bn.xy, s, color, az, bn.z);
DrawArrow(a, bn.xy, s, data, az, bn.z);
} }
void Debug::DrawArrow(vec2 a, vec2 b, vec3 s, vec4 color, float az, float bz)
void Debug::DrawArrow(vec2 a, vec2 b, vec3 s, DCD data, float az, float bz)
{ {
vec3 an = vec3(a, az); vec3 an = vec3(a, az);
vec3 bn = vec3(b, bz); vec3 bn = vec3(b, bz);
@@ -204,40 +159,40 @@ void Debug::DrawArrow(vec2 a, vec2 b, vec3 s, vec4 color, float az, float bz)
vec3 x = s.z * orthonormal(bn - an); vec3 x = s.z * orthonormal(bn - an);
vec3 y = s.y * cross(normalize(x), normalize(z)); vec3 y = s.y * cross(normalize(x), normalize(z));


Debug::DrawLine(a, b, color, az, bz);
Debug::DrawLine(b, b - (z + x).xy, color, bz, bz - (z + x).z);
Debug::DrawLine(b, b - (z - x).xy, color, bz, bz - (z - x).z);
Debug::DrawLine(b, b - (z + y).xy, color, bz, bz - (z + y).z);
Debug::DrawLine(b, b - (z - y).xy, color, bz, bz - (z - y).z);
Debug::DrawLine(a, b, data, az, bz);
Debug::DrawLine(b, b - (z + x).xy, data, bz, bz - (z + x).z);
Debug::DrawLine(b, b - (z - x).xy, data, bz, bz - (z - x).z);
Debug::DrawLine(b, b - (z + y).xy, data, bz, bz - (z + y).z);
Debug::DrawLine(b, b - (z - y).xy, data, bz, bz - (z - y).z);


Debug::DrawLine(b - (z + x).xy, b - (z + y).xy, color, bz - (z + x).z, bz - (z + y).z);
Debug::DrawLine(b - (z + x).xy, b - (z - y).xy, color, bz - (z + x).z, bz - (z - y).z);
Debug::DrawLine(b - (z - x).xy, b - (z + y).xy, color, bz - (z - x).z, bz - (z + y).z);
Debug::DrawLine(b - (z - x).xy, b - (z - y).xy, color, bz - (z - x).z, bz - (z - y).z);
Debug::DrawLine(b - (z + x).xy, b - (z + y).xy, data, bz - (z + x).z, bz - (z + y).z);
Debug::DrawLine(b - (z + x).xy, b - (z - y).xy, data, bz - (z + x).z, bz - (z - y).z);
Debug::DrawLine(b - (z - x).xy, b - (z + y).xy, data, bz - (z - x).z, bz - (z + y).z);
Debug::DrawLine(b - (z - x).xy, b - (z - y).xy, data, bz - (z - x).z, bz - (z - y).z);


Debug::DrawLine(b - (z + x).xy, b - (z - x).xy, color, bz - (z + x).z, bz - (z - x).z);
Debug::DrawLine(b - (z + y).xy, b - (z - y).xy, color, bz - (z + y).z, bz - (z - y).z);
Debug::DrawLine(b - (z + x).xy, b - (z - x).xy, data, bz - (z + x).z, bz - (z - x).z);
Debug::DrawLine(b - (z + y).xy, b - (z - y).xy, data, bz - (z + y).z, bz - (z - y).z);
} }


//-- BOX: 3D -2D - 3D_to_2D --------------------------------------------------- //-- BOX: 3D -2D - 3D_to_2D ---------------------------------------------------
void Debug::DrawBox(box3 a) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a.aa, a.bb, scene.GetLineColor()); }
void Debug::DrawBox(box2 a) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a.aa, a.bb, scene.GetLineColor()); }
void Debug::DrawBox(box3 a, vec4 color) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a.aa, a.bb, color); }
void Debug::DrawBox(box2 a, vec4 color) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a.aa, a.bb, color); }
void Debug::DrawBox(vec3 a, vec3 b) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a, b, scene.GetLineColor()); }
void Debug::DrawBox(vec2 a, vec2 b) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a, b, scene.GetLineColor()); }
void Debug::DrawBox(vec2 a, float s) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a, s, scene.GetLineColor()); }
void Debug::DrawBox(vec3 a, vec3 b, vec4 color) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a, b, mat4::identity, color); }
void Debug::DrawBox(vec2 a, vec2 b, vec4 color) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a, b, mat2::identity, color); }
void Debug::DrawBox(vec2 a, float s, vec4 color) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a, s, mat2::identity, color); }
void Debug::DrawBox(box3 a, mat4 transform) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a.aa, a.bb, transform, scene.GetLineColor()); }
void Debug::DrawBox(box2 a, mat2 transform) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a.aa, a.bb, transform, scene.GetLineColor()); }
void Debug::DrawBox(box3 a, mat4 transform, vec4 color) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a.aa, a.bb, transform, color); }
void Debug::DrawBox(box2 a, mat2 transform, vec4 color) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a.aa, a.bb, transform, color); }
void Debug::DrawBox(vec3 a, vec3 b, mat4 transform) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a, b, transform, scene.GetLineColor()); }
void Debug::DrawBox(vec2 a, vec2 b, mat2 transform) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a, b, transform, scene.GetLineColor()); }
void Debug::DrawBox(vec2 a, float s, mat2 transform) { Scene& scene = Scene::GetScene(); Debug::DrawBox(a, s, transform, scene.GetLineColor()); }
void Debug::DrawBox(vec3 a, vec3 b, mat4 transform, vec4 color)
void Debug::DrawBox(box3 a) { Debug::DrawBox(a.aa, a.bb, DC::GetGlobalData()); }
void Debug::DrawBox(box2 a) { Debug::DrawBox(a.aa, a.bb, DC::GetGlobalData()); }
void Debug::DrawBox(box3 a, DCD data) { Debug::DrawBox(a.aa, a.bb, data); }
void Debug::DrawBox(box2 a, DCD data) { Debug::DrawBox(a.aa, a.bb, data); }
void Debug::DrawBox(vec3 a, vec3 b) { Debug::DrawBox(a, b, DC::GetGlobalData()); }
void Debug::DrawBox(vec2 a, vec2 b) { Debug::DrawBox(a, b, DC::GetGlobalData()); }
void Debug::DrawBox(vec2 a, float s) { Debug::DrawBox(a, s, DC::GetGlobalData()); }
void Debug::DrawBox(vec3 a, vec3 b, DCD data) { Debug::DrawBox(a, b, mat4::identity, data); }
void Debug::DrawBox(vec2 a, vec2 b, DCD data) { Debug::DrawBox(a, b, mat2::identity, data); }
void Debug::DrawBox(vec2 a, float s, DCD data) { Debug::DrawBox(a, s, mat2::identity, data); }
void Debug::DrawBox(box3 a, mat4 transform) { Debug::DrawBox(a.aa, a.bb, transform, DC::GetGlobalData()); }
void Debug::DrawBox(box2 a, mat2 transform) { Debug::DrawBox(a.aa, a.bb, transform, DC::GetGlobalData()); }
void Debug::DrawBox(box3 a, mat4 transform, DCD data) { Debug::DrawBox(a.aa, a.bb, transform, data); }
void Debug::DrawBox(box2 a, mat2 transform, DCD data) { Debug::DrawBox(a.aa, a.bb, transform, data); }
void Debug::DrawBox(vec3 a, vec3 b, mat4 transform) { Debug::DrawBox(a, b, transform, DC::GetGlobalData()); }
void Debug::DrawBox(vec2 a, vec2 b, mat2 transform) { Debug::DrawBox(a, b, transform, DC::GetGlobalData()); }
void Debug::DrawBox(vec2 a, float s, mat2 transform) { Debug::DrawBox(a, s, transform, DC::GetGlobalData()); }
void Debug::DrawBox(vec3 a, vec3 b, mat4 transform, DCD data)
{ {
vec4 v[8]; vec4 v[8];
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
@@ -252,12 +207,12 @@ void Debug::DrawBox(vec3 a, vec3 b, mat4 transform, vec4 color)
{ {
int j = ((i & 1) << 1) | ((i >> 1) ^ 1); int j = ((i & 1) << 1) | ((i >> 1) ^ 1);


Debug::DrawLine((transform * v[i]).xyz, (transform * v[i + 4]).xyz, color);
Debug::DrawLine((transform * v[i]).xyz, (transform * v[j]).xyz, color);
Debug::DrawLine((transform * v[i + 4]).xyz, (transform * v[j + 4]).xyz, color);
Debug::DrawLine((transform * v[i]).xyz, (transform * v[i + 4]).xyz, data);
Debug::DrawLine((transform * v[i]).xyz, (transform * v[j]).xyz, data);
Debug::DrawLine((transform * v[i + 4]).xyz, (transform * v[j + 4]).xyz, data);
} }
} }
void Debug::DrawBox(vec2 a, vec2 b, mat2 transform, vec4 color)
void Debug::DrawBox(vec2 a, vec2 b, mat2 transform, DCD data)
{ {
vec2 v[4]; vec2 v[4];
v[0] = a; v[0] = a;
@@ -266,41 +221,41 @@ void Debug::DrawBox(vec2 a, vec2 b, mat2 transform, vec4 color)
v[3] = vec2(b.x, a.y); v[3] = vec2(b.x, a.y);


int i = 0; int i = 0;
Debug::DrawLine((transform * v[0]).xy, (transform * v[1]).xy, color);
Debug::DrawLine((transform * v[1]).xy, (transform * v[2]).xy, color);
Debug::DrawLine((transform * v[2]).xy, (transform * v[3]).xy, color);
Debug::DrawLine((transform * v[3]).xy, (transform * v[0]).xy, color);
Debug::DrawLine((transform * v[0]).xy, (transform * v[1]).xy, data);
Debug::DrawLine((transform * v[1]).xy, (transform * v[2]).xy, data);
Debug::DrawLine((transform * v[2]).xy, (transform * v[3]).xy, data);
Debug::DrawLine((transform * v[3]).xy, (transform * v[0]).xy, data);
} }
void Debug::DrawBox(vec2 a, float s, mat2 transform, vec4 color)
void Debug::DrawBox(vec2 a, float s, mat2 transform, DCD data)
{ {
vec2 b = s * vec2(1.f, Renderer::Get()->GetXYRatio()); vec2 b = s * vec2(1.f, Renderer::Get()->GetXYRatio());
Debug::DrawBox(a - b, a + b, transform, color);
Debug::DrawBox(a - b, a + b, transform, data);
} }


//-- CIRCLE ------------------------------------------------------------------- //-- CIRCLE -------------------------------------------------------------------
void Debug::DrawCircle(vec2 a, float s) { Scene& scene = Scene::GetScene(); Debug::DrawCircle(a, s * vec2(1.f, Renderer::Get()->GetXYRatio()), scene.GetLineColor()); }
void Debug::DrawCircle(vec3 a, vec3 n) { Scene& scene = Scene::GetScene(); Debug::DrawCircle(a, n, scene.GetLineColor()); }
void Debug::DrawCircle(vec2 a, vec2 s) { Scene& scene = Scene::GetScene(); Debug::DrawCircle(a, s * vec2(1.f, Renderer::Get()->GetXYRatio()), scene.GetLineColor()); }
void Debug::DrawCircle(vec3 a, vec3 x, vec3 y) { Scene& scene = Scene::GetScene(); Debug::DrawCircle(a, x, y, scene.GetLineColor()); }
void Debug::DrawCircle(vec2 a, vec2 x, vec2 y) { Scene& scene = Scene::GetScene(); Debug::DrawCircle(a, x, y, scene.GetLineColor()); }
void Debug::DrawCircle(vec3 a, vec3 n, vec4 color)
void Debug::DrawCircle(vec2 a, float s) { Debug::DrawCircle(a, s * vec2(1.f, Renderer::Get()->GetXYRatio()), DC::GetGlobalData()); }
void Debug::DrawCircle(vec3 a, vec3 n) { Debug::DrawCircle(a, n, DC::GetGlobalData()); }
void Debug::DrawCircle(vec2 a, vec2 s) { Debug::DrawCircle(a, s * vec2(1.f, Renderer::Get()->GetXYRatio()), DC::GetGlobalData()); }
void Debug::DrawCircle(vec3 a, vec3 x, vec3 y) { Debug::DrawCircle(a, x, y, DC::GetGlobalData()); }
void Debug::DrawCircle(vec2 a, vec2 x, vec2 y) { Debug::DrawCircle(a, x, y, DC::GetGlobalData()); }
void Debug::DrawCircle(vec3 a, vec3 n, DCD data)
{ {
vec3 x = orthogonal(n); vec3 x = orthogonal(n);
vec3 y = cross(normalize(n), normalize(x)) * length(n); vec3 y = cross(normalize(n), normalize(x)) * length(n);
DrawCircle(a, x, y, color);
DrawCircle(a, x, y, data);
} }
void Debug::DrawCircle(vec2 a, vec2 s, vec4 color)
void Debug::DrawCircle(vec2 a, vec2 s, DCD data)
{ {
vec2 x = vec2::axis_x * s.x; vec2 x = vec2::axis_x * s.x;
vec2 y = vec2::axis_y * s.y; vec2 y = vec2::axis_y * s.y;
DrawCircle(a, x, y, color);
DrawCircle(a, x, y, data);
} }
//-- //--
void Debug::DrawCircle(vec3 a, vec3 x, vec3 y, vec4 color)
void Debug::DrawCircle(vec3 a, vec3 x, vec3 y, DCD data)
{ {
Scene& scene = Scene::GetScene(); Scene& scene = Scene::GetScene();
float size = F_PI * 2.f * lol::max(length(x), length(y)); float size = F_PI * 2.f * lol::max(length(x), length(y));
int segment_nb = lol::max(1, (int)((size * .25f) / scene.GetLineSegmentSize()));
int segment_nb = lol::max(1, (int)((size * .25f) / data.m_segment_size));
for (int i = 0; i < segment_nb; i++) for (int i = 0; i < segment_nb; i++)
{ {
float a0 = (((float)i) / (float)segment_nb) * F_PI_2; float a0 = (((float)i) / (float)segment_nb) * F_PI_2;
@@ -308,18 +263,18 @@ void Debug::DrawCircle(vec3 a, vec3 x, vec3 y, vec4 color)
vec2 p0 = vec2(lol::cos(a0), lol::sin(a0)); vec2 p0 = vec2(lol::cos(a0), lol::sin(a0));
vec2 p1 = vec2(lol::cos(a1), lol::sin(a1)); vec2 p1 = vec2(lol::cos(a1), lol::sin(a1));


Debug::DrawLine(a + p0.x * x + p0.y * y, a + p1.x * x + p1.y * y, color);
Debug::DrawLine(a + p0.x * -x + p0.y * -y, a + p1.x * -x + p1.y * -y, color);
Debug::DrawLine(a + p0.x * x + p0.y * -y, a + p1.x * x + p1.y * -y, color);
Debug::DrawLine(a + p0.x * -x + p0.y * y, a + p1.x * -x + p1.y * y, color);
Debug::DrawLine(a + p0.x * x + p0.y * y, a + p1.x * x + p1.y * y, data);
Debug::DrawLine(a + p0.x * -x + p0.y * -y, a + p1.x * -x + p1.y * -y, data);
Debug::DrawLine(a + p0.x * x + p0.y * -y, a + p1.x * x + p1.y * -y, data);
Debug::DrawLine(a + p0.x * -x + p0.y * y, a + p1.x * -x + p1.y * y, data);
} }
} }
//-- //--
void Debug::DrawCircle(vec2 a, vec2 x, vec2 y, vec4 color)
void Debug::DrawCircle(vec2 a, vec2 x, vec2 y, DCD data)
{ {
Scene& scene = Scene::GetScene(); Scene& scene = Scene::GetScene();
float size = F_PI * 2.f * lol::max(length(x), length(y)); float size = F_PI * 2.f * lol::max(length(x), length(y));
int segment_nb = lol::max(1, (int)((size * .25f) / scene.GetLineSegmentSize()));
int segment_nb = lol::max(1, (int)((size * .25f) / data.m_segment_size));
for (int i = 0; i < segment_nb; i++) for (int i = 0; i < segment_nb; i++)
{ {
float a0 = (((float)i) / (float)segment_nb) * F_PI_2; float a0 = (((float)i) / (float)segment_nb) * F_PI_2;
@@ -327,52 +282,52 @@ void Debug::DrawCircle(vec2 a, vec2 x, vec2 y, vec4 color)
vec2 p0 = vec2(lol::cos(a0), lol::sin(a0)); vec2 p0 = vec2(lol::cos(a0), lol::sin(a0));
vec2 p1 = vec2(lol::cos(a1), lol::sin(a1)); vec2 p1 = vec2(lol::cos(a1), lol::sin(a1));


Debug::DrawLine(a + p0.x * x + p0.y * y, a + p1.x * x + p1.y * y, color);
Debug::DrawLine(a + p0.x * -x + p0.y * -y, a + p1.x * -x + p1.y * -y, color);
Debug::DrawLine(a + p0.x * x + p0.y * -y, a + p1.x * x + p1.y * -y, color);
Debug::DrawLine(a + p0.x * -x + p0.y * y, a + p1.x * -x + p1.y * y, color);
Debug::DrawLine(a + p0.x * x + p0.y * y, a + p1.x * x + p1.y * y, data);
Debug::DrawLine(a + p0.x * -x + p0.y * -y, a + p1.x * -x + p1.y * -y, data);
Debug::DrawLine(a + p0.x * x + p0.y * -y, a + p1.x * x + p1.y * -y, data);
Debug::DrawLine(a + p0.x * -x + p0.y * y, a + p1.x * -x + p1.y * y, data);
} }
} }


//-- SPHERE ------------------------------------------------------------------- //-- SPHERE -------------------------------------------------------------------
void Debug::DrawSphere(vec3 a, float s) { Scene& scene = Scene::GetScene(); Debug::DrawSphere(a, s, scene.GetLineColor()); }
void Debug::DrawSphere(vec3 a, float s, vec4 color) { Debug::DrawSphere(a, vec3::axis_x * s, vec3::axis_y * s, vec3::axis_z * s, color); }
void Debug::DrawSphere(vec3 a, vec3 x, vec3 y, vec3 z) { Scene& scene = Scene::GetScene(); Debug::DrawSphere(a, x, y, z, scene.GetLineColor()); }
void Debug::DrawSphere(vec3 a, vec3 x, vec3 y, vec3 z, vec4 color)
{
Debug::DrawCircle(a, x, y, color);
Debug::DrawCircle(a, x, (y + z) * .707f, color);
Debug::DrawCircle(a, x, (y - z) * .707f, color);
Debug::DrawCircle(a, z, x, color);
Debug::DrawCircle(a, z, (x + y) * .707f, color);
Debug::DrawCircle(a, z, (x - y) * .707f, color);
Debug::DrawCircle(a, y, z, color);
Debug::DrawCircle(a, y, (z + x) * .707f, color);
Debug::DrawCircle(a, y, (z - x) * .707f, color);
void Debug::DrawSphere(vec3 a, float s) { Debug::DrawSphere(a, s, DC::GetGlobalData()); }
void Debug::DrawSphere(vec3 a, float s, DCD data) { Debug::DrawSphere(a, vec3::axis_x * s, vec3::axis_y * s, vec3::axis_z * s, data); }
void Debug::DrawSphere(vec3 a, vec3 x, vec3 y, vec3 z) { Debug::DrawSphere(a, x, y, z, DC::GetGlobalData()); }
void Debug::DrawSphere(vec3 a, vec3 x, vec3 y, vec3 z, DCD data)
{
Debug::DrawCircle(a, x, y, data);
Debug::DrawCircle(a, x, (y + z) * .707f, data);
Debug::DrawCircle(a, x, (y - z) * .707f, data);
Debug::DrawCircle(a, z, x, data);
Debug::DrawCircle(a, z, (x + y) * .707f, data);
Debug::DrawCircle(a, z, (x - y) * .707f, data);
Debug::DrawCircle(a, y, z, data);
Debug::DrawCircle(a, y, (z + x) * .707f, data);
Debug::DrawCircle(a, y, (z - x) * .707f, data);
} }


//-- CAPSULE ------------------------------------------------------------------ //-- CAPSULE ------------------------------------------------------------------
void Debug::DrawCapsule(vec3 a, float s, vec3 h) { Scene& scene = Scene::GetScene(); Debug::DrawCapsule(a, s, h, scene.GetLineColor()); }
void Debug::DrawCapsule(vec3 a, vec3 x, vec3 y, vec3 z, vec3 h) { Scene& scene = Scene::GetScene(); Debug::DrawCapsule(a, x, y, z, h, scene.GetLineColor()); }
void Debug::DrawCapsule(vec3 a, float s, vec3 h, vec4 color)
void Debug::DrawCapsule(vec3 a, float s, vec3 h) { Debug::DrawCapsule(a, s, h, DC::GetGlobalData()); }
void Debug::DrawCapsule(vec3 a, vec3 x, vec3 y, vec3 z, vec3 h) { Debug::DrawCapsule(a, x, y, z, h, DC::GetGlobalData()); }
void Debug::DrawCapsule(vec3 a, float s, vec3 h, DCD data)
{ {
vec3 x = orthonormal(h) * s; vec3 x = orthonormal(h) * s;
vec3 y = cross(normalize(h), normalize(x)) * s; vec3 y = cross(normalize(h), normalize(x)) * s;
Debug::DrawCapsule(a, x, y, normalize(h) * s, h, color);
Debug::DrawCapsule(a, x, y, normalize(h) * s, h, data);
} }
//-- //--
void Debug::DrawCapsule(vec3 a, vec3 x, vec3 y, vec3 z, vec3 h, vec4 color)
void Debug::DrawCapsule(vec3 a, vec3 x, vec3 y, vec3 z, vec3 h, DCD data)
{ {
Scene& scene = Scene::GetScene(); Scene& scene = Scene::GetScene();
float size = F_PI * 2.f * lol::max(length(x), length(y)); float size = F_PI * 2.f * lol::max(length(x), length(y));
int segment_nb = lol::max(1, (int)((size * .25f) / scene.GetLineSegmentSize()));
int segment_nb = lol::max(1, (int)((size * .25f) / data.m_segment_size));
for (int i = -1; i < 2; i += 2) for (int i = -1; i < 2; i += 2)
{ {
vec3 b = a + h * .5f * (float)i; vec3 b = a + h * .5f * (float)i;
vec3 c = a - h * .5f * (float)i; vec3 c = a - h * .5f * (float)i;
Debug::DrawCircle(b, x, y, color);
Debug::DrawLine(b + x * (float)i, c + x * (float)i, color);
Debug::DrawLine(b + y * (float)i, c + y * (float)i, color);
Debug::DrawCircle(b, x, y, data);
Debug::DrawLine(b + x * (float)i, c + x * (float)i, data);
Debug::DrawLine(b + y * (float)i, c + y * (float)i, data);
for (int j = 0; j < segment_nb; j++) for (int j = 0; j < segment_nb; j++)
{ {
float a0 = (((float)j) / (float)segment_nb) * F_PI_2; float a0 = (((float)j) / (float)segment_nb) * F_PI_2;
@@ -380,18 +335,18 @@ void Debug::DrawCapsule(vec3 a, vec3 x, vec3 y, vec3 z, vec3 h, vec4 color)
vec2 p0 = vec2(lol::cos(a0), lol::sin(a0)); vec2 p0 = vec2(lol::cos(a0), lol::sin(a0));
vec2 p1 = vec2(lol::cos(a1), lol::sin(a1)); vec2 p1 = vec2(lol::cos(a1), lol::sin(a1));


Debug::DrawLine(b + p0.x * x + p0.y * z * (float)i, b + p1.x * x + p1.y * z * (float)i, color);
Debug::DrawLine(b + p0.x * -x + p0.y * z * (float)i, b + p1.x * -x + p1.y * z * (float)i, color);
Debug::DrawLine(b + p0.x * y + p0.y * z * (float)i, b + p1.x * y + p1.y * z * (float)i, color);
Debug::DrawLine(b + p0.x * -y + p0.y * z * (float)i, b + p1.x * -y + p1.y * z * (float)i, color);
Debug::DrawLine(b + p0.x * x + p0.y * z * (float)i, b + p1.x * x + p1.y * z * (float)i, data);
Debug::DrawLine(b + p0.x * -x + p0.y * z * (float)i, b + p1.x * -x + p1.y * z * (float)i, data);
Debug::DrawLine(b + p0.x * y + p0.y * z * (float)i, b + p1.x * y + p1.y * z * (float)i, data);
Debug::DrawLine(b + p0.x * -y + p0.y * z * (float)i, b + p1.x * -y + p1.y * z * (float)i, data);
} }
} }
} }


//-- VIEW PROJ ---------------------------------------------------------------- //-- VIEW PROJ ----------------------------------------------------------------
void Debug::DrawViewProj(mat4 view, mat4 proj) { Scene& scene = Scene::GetScene(); Debug::DrawViewProj(view, proj, scene.GetLineColor()); }
void Debug::DrawViewProj(mat4 view_proj) { Scene& scene = Scene::GetScene(); Debug::DrawViewProj(view_proj, scene.GetLineColor()); }
void Debug::DrawViewProj(mat4 view, mat4 proj, vec4 color)
void Debug::DrawViewProj(mat4 view, mat4 proj) { Debug::DrawViewProj(view, proj, DC::GetGlobalData()); }
void Debug::DrawViewProj(mat4 view_proj) { Debug::DrawViewProj(view_proj, DC::GetGlobalData()); }
void Debug::DrawViewProj(mat4 view, mat4 proj, DCD data)
{ {
mat4 const view_proj = proj * view; mat4 const view_proj = proj * view;


@@ -409,13 +364,13 @@ void Debug::DrawViewProj(mat4 view, mat4 proj, vec4 color)


//Draw near //Draw near
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
Debug::DrawLine(p[i].xyz, p0, color);
Debug::DrawLine(p[i].xyz, p0, data);


Debug::DrawViewProj(view_proj, color);
Debug::DrawViewProj(view_proj, data);
} }


//-- //--
void Debug::DrawViewProj(mat4 view_proj, vec4 color)
void Debug::DrawViewProj(mat4 view_proj, DCD data)
{ {
//Near plane //Near plane
mat4 const inv_view_proj = inverse(view_proj); mat4 const inv_view_proj = inverse(view_proj);
@@ -433,16 +388,16 @@ void Debug::DrawViewProj(mat4 view_proj, vec4 color)


//Draw near //Draw near
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
Debug::DrawLine(p[i].xyz, p[(i + 1) % 4].xyz, color);
Debug::DrawLine(p[i].xyz, p[(i + 1) % 4].xyz, data);
//Draw far //Draw far
for (int i = 4; i < 8; i++) for (int i = 4; i < 8; i++)
Debug::DrawLine(p[i].xyz, p[(i - 4 + 1) % 4 + 4].xyz, color);
Debug::DrawLine(p[i].xyz, p[(i - 4 + 1) % 4 + 4].xyz, data);
//Draw near to far //Draw near to far
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
Debug::DrawLine(p[i].xyz, p[i + 4].xyz, color);
Debug::DrawLine(p[i].xyz, p[i + 4].xyz, data);
//Draw diagonal //Draw diagonal
for (int i = 2; i < 6; i++) for (int i = 2; i < 6; i++)
Debug::DrawLine(p[i].xyz, p[i + ((i < 4)?(-2):(+2))].xyz, color);
Debug::DrawLine(p[i].xyz, p[i + ((i < 4)?(-2):(+2))].xyz, data);
} }


} /* namespace lol */ } /* namespace lol */


+ 5
- 1
src/easymesh/easymesh.h View File

@@ -392,7 +392,11 @@ public:
- offset : useless - offset : useless
*/ */
void AppendCog(int nbsides, float h, float d10, float d20, float d11, void AppendCog(int nbsides, float h, float d10, float d20, float d11,
float d21, float d12, float d22, float sidemul=0.f, bool offset=false);
float d21, float d12, float d22, float sidemul = 0.f, bool offset = false);
void AppendCog(int nbsides, float h, vec2 d0, vec2 d1, vec2 d2, float sidemul = 0.f, bool offset = false)
{
AppendCog(nbsides, h, d0.x, d0.y, d1.x, d1.y, d2.x, d2.y, sidemul, offset);
}


//------------------------------------------------------------------------- //-------------------------------------------------------------------------
//TODO : Mesh Bone operations //TODO : Mesh Bone operations


+ 10
- 8
src/easymesh/easymeshlua.cpp View File

@@ -27,7 +27,7 @@ EasyMeshLuaLoader::EasyMeshLuaLoader() : LuaLoader()
lua_State* l = GetLuaState(); lua_State* l = GetLuaState();


//Registering demo object //Registering demo object
LuaObjectDef::Register<EasyMeshLuaObject>(l);
LuaObjectHelper::Register<EasyMeshLuaObject>(l);
} }


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -81,17 +81,17 @@ EasyMeshLuaObject* EasyMeshLuaObject::New(lua_State* l, int arg_nb)
{ {
UNUSED(l); UNUSED(l);
UNUSED(arg_nb); UNUSED(arg_nb);
LuaStack s(l);
LuaString n("", true);
s >> n;
return new EasyMeshLuaObject(n());
LuaStack s = LuaStack::Begin(l);
String str = s.Get<String>("");
return new EasyMeshLuaObject(str);
} }


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
const LuaObjectLib* EasyMeshLuaObject::GetLib()
const LuaObjectLibrary* EasyMeshLuaObject::GetLib()
{ {
typedef EasyMeshLuaObject EMLO;
static const LuaObjectLib lib = LuaObjectLib(
#define EMLO EasyMeshLuaObject

static const LuaObjectLibrary lib = LuaObjectLibrary(
"EasyMesh", "EasyMesh",
//Statics //Statics
{ { nullptr, nullptr } }, { { nullptr, nullptr } },
@@ -182,6 +182,8 @@ const LuaObjectLib* EasyMeshLuaObject::GetLib()
//Variables //Variables
{ { nullptr, nullptr, nullptr } }); { { nullptr, nullptr, nullptr } });
return &lib; return &lib;

#undef EMLO
} }


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------


+ 84
- 603
src/easymesh/easymeshlua.h View File

@@ -18,7 +18,6 @@ namespace lol
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class EasyMeshLuaObject : public LuaObject class EasyMeshLuaObject : public LuaObject
{ {
typedef Lolua::VarPtr<EasyMeshLuaObject> EzMeshPtr;
EasyMesh m_instance; EasyMesh m_instance;
public: public:
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@@ -28,610 +27,91 @@ public:


//------------------------------------------------------------------------- //-------------------------------------------------------------------------
static EasyMeshLuaObject* New(lua_State* l, int arg_nb); static EasyMeshLuaObject* New(lua_State* l, int arg_nb);
static const LuaObjectLib* GetLib();
static const LuaObjectLibrary* GetLib();

#define EMLO GetPtr<EasyMeshLuaObject>()


//------------------------------------------------------------------------- //-------------------------------------------------------------------------
static int AppendCylinder(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaInt32 nsides;
LuaFloat h, d1, d2;
LuaBool dualside(false, true), smooth(false, true), close(false, true);
s >> m >> nsides >> h >> d1 >> d2 >> dualside >> smooth >> close;
m->m_instance.AppendCylinder(nsides, h, d1, d2, dualside, smooth, close);
return 0;
}
static int AppendSphere(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaInt32 ndivisions;
LuaFloat d;
s >> m >> ndivisions >> d;
m->m_instance.AppendSphere(ndivisions, d);
return 0;
}
static int AppendCapsule(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaInt32 ndivisions;
LuaFloat h, d;
s >> m >> ndivisions >> h >> d;
m->m_instance.AppendCapsule(ndivisions, h, d);
return 0;
}
static int AppendTorus(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaInt32 ndivisions;
LuaFloat d1, d2;
s >> m >> ndivisions >> d1 >> d2;
m->m_instance.AppendTorus(ndivisions, d1, d2);
return 0;
}
static int AppendBox(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaVec3 size;
LuaFloat chamf(0.f, true);
LuaBool smooth(false, true);
s >> m >> size >> chamf >> smooth;
m->m_instance.AppendBox(size, chamf, smooth);
return 0;
}
static int AppendStar(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaInt32 nbranches;
LuaFloat d1, d2;
LuaBool fade(false, true), fade2(false, true);
s >> m >> nbranches >> d1 >> d2 >> fade >> fade2;
m->m_instance.AppendStar(nbranches, d1, d2, fade, fade2);
return 0;
}
static int AppendExpandedStar(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaInt32 nbranches;
LuaFloat d1, d2, extrad(0.f, true);
s >> m >> nbranches >> d1 >> d2 >> extrad;
m->m_instance.AppendExpandedStar(nbranches, d1, d2, extrad);
return 0;
}
static int AppendDisc(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaInt32 nsides;
LuaFloat d;
LuaBool fade(false, true);
s >> m >> nsides >> d >> fade;
m->m_instance.AppendDisc(nsides, d, fade);
return 0;
}
static int AppendSimpleTriangle(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat d;
LuaBool fade(false, true);
s >> m >> d >> fade;
m->m_instance.AppendSimpleTriangle(d, fade);
return 0;
}
static int AppendSimpleQuad(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat size;
LuaBool fade(false, true);
s >> m >> size >> fade;
m->m_instance.AppendSimpleQuad(size, fade);
return 0;
}
static int AppendCog(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaInt32 nbsides;
LuaFloat h, sidemul(0.f, true);
LuaVec2 d0, d1, d2;
LuaBool offset(false, true);
s >> m >> nbsides >> h >> d0 >> d1 >> d2 >> sidemul >> offset;
m->m_instance.AppendCog(nbsides, h, d0().x, d0().y, d1().x, d1().y, d2().x, d2().y, sidemul, offset);
return 0;
}
//-------------------------------------------------------------------------
static int TranslateX(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat f;
s >> m >> f;
m->m_instance.TranslateX(f);
return 0;
}
static int TranslateY(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat f;
s >> m >> f;
m->m_instance.TranslateY(f);
return 0;
}
static int TranslateZ(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat f;
s >> m >> f;
m->m_instance.TranslateZ(f);
return 0;
}
static int Translate(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaVec3 v;
s >> m >> v;
m->m_instance.Translate(v);
return 0;
}
//-------------------------------------------------------------------------
static int RotateX(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat a;
s >> m >> a;
m->m_instance.RotateX(a);
return 0;
}
static int RotateY(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat a;
s >> m >> a;
m->m_instance.RotateY(a);
return 0;
}
static int RotateZ(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat a;
s >> m >> a;
m->m_instance.RotateZ(a);
return 0;
}
static int Rotate(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat a;
LuaVec3 v;
s >> m >> a >> v;
m->m_instance.Rotate(a, v);
return 0;
}
//-------------------------------------------------------------------------
static int ScaleX(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat x;
s >> m >> x;
m->m_instance.ScaleX(x);
return 0;
}
static int ScaleY(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat y;
s >> m >> y;
m->m_instance.ScaleY(y);
return 0;
}
static int ScaleZ(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat z;
s >> m >> z;
m->m_instance.ScaleZ(z);
return 0;
}
static int Scale(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaVec3 v;
s >> m >> v;
m->m_instance.Scale(v);
return 0;
}
//-------------------------------------------------------------------------
static int RadialJitter(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat f;
s >> m >> f;
m->m_instance.RadialJitter(f);
return 0;
}
//-------------------------------------------------------------------------
static int TaperX(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat y, z, xoff(0.f, true);
LuaBool abs(true, true);
s >> m >> y >> z >> xoff >> abs;
m->m_instance.TaperX(y, z, xoff, abs);
return 0;
}
static int TaperY(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat x, z, yoff(0.f, true);
LuaBool abs(true, true);
s >> m >> x >> z >> yoff >> abs;
m->m_instance.TaperY(x, z, yoff, abs);
return 0;
}
static int TaperZ(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat x, y, zoff(0.f, true);
LuaBool abs(true, true);
s >> m >> x >> y >> zoff >> abs;
m->m_instance.TaperZ(x, y, zoff, abs);
return 0;
}
//-------------------------------------------------------------------------
static int TwistX(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat t, toff(0.f, true);
s >> m >> t >> toff;
m->m_instance.TwistX(t, toff);
return 0;
}
static int TwistY(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat t, toff(0.f, true);
s >> m >> t >> toff;
m->m_instance.TwistY(t, toff);
return 0;
}
static int TwistZ(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat t, toff(0.f, true);
s >> m >> t >> toff;
m->m_instance.TwistZ(t, toff);
return 0;
}
//-------------------------------------------------------------------------
static int ShearX(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat y, z, xoff(0.f, true);
LuaBool abs(true, true);
s >> m >> y >> z >> xoff >> abs;
m->m_instance.ShearX(y, z, xoff, abs);
return 0;
}
static int ShearY(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat x, z, yoff(0.f, true);
LuaBool abs(true, true);
s >> m >> x >> z >> yoff >> abs;
m->m_instance.ShearY(x, z, yoff, abs);
return 0;
}
static int ShearZ(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat x, y, zoff(0.f, true);
LuaBool abs(true, true);
s >> m >> x >> y >> zoff >> abs;
m->m_instance.ShearZ(x, y, zoff, abs);
return 0;
}
//-------------------------------------------------------------------------
static int StretchX(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat y, z, xoff(0.f, true);
s >> m >> y >> z >> xoff;
m->m_instance.StretchX(y, z, xoff);
return 0;
}
static int StretchY(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat x, z, yoff(0.f, true);
s >> m >> x >> z >> yoff;
m->m_instance.StretchY(x, z, yoff);
return 0;
}
static int StretchZ(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat x, y, zoff(0.f, true);
s >> m >> x >> y >> zoff;
m->m_instance.StretchZ(x, y, zoff);
return 0;
}
//-------------------------------------------------------------------------
static int BendXY(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat t, toff(0.f, true);
s >> m >> t >> toff;
m->m_instance.BendXY(t, toff);
return 0;
}
static int BendXZ(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat t, toff(0.f, true);
s >> m >> t >> toff;
m->m_instance.BendXZ(t, toff);
return 0;
}
static int BendYX(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat t, toff(0.f, true);
s >> m >> t >> toff;
m->m_instance.BendYX(t, toff);
return 0;
}
static int BendYZ(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat t, toff(0.f, true);
s >> m >> t >> toff;
m->m_instance.BendYZ(t, toff);
return 0;
}
static int BendZX(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat t, toff(0.f, true);
s >> m >> t >> toff;
m->m_instance.BendZX(t, toff);
return 0;
}
static int BendZY(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat t, toff(0.f, true);
s >> m >> t >> toff;
m->m_instance.BendZY(t, toff);
return 0;
}
//-------------------------------------------------------------------------
static int MirrorX(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.MirrorX();
return 0;
}
static int MirrorY(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.MirrorY();
return 0;
}
static int MirrorZ(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.MirrorZ();
return 0;
}
//-------------------------------------------------------------------------
static int LoopStart(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaInt32 loopnb;
s >> m >> loopnb;
m->m_instance.LoopStart(loopnb);
return 0;
}
static int LoopEnd(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.LoopEnd();
return 0;
}
static int OpenBrace(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.OpenBrace();
return 0;
}
static int CloseBrace(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.CloseBrace();
return 0;
}
//-------------------------------------------------------------------------
static int ToggleScaleWinding(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.ToggleScaleWinding();
return 0;
}
static int ToggleQuadWeighting(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.ToggleQuadWeighting();
return 0;
}
static int TogglePostBuildNormal(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.TogglePostBuildNormal();
return 0;
}
static int ToggleVerticeNoCleanup(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.ToggleVerticeNoCleanup();
return 0;
}
//-------------------------------------------------------------------------
static int VerticesMerge(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.VerticesMerge();
return 0;
}
static int VerticesSeparate(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.VerticesSeparate();
return 0;
}
static int VerticesCleanup(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
s >> m;
m->m_instance.VerticesCleanup();
return 0;
}
//-------------------------------------------------------------------------
static int Duplicate(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaVec3 ds(vec3(1.f));
s >> m >> ds;
m->m_instance.DupAndScale(ds, true);
return 0;
}
static int Smooth(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaInt32 pass, split_per_pass, smooth_per_pass;
s >> m >> pass >> split_per_pass >> smooth_per_pass;
m->m_instance.SmoothMesh(pass, split_per_pass, smooth_per_pass);
return 0;
}
static int SplitTriangles(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaInt32 pass;
s >> m >> pass;
m->m_instance.SplitTriangles(pass);
return 0;
}
static int Chamfer(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaFloat f;
s >> m >> f;
m->m_instance.Chamfer(f);
return 0;
}
//-------------------------------------------------------------------------
static int SetCurColor(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaColor c;
s >> m >> c;
m->m_instance.SetCurColor(c);
return 0;
}
static int SetCurColorA(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaColor c;
s >> m >> c;
m->m_instance.SetCurColorA(c);
return 0;
}
static int SetCurColorB(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaColor c;
m->m_instance.SetCurColorB(c);
return 0;
}
static int SetVertColor(lua_State* l)
{
LuaStack s(l);
EzMeshPtr m;
LuaColor c;
s >> m >> c;
m->m_instance.SetVertColor(c);
return 0;
}
LOLUA_DECLARE_VOID_METHOD_ARGS(AppendCylinder, EMLO, m_instance.AppendCylinder, Get<int32_t>(), Get<float>(), Get<float>(), Get<float>(), Get<bool>(false), Get<bool>(false), Get<bool>(false));
LOLUA_DECLARE_VOID_METHOD_ARGS(AppendSphere, EMLO, m_instance.AppendSphere, Get<int32_t>(), Get<float>());
LOLUA_DECLARE_VOID_METHOD_ARGS(AppendCapsule, EMLO, m_instance.AppendCapsule, Get<int32_t>(), Get<float>(), Get<float>());
LOLUA_DECLARE_VOID_METHOD_ARGS(AppendTorus, EMLO, m_instance.AppendTorus, Get<int32_t>(), Get<float>(), Get<float>());
LOLUA_DECLARE_VOID_METHOD_ARGS(AppendBox, EMLO, m_instance.AppendBox, Get<vec3>(), Get<float>(0.f), Get<bool>(false));
LOLUA_DECLARE_VOID_METHOD_ARGS(AppendStar, EMLO, m_instance.AppendStar, Get<int32_t>(), Get<float>(), Get<float>(), Get<bool>(false), Get<bool>(false));
LOLUA_DECLARE_VOID_METHOD_ARGS(AppendExpandedStar, EMLO, m_instance.AppendExpandedStar, Get<int32_t>(), Get<float>(), Get<float>(), Get<float>(0.f));
LOLUA_DECLARE_VOID_METHOD_ARGS(AppendDisc, EMLO, m_instance.AppendDisc, Get<int32_t>(), Get<float>(), Get<bool>(false));
LOLUA_DECLARE_VOID_METHOD_ARGS(AppendSimpleTriangle, EMLO, m_instance.AppendSimpleTriangle, Get<float>(), Get<bool>(false));
LOLUA_DECLARE_VOID_METHOD_ARGS(AppendSimpleQuad, EMLO, m_instance.AppendSimpleQuad, Get<float>(), Get<bool>(false));
LOLUA_DECLARE_VOID_METHOD_ARGS(AppendCog, EMLO, m_instance.AppendCog, Get<int32_t>(), Get<float>(), Get<vec2>(), Get<vec2>(), Get<vec2>(), Get<float>(0.f), Get<bool>(false));
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_ARGS(TranslateX, EMLO, m_instance.TranslateX, Get<float>());
LOLUA_DECLARE_VOID_METHOD_ARGS(TranslateY, EMLO, m_instance.TranslateY, Get<float>());
LOLUA_DECLARE_VOID_METHOD_ARGS(TranslateZ, EMLO, m_instance.TranslateZ, Get<float>());
LOLUA_DECLARE_VOID_METHOD_ARGS(Translate, EMLO, m_instance.Translate, Get<vec3>());
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_ARGS(RotateX, EMLO, m_instance.RotateX, Get<float>());
LOLUA_DECLARE_VOID_METHOD_ARGS(RotateY, EMLO, m_instance.RotateY, Get<float>());
LOLUA_DECLARE_VOID_METHOD_ARGS(RotateZ, EMLO, m_instance.RotateZ, Get<float>());
LOLUA_DECLARE_VOID_METHOD_ARGS(Rotate, EMLO, m_instance.Rotate, Get<float>(), Get<vec3>());
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_ARGS(ScaleX, EMLO, m_instance.ScaleX, Get<float>());
LOLUA_DECLARE_VOID_METHOD_ARGS(ScaleY, EMLO, m_instance.ScaleY, Get<float>());
LOLUA_DECLARE_VOID_METHOD_ARGS(ScaleZ, EMLO, m_instance.ScaleZ, Get<float>());
LOLUA_DECLARE_VOID_METHOD_ARGS(Scale, EMLO, m_instance.Scale, Get<vec3>());
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_ARGS(RadialJitter, EMLO, m_instance.RadialJitter, Get<float>());
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_ARGS(TaperX, EMLO, m_instance.TaperX, Get<float>(), Get<float>(), Get<float>(0.f), Get<bool>(true));
LOLUA_DECLARE_VOID_METHOD_ARGS(TaperY, EMLO, m_instance.TaperY, Get<float>(), Get<float>(), Get<float>(0.f), Get<bool>(true));
LOLUA_DECLARE_VOID_METHOD_ARGS(TaperZ, EMLO, m_instance.TaperZ, Get<float>(), Get<float>(), Get<float>(0.f), Get<bool>(true));
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_ARGS(TwistX, EMLO, m_instance.TwistX, Get<float>(), Get<float>(0.f));
LOLUA_DECLARE_VOID_METHOD_ARGS(TwistY, EMLO, m_instance.TwistY, Get<float>(), Get<float>(0.f));
LOLUA_DECLARE_VOID_METHOD_ARGS(TwistZ, EMLO, m_instance.TwistZ, Get<float>(), Get<float>(0.f));
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_ARGS(ShearX, EMLO, m_instance.ShearX, Get<float>(), Get<float>(), Get<float>(0.f), Get<bool>(true));
LOLUA_DECLARE_VOID_METHOD_ARGS(ShearY, EMLO, m_instance.ShearY, Get<float>(), Get<float>(), Get<float>(0.f), Get<bool>(true));
LOLUA_DECLARE_VOID_METHOD_ARGS(ShearZ, EMLO, m_instance.ShearZ, Get<float>(), Get<float>(), Get<float>(0.f), Get<bool>(true));
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_ARGS(StretchX, EMLO, m_instance.StretchX, Get<float>(), Get<float>(), Get<float>(0.f));
LOLUA_DECLARE_VOID_METHOD_ARGS(StretchY, EMLO, m_instance.StretchY, Get<float>(), Get<float>(), Get<float>(0.f));
LOLUA_DECLARE_VOID_METHOD_ARGS(StretchZ, EMLO, m_instance.StretchZ, Get<float>(), Get<float>(), Get<float>(0.f));
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_ARGS(BendXY, EMLO, m_instance.BendXY, Get<float>(), Get<float>(0.f));
LOLUA_DECLARE_VOID_METHOD_ARGS(BendXZ, EMLO, m_instance.BendXZ, Get<float>(), Get<float>(0.f));
LOLUA_DECLARE_VOID_METHOD_ARGS(BendYX, EMLO, m_instance.BendYX, Get<float>(), Get<float>(0.f));
LOLUA_DECLARE_VOID_METHOD_ARGS(BendYZ, EMLO, m_instance.BendYZ, Get<float>(), Get<float>(0.f));
LOLUA_DECLARE_VOID_METHOD_ARGS(BendZX, EMLO, m_instance.BendZX, Get<float>(), Get<float>(0.f));
LOLUA_DECLARE_VOID_METHOD_ARGS(BendZY, EMLO, m_instance.BendZY, Get<float>(), Get<float>(0.f));
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_VOID(MirrorX, EMLO, m_instance.MirrorX);
LOLUA_DECLARE_VOID_METHOD_VOID(MirrorY, EMLO, m_instance.MirrorY);
LOLUA_DECLARE_VOID_METHOD_VOID(MirrorZ, EMLO, m_instance.MirrorZ);
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_ARGS(LoopStart, EMLO, m_instance.LoopStart, Get<int32_t>());
LOLUA_DECLARE_VOID_METHOD_VOID(LoopEnd, EMLO, m_instance.LoopEnd);
LOLUA_DECLARE_VOID_METHOD_VOID(OpenBrace, EMLO, m_instance.OpenBrace, Get<float>());
LOLUA_DECLARE_VOID_METHOD_VOID(CloseBrace, EMLO, m_instance.CloseBrace, Get<float>());
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_VOID(ToggleScaleWinding, EMLO, m_instance.ToggleScaleWinding);
LOLUA_DECLARE_VOID_METHOD_VOID(ToggleQuadWeighting, EMLO, m_instance.ToggleQuadWeighting);
LOLUA_DECLARE_VOID_METHOD_VOID(TogglePostBuildNormal, EMLO, m_instance.TogglePostBuildNormal);
LOLUA_DECLARE_VOID_METHOD_VOID(ToggleVerticeNoCleanup, EMLO, m_instance.ToggleVerticeNoCleanup);
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_VOID(VerticesMerge, EMLO, m_instance.VerticesMerge);
LOLUA_DECLARE_VOID_METHOD_VOID(VerticesSeparate, EMLO, m_instance.VerticesSeparate);
LOLUA_DECLARE_VOID_METHOD_VOID(VerticesCleanup, EMLO, m_instance.VerticesCleanup);
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_ARGS(Duplicate, EMLO, m_instance.DupAndScale, Get<vec3>(vec3(1.f)), Get<bool>(true));
LOLUA_DECLARE_VOID_METHOD_ARGS(Smooth, EMLO, m_instance.SmoothMesh, Get<int32_t>(), Get<int32_t>(), Get<int32_t>());
LOLUA_DECLARE_VOID_METHOD_ARGS(SplitTriangles, EMLO, m_instance.SplitTriangles, Get<int32_t>());
LOLUA_DECLARE_VOID_METHOD_ARGS(Chamfer, EMLO, m_instance.Chamfer, Get<float>());
//-------------------------------------------------------------------------
LOLUA_DECLARE_VOID_METHOD_ARGS(SetCurColor, EMLO, m_instance.SetCurColor, Get<vec4>());
LOLUA_DECLARE_VOID_METHOD_ARGS(SetCurColorA, EMLO, m_instance.SetCurColorA, Get<vec4>());
LOLUA_DECLARE_VOID_METHOD_ARGS(SetCurColorB, EMLO, m_instance.SetCurColorB, Get<vec4>());
LOLUA_DECLARE_VOID_METHOD_ARGS(SetVertColor, EMLO, m_instance.SetVertColor, Get<vec4>());

/* /*
(csgu|csgunion) { return token::T_CSGUNION; } (csgu|csgunion) { return token::T_CSGUNION; }
(csgs|CsgSub) { return token::T_CSGSUBSTRACT; } (csgs|CsgSub) { return token::T_CSGSUBSTRACT; }
@@ -640,6 +120,7 @@ public:
(csgx|csgxor) { return token::T_CSGXOR; } (csgx|csgxor) { return token::T_CSGXOR; }
*/ */


#undef EMLO
}; };


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------


+ 12
- 10
src/gpu/framebuffer.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -343,14 +345,14 @@ ivec2 Framebuffer::GetSize() const
return m_data->m_size; return m_data->m_size;
} }


Image Framebuffer::GetImage() const
image Framebuffer::GetImage() const
{ {
Image ret(m_data->m_size);
image ret(m_data->m_size);


u8vec4 *buffer = ret.Lock<PixelFormat::RGBA_8>();
u8vec4 *buffer = ret.lock<PixelFormat::RGBA_8>();
glReadPixels(0, 0, m_data->m_size.x, m_data->m_size.y, glReadPixels(0, 0, m_data->m_size.x, m_data->m_size.y,
GL_RGBA, GL_UNSIGNED_BYTE, buffer); GL_RGBA, GL_UNSIGNED_BYTE, buffer);
ret.Unlock(buffer);
ret.unlock(buffer);


return ret; return ret;
} }


+ 31
- 0
src/gpu/rendercontext.cpp View File

@@ -59,6 +59,8 @@ private:
TrackedState<DepthMask> m_depth_mask; TrackedState<DepthMask> m_depth_mask;
TrackedState<CullMode> m_cull_mode; TrackedState<CullMode> m_cull_mode;
TrackedState<PolygonMode> m_polygon_mode; TrackedState<PolygonMode> m_polygon_mode;
TrackedState<ScissorMode> m_scissor_mode;
TrackedState<vec4> m_scissor_rect;
}; };


/* /*
@@ -101,6 +103,9 @@ RenderContext::~RenderContext()
if (m_data->m_polygon_mode.HasChanged()) if (m_data->m_polygon_mode.HasChanged())
Renderer::Get()->SetPolygonMode(m_data->m_polygon_mode.GetValue()); Renderer::Get()->SetPolygonMode(m_data->m_polygon_mode.GetValue());


if (m_data->m_scissor_mode.HasChanged())
Renderer::Get()->SetScissorMode(m_data->m_scissor_mode.GetValue());

delete m_data; delete m_data;
} }


@@ -255,5 +260,31 @@ PolygonMode RenderContext::GetPolygonMode()
return Renderer::Get()->GetPolygonMode(); return Renderer::Get()->GetPolygonMode();
} }


void RenderContext::SetScissorMode(ScissorMode mode)
{
if (!m_data->m_scissor_mode.HasChanged())
m_data->m_scissor_mode.TrackValue(Renderer::Get()->GetScissorMode());

Renderer::Get()->SetScissorMode(mode);
}

void RenderContext::SetScissorRect(vec4 rect)
{
if (!m_data->m_scissor_rect.HasChanged())
m_data->m_scissor_rect.TrackValue(Renderer::Get()->GetScissorRect());

Renderer::Get()->SetScissorRect(rect);
}

ScissorMode RenderContext::GetScissorMode()
{
return Renderer::Get()->GetScissorMode();
}

vec4 RenderContext::GetScissorRect()
{
return Renderer::Get()->GetScissorRect();
}

} /* namespace lol */ } /* namespace lol */



+ 42
- 0
src/gpu/renderer.cpp View File

@@ -54,6 +54,8 @@ private:
DepthMask m_depth_mask; DepthMask m_depth_mask;
CullMode m_cull_mode; CullMode m_cull_mode;
PolygonMode m_polygon_mode; PolygonMode m_polygon_mode;
ScissorMode m_scissor_mode;
vec4 m_scissor_rect;
}; };


/* /*
@@ -107,6 +109,9 @@ Renderer::Renderer(ivec2 size)
m_data->m_polygon_mode = PolygonMode::Point; m_data->m_polygon_mode = PolygonMode::Point;
SetPolygonMode(PolygonMode::Fill); SetPolygonMode(PolygonMode::Fill);


m_data->m_scissor_mode = ScissorMode::Disabled;
SetPolygonMode(PolygonMode::Fill);

/* Add some rendering states that we don't export to the user */ /* Add some rendering states that we don't export to the user */
#if defined HAVE_GL_2X && !defined __APPLE__ #if defined HAVE_GL_2X && !defined __APPLE__
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
@@ -548,5 +553,42 @@ PolygonMode Renderer::GetPolygonMode() const
return m_data->m_polygon_mode; return m_data->m_polygon_mode;
} }


/*
* Scissor test mode
*/

void Renderer::SetScissorMode(ScissorMode mode)
{
if (m_data->m_scissor_mode == mode)
return;

if (mode == ScissorMode::Enabled)
glEnable(GL_SCISSOR_TEST);
else
glDisable(GL_SCISSOR_TEST);

m_data->m_scissor_mode = mode;
}

void Renderer::SetScissorRect(vec4 rect)
{
m_data->m_scissor_rect = rect;
if (m_data->m_scissor_mode == ScissorMode::Enabled)
{
glScissor((int)rect.x, (int)Video::GetSize().y - rect.w, (int)(rect.z - rect.x), (int)(rect.w - rect.y));
//glScissor((int)rect.x, (int)rect.y, (int)(rect.z - rect.x), (int)(rect.w - rect.y));
}
}

ScissorMode Renderer::GetScissorMode() const
{
return m_data->m_scissor_mode;
}

vec4 Renderer::GetScissorRect() const
{
return m_data->m_scissor_rect;
}

} /* namespace lol */ } /* namespace lol */



+ 8
- 8
src/image/codec/android-image.cpp View File

@@ -21,7 +21,7 @@ extern "C" {
#include <android_native_app_glue.h> #include <android_native_app_glue.h>
} }


#include "../../image/image-private.h"
#include "../../image/resource-private.h"


namespace lol namespace lol
{ {
@@ -32,12 +32,12 @@ extern ANativeActivity *g_activity;
* Image implementation class * Image implementation class
*/ */


class AndroidImageCodec : public ImageCodec
class AndroidImageCodec : public ResourceCodec
{ {
public: public:
virtual char const *GetName() { return "<AndroidImageCodec>"; } virtual char const *GetName() { return "<AndroidImageCodec>"; }
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual ResourceCodecData* Load(char const *path);
virtual bool Save(char const *path, ResourceCodecData* data);
virtual bool Close(); virtual bool Close();


virtual uint8_t *GetData() const; virtual uint8_t *GetData() const;
@@ -50,7 +50,7 @@ private:


DECLARE_IMAGE_CODEC(AndroidImageCodec, 100) DECLARE_IMAGE_CODEC(AndroidImageCodec, 100)


bool AndroidImageCodec::Load(Image *image, char const *path)
ResourceCodecData* AndroidImageCodec::Load(char const *path)
{ {
JNIEnv *env; JNIEnv *env;
jint res = g_activity->vm->GetEnv((void **)&env, JNI_VERSION_1_2); jint res = g_activity->vm->GetEnv((void **)&env, JNI_VERSION_1_2);
@@ -106,12 +106,12 @@ bool AndroidImageCodec::Load(Image *image, char const *path)
} }
m_format = PixelFormat::RGBA_8; m_format = PixelFormat::RGBA_8;


return true;
return new ResourceCodecData();
} }


bool AndroidImageCodec::Save(Image *image, char const *path)
bool AndroidImageCodec::Save(char const *path, ResourceCodecData* data)
{ {
UNUSED(path);
UNUSED(path, data);


/* TODO: unimplemented */ /* TODO: unimplemented */
} }


+ 22
- 19
src/image/codec/dummy-image.cpp View File

@@ -1,16 +1,18 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>


#include "../../image/image-private.h"
#include "../../image/resource-private.h"


namespace lol namespace lol
{ {
@@ -19,12 +21,12 @@ namespace lol
* Image implementation class * Image implementation class
*/ */


class DummyImageCodec : public ImageCodec
class DummyImageCodec : public ResourceCodec
{ {
public: public:
virtual char const *GetName() { return "<DummyImageCodec>"; } virtual char const *GetName() { return "<DummyImageCodec>"; }
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual ResourceCodecData* Load(char const *path);
virtual bool Save(char const *path, ResourceCodecData* data);
}; };


//Priority 0 because it's supposed to be the last one //Priority 0 because it's supposed to be the last one
@@ -34,12 +36,14 @@ DECLARE_IMAGE_CODEC(DummyImageCodec, 0)
* Public Image class * Public Image class
*/ */


bool DummyImageCodec::Load(Image *image, char const *path)
ResourceCodecData* DummyImageCodec::Load(char const *path)
{ {
UNUSED(path);
if (strcmp("DUMMY", path))
return nullptr;


image->SetSize(ivec2(256));
u8vec4 *pixels = image->Lock<PixelFormat::RGBA_8>(), *tmp = pixels;
auto data = new ResourceImageData(new image(ivec2(256)));
auto image = data->m_image;
u8vec4 *pixels = image->lock<PixelFormat::RGBA_8>(), *tmp = pixels;
for (int j = 0; j < 256; j++) for (int j = 0; j < 256; j++)
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
{ {
@@ -49,15 +53,14 @@ bool DummyImageCodec::Load(Image *image, char const *path)
tmp->a = (((i >> 4) ^ (j >> 4)) & 1) * 0xff; tmp->a = (((i >> 4) ^ (j >> 4)) & 1) * 0xff;
++tmp; ++tmp;
} }
image->Unlock(pixels);
image->unlock(pixels);


//return false, because we're not supposed to be here.
return false;
return data;
} }


bool DummyImageCodec::Save(Image *image, char const *path)
bool DummyImageCodec::Save(char const *path, ResourceCodecData* data)
{ {
UNUSED(path);
UNUSED(path, data);


return false; return false;
} }


+ 23
- 17
src/image/codec/gdiplus-image.cpp View File

@@ -1,7 +1,7 @@
// //
// Lol Engine // Lol Engine
// //
// Copyright © 2010—2016 Sam Hocevar <sam@hocevar.net>
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
// //
// Lol Engine is free software. It comes without any warranty, to // Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it // the extent permitted by applicable law. You can redistribute it
@@ -26,7 +26,7 @@ using std::max;


#if LOL_USE_GDIPLUS #if LOL_USE_GDIPLUS


#include "../../image/image-private.h"
#include "../../image/resource-private.h"


namespace lol namespace lol
{ {
@@ -35,12 +35,12 @@ namespace lol
* Image implementation class * Image implementation class
*/ */


class GdiPlusImageCodec : public ImageCodec
class GdiPlusImageCodec : public ResourceCodec
{ {
public: public:
virtual char const *GetName() { return "<GdiPlusImageCodec>"; } virtual char const *GetName() { return "<GdiPlusImageCodec>"; }
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual ResourceCodecData* Load(char const *path);
virtual bool Save(char const *path, ResourceCodecData* data);
}; };


DECLARE_IMAGE_CODEC(GdiPlusImageCodec, 100) DECLARE_IMAGE_CODEC(GdiPlusImageCodec, 100)
@@ -49,7 +49,7 @@ DECLARE_IMAGE_CODEC(GdiPlusImageCodec, 100)
* Public Image class * Public Image class
*/ */


bool GdiPlusImageCodec::Load(Image *image, char const *path)
ResourceCodecData* GdiPlusImageCodec::Load(char const *path)
{ {
Gdiplus::Status status; Gdiplus::Status status;
ULONG_PTR token; ULONG_PTR token;
@@ -58,7 +58,7 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path)
if (status != Gdiplus::Ok) if (status != Gdiplus::Ok)
{ {
msg::error("error %d while initialising GDI+\n", status); msg::error("error %d while initialising GDI+\n", status);
return false;
return nullptr;
} }


array<String> pathlist = sys::get_path_list(path); array<String> pathlist = sys::get_path_list(path);
@@ -99,7 +99,7 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path)
if (!bitmap) if (!bitmap)
{ {
msg::error("could not load %s\n", path); msg::error("could not load %s\n", path);
return false;
return nullptr;
} }


ivec2 size(bitmap->GetWidth(), bitmap->GetHeight()); ivec2 size(bitmap->GetWidth(), bitmap->GetHeight());
@@ -110,27 +110,32 @@ bool GdiPlusImageCodec::Load(Image *image, char const *path)
{ {
msg::error("could not lock bits in %s\n", path); msg::error("could not lock bits in %s\n", path);
delete bitmap; delete bitmap;
return false;
return nullptr;
} }


/* FIXME: GDI+ doesn't know about RGBA, only ARGB. And OpenGL doesn't /* FIXME: GDI+ doesn't know about RGBA, only ARGB. And OpenGL doesn't
* know about ARGB, only RGBA. So we swap bytes. We could also fix * know about ARGB, only RGBA. So we swap bytes. We could also fix
* this in the shader. */ * this in the shader. */
image->SetSize(size);
u8vec4 *pdst = image->Lock<PixelFormat::RGBA_8>();
auto data = new ResourceImageData(new image(ivec2(size)));
auto image = data->m_image;
u8vec4 *pdst = image->lock<PixelFormat::RGBA_8>();
u8vec4 *psrc = static_cast<u8vec4 *>(bdata.Scan0); u8vec4 *psrc = static_cast<u8vec4 *>(bdata.Scan0);
for (int n = 0; n < size.x * size.y; n++) for (int n = 0; n < size.x * size.y; n++)
pdst[n] = psrc[n].bgra; pdst[n] = psrc[n].bgra;
image->Unlock(pdst);
image->unlock(pdst);


bitmap->UnlockBits(&bdata); bitmap->UnlockBits(&bdata);
delete bitmap; delete bitmap;


return true;
return data;
} }


bool GdiPlusImageCodec::Save(Image *image, char const *path)
bool GdiPlusImageCodec::Save(char const *path, ResourceCodecData* data)
{ {
auto data_image = dynamic_cast<ResourceImageData*>(data);
if (data_image == nullptr)
return false;

ULONG_PTR token; ULONG_PTR token;
Gdiplus::GdiplusStartupInput input; Gdiplus::GdiplusStartupInput input;
Gdiplus::GdiplusStartup(&token, &input, nullptr); Gdiplus::GdiplusStartup(&token, &input, nullptr);
@@ -178,7 +183,8 @@ bool GdiPlusImageCodec::Save(Image *image, char const *path)
return false; return false;
} }


ivec2 size = image->GetSize();
auto image = data_image->m_image;
ivec2 size = image->size();


Gdiplus::Bitmap *b = new Gdiplus::Bitmap(size.x, size.y, Gdiplus::Bitmap *b = new Gdiplus::Bitmap(size.x, size.y,
PixelFormat32bppARGB); PixelFormat32bppARGB);
@@ -195,13 +201,13 @@ bool GdiPlusImageCodec::Save(Image *image, char const *path)
return false; return false;
} }


u8vec4 *psrc = image->Lock<PixelFormat::RGBA_8>();
u8vec4 *psrc = image->lock<PixelFormat::RGBA_8>();
u8vec4 *psrc0 = psrc; u8vec4 *psrc0 = psrc;
u8vec4 *pdst = static_cast<u8vec4 *>(bdata.Scan0); u8vec4 *pdst = static_cast<u8vec4 *>(bdata.Scan0);
for (int y = 0; y < size.y; y++) for (int y = 0; y < size.y; y++)
for (int x = 0; x < size.x; x++) for (int x = 0; x < size.x; x++)
*pdst++ = (*psrc++).bgra; *pdst++ = (*psrc++).bgra;
image->Unlock(psrc0);
image->unlock(psrc0);
b->UnlockBits(&bdata); b->UnlockBits(&bdata);


if (b->Save(wpath, &clsid, nullptr) != Gdiplus::Ok) if (b->Save(wpath, &clsid, nullptr) != Gdiplus::Ok)


+ 23
- 16
src/image/codec/imlib2-image.cpp View File

@@ -1,7 +1,7 @@
// //
// Lol Engine // Lol Engine
// //
// Copyright © 2010—2016 Sam Hocevar <sam@hocevar.net>
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
// //
// Lol Engine is free software. It comes without any warranty, to // Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it // the extent permitted by applicable law. You can redistribute it
@@ -22,7 +22,7 @@ static_assert(sizeof(DATA32) == sizeof(uint32_t), "Imlib2 type DATA32 is broken"
static_assert(sizeof(DATA16) == sizeof(uint16_t), "Imlib2 type DATA16 is broken"); static_assert(sizeof(DATA16) == sizeof(uint16_t), "Imlib2 type DATA16 is broken");
static_assert(sizeof(DATA8) == sizeof(uint8_t), "Imlib2 type DATA8 is broken"); static_assert(sizeof(DATA8) == sizeof(uint8_t), "Imlib2 type DATA8 is broken");


#include "../../image/image-private.h"
#include "../../image/resource-private.h"


namespace lol namespace lol
{ {
@@ -31,17 +31,18 @@ namespace lol
* Imlib2 image codec * Imlib2 image codec
*/ */


class Imlib2ImageCodec : public ImageCodec
class Imlib2ImageCodec : public ResourceCodec
{ {
public: public:
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual char const *GetName() { return "<Imlib2ImageCodec>"; }
virtual ResourceCodecData* Load(char const *path);
virtual bool Save(char const *path, ResourceCodecData* data);
}; };


/* Set priority higher than SDL because we can save in many formats. */ /* Set priority higher than SDL because we can save in many formats. */
DECLARE_IMAGE_CODEC(Imlib2ImageCodec, 70) DECLARE_IMAGE_CODEC(Imlib2ImageCodec, 70)


bool Imlib2ImageCodec::Load(Image *image, char const *path)
ResourceCodecData *Imlib2ImageCodec::Load(char const *path)
{ {
Imlib_Image im = nullptr; Imlib_Image im = nullptr;


@@ -57,7 +58,7 @@ bool Imlib2ImageCodec::Load(Image *image, char const *path)
#if !LOL_BUILD_RELEASE #if !LOL_BUILD_RELEASE
msg::error("could not load image %s\n", path); msg::error("could not load image %s\n", path);
#endif #endif
return false;
return nullptr;
} }


imlib_context_set_image(im); imlib_context_set_image(im);
@@ -69,13 +70,14 @@ bool Imlib2ImageCodec::Load(Image *image, char const *path)
#if !LOL_BUILD_RELEASE #if !LOL_BUILD_RELEASE
msg::error("could not get image data for %s\n", path); msg::error("could not get image data for %s\n", path);
#endif #endif
return false;
return nullptr;
} }


ivec2 size(imlib_image_get_width(), imlib_image_get_height()); ivec2 size(imlib_image_get_width(), imlib_image_get_height());
image->SetSize(size);
auto data = new ResourceImageData(new image(size));
auto image = data->m_image;


u8vec4 *dstdata = image->Lock<PixelFormat::RGBA_8>();
u8vec4 *dstdata = image->lock<PixelFormat::RGBA_8>();


for (int i = 0; i < size.x * size.y; i++) for (int i = 0; i < size.x * size.y; i++)
{ {
@@ -84,22 +86,27 @@ bool Imlib2ImageCodec::Load(Image *image, char const *path)
else else
dstdata[i] = srcdata[i].bgra; dstdata[i] = srcdata[i].bgra;
} }
image->Unlock(dstdata);
image->unlock(dstdata);


imlib_free_image(); imlib_free_image();


return true;
return data;
} }


bool Imlib2ImageCodec::Save(Image *image, char const *path)
bool Imlib2ImageCodec::Save(char const *path, ResourceCodecData *data)
{ {
ivec2 size = image->GetSize();
auto data_image = dynamic_cast<ResourceImageData*>(data);
if (data_image == nullptr)
return false;

auto image = data_image->m_image;
ivec2 size = image->size();
Imlib_Image priv = imlib_create_image(size.x, size.y); Imlib_Image priv = imlib_create_image(size.x, size.y);


imlib_context_set_image(priv); imlib_context_set_image(priv);
imlib_image_set_has_alpha(1); imlib_image_set_has_alpha(1);


u8vec4 const *srcdata = image->Lock<PixelFormat::RGBA_8>();
u8vec4 const *srcdata = image->lock<PixelFormat::RGBA_8>();
u8vec4 *dstdata = (u8vec4 *)imlib_image_get_data(); u8vec4 *dstdata = (u8vec4 *)imlib_image_get_data();


for (int i = 0; i < size.x * size.y; i++) for (int i = 0; i < size.x * size.y; i++)
@@ -111,7 +118,7 @@ bool Imlib2ImageCodec::Save(Image *image, char const *path)
} }


imlib_image_put_back_data((DATA32 *)dstdata); imlib_image_put_back_data((DATA32 *)dstdata);
image->Unlock(srcdata);
image->unlock(srcdata);


imlib_save_image(path); imlib_save_image(path);
imlib_free_image(); imlib_free_image();


+ 9
- 9
src/image/codec/ios-image.cpp View File

@@ -16,7 +16,7 @@


#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>


#include "../../image/image-private.h"
#include "../../image/resource-private.h"


namespace lol namespace lol
{ {
@@ -25,12 +25,12 @@ namespace lol
* Image implementation class * Image implementation class
*/ */


class IosImageCodec : public ImageCodec
class IosImageCodec : public ResourceCodec
{ {
public: public:
virtual char const *GetName() { return "<IosImageCodec>"; } virtual char const *GetName() { return "<IosImageCodec>"; }
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual ResourceCodecData* Load(char const *path);
virtual bool Save(char const *path, ResourceCodecData* data);
}; };


DECLARE_IMAGE_CODEC(IosImageCodec, 100) DECLARE_IMAGE_CODEC(IosImageCodec, 100)
@@ -39,7 +39,7 @@ DECLARE_IMAGE_CODEC(IosImageCodec, 100)
* Public Image class * Public Image class
*/ */


bool IosImageCodec::Load(Image *image, char const *path)
ResourceCodecData* IosImageCodec::Load(char const *path)
{ {
NSString *fullpath = [NSString stringWithUTF8String:path]; NSString *fullpath = [NSString stringWithUTF8String:path];
NSArray *chunks = [fullpath componentsSeparatedByString: @"/"]; NSArray *chunks = [fullpath componentsSeparatedByString: @"/"];
@@ -54,7 +54,7 @@ bool IosImageCodec::Load(Image *image, char const *path)
#if !LOL_BUILD_RELEASE #if !LOL_BUILD_RELEASE
msg::error("could not load %s\n", path); msg::error("could not load %s\n", path);
#endif #endif
return false;
return nullptr;
} }


int w = CGImageGetWidth(image.CGImage); int w = CGImageGetWidth(image.CGImage);
@@ -75,12 +75,12 @@ bool IosImageCodec::Load(Image *image, char const *path)
[image release]; [image release];
[pngdata release]; [pngdata release];


return true;
return new ResourceCodecData();
} }


bool IosImageCodec::Save(Image *image, char const *path)
bool IosImageCodec::Save(char const *path, ResourceCodecData* data)
{ {
UNUSED(path);
UNUSED(path, data);


/* TODO: unimplemented */ /* TODO: unimplemented */
return true; return true;


+ 38
- 30
src/image/codec/oric-image.cpp View File

@@ -1,18 +1,20 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>


#include <cctype> #include <cctype>


#include "../../image/image-private.h"
#include "../../image/resource-private.h"


namespace lol namespace lol
{ {
@@ -27,16 +29,16 @@ namespace lol
* Image implementation class * Image implementation class
*/ */


class OricImageCodec : public ImageCodec
class OricImageCodec : public ResourceCodec
{ {
public: public:
virtual char const *GetName() { return "<OricImageCodec>"; } virtual char const *GetName() { return "<OricImageCodec>"; }
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual ResourceCodecData* Load(char const *path);
virtual bool Save(char const *path, ResourceCodecData* data);


private: private:
static String ReadScreen(char const *name); static String ReadScreen(char const *name);
static void WriteScreen(Image &image, array<uint8_t> &result);
static void WriteScreen(image &image, array<uint8_t> &result);
}; };


DECLARE_IMAGE_CODEC(OricImageCodec, 100) DECLARE_IMAGE_CODEC(OricImageCodec, 100)
@@ -45,7 +47,7 @@ DECLARE_IMAGE_CODEC(OricImageCodec, 100)
* Public Image class * Public Image class
*/ */


bool OricImageCodec::Load(Image *image, char const *path)
ResourceCodecData* OricImageCodec::Load(char const *path)
{ {
static u8vec4 const pal[8] = static u8vec4 const pal[8] =
{ {
@@ -61,13 +63,14 @@ bool OricImageCodec::Load(Image *image, char const *path)


String screen = ReadScreen(path); String screen = ReadScreen(path);
if (screen.count() == 0) if (screen.count() == 0)
return false;
return nullptr;


image->SetSize(ivec2(WIDTH, screen.count() * 6 / WIDTH));
auto data = new ResourceImageData(new image(ivec2(WIDTH, screen.count() * 6 / WIDTH)));
auto img = data->m_image;


u8vec4 *pixels = image->Lock<PixelFormat::RGBA_8>();
u8vec4 *pixels = img->lock<PixelFormat::RGBA_8>();


for (int y = 0; y < image->GetSize().y; y++)
for (int y = 0; y < img->size().y; y++)
{ {
u8vec2 bgfg(0, 7); u8vec2 bgfg(0, 7);


@@ -100,14 +103,18 @@ bool OricImageCodec::Load(Image *image, char const *path)
} }
} }


image->Unlock(pixels);
img->unlock(pixels);


return true;
return data;
} }


bool OricImageCodec::Save(Image *image, char const *path)
bool OricImageCodec::Save(char const *path, ResourceCodecData* data)
{ {
int len = strlen(path);
auto data_image = dynamic_cast<ResourceImageData*>(data);
if (data_image == nullptr)
return false;

int len = (int)strlen(path);
if (len < 4 || path[len - 4] != '.' if (len < 4 || path[len - 4] != '.'
|| toupper(path[len - 3]) != 'T' || toupper(path[len - 3]) != 'T'
|| toupper(path[len - 2]) != 'A' || toupper(path[len - 2]) != 'A'
@@ -124,17 +131,18 @@ bool OricImageCodec::Save(Image *image, char const *path)
result << (uint8_t)name[0]; result << (uint8_t)name[0];
result << 0; result << 0;


Image tmp;
ivec2 size = image->GetSize();
auto img = data_image->m_image;
image tmp;
ivec2 size = img->size();
if (size.x != WIDTH) if (size.x != WIDTH)
{ {
size.y = (int)((float)size.y * WIDTH / size.x); size.y = (int)((float)size.y * WIDTH / size.x);
size.x = WIDTH; size.x = WIDTH;
tmp = image->Resize(size, ResampleAlgorithm::Bresenham);
image = &tmp;
tmp = img->Resize(size, ResampleAlgorithm::Bresenham);
img = &tmp;
} }


WriteScreen(*image, result);
WriteScreen(*img, result);


File f; File f;
f.Open(path, FileAccess::Write); f.Open(path, FileAccess::Write);
@@ -463,10 +471,10 @@ static uint8_t bestmove(ivec3 const *in, u8vec2 bgfg,
return bestcommand; return bestcommand;
} }


void OricImageCodec::WriteScreen(Image &image, array<uint8_t> &result)
void OricImageCodec::WriteScreen(image &img, array<uint8_t> &result)
{ {
ivec2 size = image.GetSize();
vec4 *pixels = image.Lock<PixelFormat::RGBA_F32>();
ivec2 size = img.size();
vec4 *pixels = img.lock<PixelFormat::RGBA_F32>();


int stride = (size.x + 1); int stride = (size.x + 1);


@@ -481,7 +489,7 @@ void OricImageCodec::WriteScreen(Image &image, array<uint8_t> &result)
for (int y = 0; y < size.y; y++) for (int y = 0; y < size.y; y++)
for (int x = 0; x < size.x; x++) for (int x = 0; x < size.x; x++)
for (int c = 0; c < 3; c++) for (int c = 0; c < 3; c++)
src[x][y][c] = 0xffff * pixels[y * size.x + x][2 - c];
src[x][y][c] = 0xffff * (int32_t)pixels[y * size.x + x][2 - c];


/* Let the fun begin */ /* Let the fun begin */
for (int y = 0; y < size.y; y++) for (int y = 0; y < size.y; y++)
@@ -520,7 +528,7 @@ void OricImageCodec::WriteScreen(Image &image, array<uint8_t> &result)
} }
} }


image.Unlock(pixels);
img.unlock(pixels);


//fprintf(stderr, " done.\n"); //fprintf(stderr, " done.\n");
} }


+ 23
- 17
src/image/codec/sdl-image.cpp View File

@@ -1,7 +1,7 @@
// //
// Lol Engine // Lol Engine
// //
// Copyright © 2010—2016 Sam Hocevar <sam@hocevar.net>
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
// //
// Lol Engine is free software. It comes without any warranty, to // Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it // the extent permitted by applicable law. You can redistribute it
@@ -25,7 +25,7 @@
# include <SDL_image.h> # include <SDL_image.h>
#endif #endif


#include "../../image/image-private.h"
#include "../../image/resource-private.h"


namespace lol namespace lol
{ {
@@ -34,19 +34,19 @@ namespace lol
* Image implementation class * Image implementation class
*/ */


class SdlImageCodec : public ImageCodec
class SdlImageCodec : public ResourceCodec
{ {
public: public:
virtual char const *GetName() { return "<SdlImageCodec>"; } virtual char const *GetName() { return "<SdlImageCodec>"; }
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual ResourceCodecData* Load(char const *path);
virtual bool Save(char const *path, ResourceCodecData* data);


static SDL_Surface *Create32BppSurface(ivec2 size); static SDL_Surface *Create32BppSurface(ivec2 size);
}; };


DECLARE_IMAGE_CODEC(SdlImageCodec, 50) DECLARE_IMAGE_CODEC(SdlImageCodec, 50)


bool SdlImageCodec::Load(Image *image, char const *path)
ResourceCodecData* SdlImageCodec::Load(char const *path)
{ {
SDL_Surface *surface = nullptr; SDL_Surface *surface = nullptr;


@@ -62,7 +62,7 @@ bool SdlImageCodec::Load(Image *image, char const *path)
#if !LOL_BUILD_RELEASE #if !LOL_BUILD_RELEASE
msg::error("could not load image %s\n", path); msg::error("could not load image %s\n", path);
#endif #endif
return false;
return nullptr;
} }


ivec2 size(surface->w, surface->h); ivec2 size(surface->w, surface->h);
@@ -75,24 +75,30 @@ bool SdlImageCodec::Load(Image *image, char const *path)
surface = tmp; surface = tmp;
} }


image->SetSize(size);
u8vec4 *data = image->Lock<PixelFormat::RGBA_8>();
memcpy(data, surface->pixels, 4 * size.x * size.y);
image->Unlock(data);
auto data = new ResourceImageData(new image(size));
auto image = data->m_image;
u8vec4 *pixel_data = image->lock<PixelFormat::RGBA_8>();
memcpy(pixel_data, surface->pixels, 4 * size.x * size.y);
image->unlock(pixel_data);


SDL_FreeSurface(surface); SDL_FreeSurface(surface);


return true;
return data;
} }


bool SdlImageCodec::Save(Image *image, char const *path)
bool SdlImageCodec::Save(char const *path, ResourceCodecData* data)
{ {
ivec2 size = image->GetSize();
auto data_image = dynamic_cast<ResourceImageData*>(data);
if (data_image == nullptr)
return false;

auto image = data_image->m_image;
ivec2 size = image->size();
SDL_Surface *surface = Create32BppSurface(size); SDL_Surface *surface = Create32BppSurface(size);


u8vec4 *data = image->Lock<PixelFormat::RGBA_8>();
memcpy(surface->pixels, data, 4 * size.x * size.y);
image->Unlock(data);
u8vec4 *pixel_data = image->lock<PixelFormat::RGBA_8>();
memcpy(surface->pixels, pixel_data, 4 * size.x * size.y);
image->unlock(pixel_data);


int ret = SDL_SaveBMP(surface, path); int ret = SDL_SaveBMP(surface, path);
SDL_FreeSurface(surface); SDL_FreeSurface(surface);


+ 39
- 41
src/image/codec/zed-image.cpp View File

@@ -1,17 +1,19 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2014 Benjamin Huet <huet.benjamin@gmail.com>
// 2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
// 2014 Benjamin Huet <huet.benjamin@gmail.com>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>


#include "../../image/image-private.h"
#include "../../image/resource-private.h"


namespace lol namespace lol
{ {
@@ -20,24 +22,12 @@ namespace lol
* Image implementation class * Image implementation class
*/ */


class ZedImageCodec : public ImageCodec
class ZedImageCodec : public ResourceCodec
{ {
public: public:
virtual char const *GetName() { return "<ZedImageCodec>"; } virtual char const *GetName() { return "<ZedImageCodec>"; }
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);

virtual bool RetrieveTiles(array<ivec2, ivec2>& tiles)
{
bool result = m_tiles.count() > 0;
tiles += m_tiles;
m_tiles.empty();
return result;
}

private:
//<Pos, Size>
array<ivec2, ivec2> m_tiles;
virtual ResourceCodecData* Load(char const *path);
virtual bool Save(char const *path, ResourceCodecData* data);
}; };


DECLARE_IMAGE_CODEC(ZedImageCodec, 10) DECLARE_IMAGE_CODEC(ZedImageCodec, 10)
@@ -46,17 +36,17 @@ DECLARE_IMAGE_CODEC(ZedImageCodec, 10)
* Public Image class * Public Image class
*/ */


bool ZedImageCodec::Load(Image *image, char const *path)
ResourceCodecData* ZedImageCodec::Load(char const *path)
{ {
if (!lol::String(path).ends_with(".RSC")) if (!lol::String(path).ends_with(".RSC"))
return false;
return nullptr;


// Compacter definition // Compacter definition
struct CompactSecondary struct CompactSecondary
{ {
CompactSecondary(int32_t size) { m_size = size; } CompactSecondary(int32_t size) { m_size = size; }
int32_t m_size;
array<int32_t> m_tiles;
int32_t m_size;
array<int32_t> m_tiles;
}; };
struct CompactMain struct CompactMain
{ {
@@ -120,7 +110,7 @@ bool ZedImageCodec::Load(Image *image, char const *path)
file.Open(path, FileAccess::Read, true); file.Open(path, FileAccess::Read, true);


//Put file in memory //Put file in memory
long file_size = file.GetSize();
long file_size = file.size();
array<uint8_t> file_buffer; array<uint8_t> file_buffer;
file_buffer.resize(file_size); file_buffer.resize(file_size);
file.Read((uint8_t*)&file_buffer[0], file_size); file.Read((uint8_t*)&file_buffer[0], file_size);
@@ -142,7 +132,9 @@ bool ZedImageCodec::Load(Image *image, char const *path)
} }
file_offset << file_size; file_offset << file_size;


m_tiles.reserve(file_count);
//<Pos, Size>
array<ivec2, ivec2> tiles;
tiles.reserve(file_count);


Compacter2d compacter; Compacter2d compacter;
compacter.StepSetup(8, 8, 10); compacter.StepSetup(8, 8, 10);
@@ -151,6 +143,7 @@ bool ZedImageCodec::Load(Image *image, char const *path)
array<uint8_t> file_convert; array<uint8_t> file_convert;
file_convert.reserve(file_size); file_convert.reserve(file_size);
array<ivec2> available_sizes; array<ivec2> available_sizes;
//got through all the files and store them
for (int i = 0; i < file_count; i++) for (int i = 0; i < file_count; i++)
{ {
file_pos = file_offset[i]; file_pos = file_offset[i];
@@ -187,8 +180,10 @@ bool ZedImageCodec::Load(Image *image, char const *path)
//Prepare buffer and tiles infos //Prepare buffer and tiles infos
int32_t convert_pos = file_convert.count(); int32_t convert_pos = file_convert.count();
ivec2 size = ivec2(size_x, size_y); ivec2 size = ivec2(size_x, size_y);
compacter.Store(m_tiles.count(), ivec2(size_x, size_y));
m_tiles.push(ivec2(file_convert.count(), data_length), ivec2(size_x, size_y));
//store tile in compacter
compacter.Store(tiles.count(), ivec2(size_x, size_y));
//push tile on the stack
tiles.push(ivec2(file_convert.count(), data_length), ivec2(size_x, size_y));
file_convert.resize(convert_pos + data_length); file_convert.resize(convert_pos + data_length);


//Retrieve actual datas //Retrieve actual datas
@@ -233,9 +228,10 @@ bool ZedImageCodec::Load(Image *image, char const *path)
while (tex_size < tex_sqrt) while (tex_size < tex_sqrt)
tex_size <<= 1; tex_size <<= 1;


//Prepare final imqge
image->SetSize(ivec2(tex_size));
uint8_t *pixels = image->Lock<PixelFormat::Y_8>();
//Prepare final image
auto data = new ResourceTilesetData(new image(ivec2(tex_size)));
auto image = data->m_image;
uint8_t *pixels = image->lock<PixelFormat::Y_8>();


//Data refactor stage //Data refactor stage
ivec2 pos = ivec2(0); ivec2 pos = ivec2(0);
@@ -255,8 +251,8 @@ bool ZedImageCodec::Load(Image *image, char const *path)


compacter.m_primary[j].m_count--; compacter.m_primary[j].m_count--;
int i = compacter.m_primary[j].m_secondary[k].m_tiles.pop(); int i = compacter.m_primary[j].m_secondary[k].m_tiles.pop();
int32_t file_off = m_tiles[i].m1[0];
ivec2 t_size = m_tiles[i].m2;
int32_t file_off = tiles[i].m1[0];
ivec2 t_size = tiles[i].m2;


ASSERT(pos.y + t_size.y < tex_size); ASSERT(pos.y + t_size.y < tex_size);


@@ -277,7 +273,7 @@ bool ZedImageCodec::Load(Image *image, char const *path)
} }


//Register new pos and move to next //Register new pos and move to next
m_tiles[i].m1 = pos;
tiles[i].m1 = pos;
pos.x += t_size.x; pos.x += t_size.x;
} }
} }
@@ -290,14 +286,16 @@ bool ZedImageCodec::Load(Image *image, char const *path)
j++; j++;
} }
} }
image->Unlock(pixels);
image->unlock(pixels);


return true;
data->m_tiles = tiles;

return data;
} }


bool ZedImageCodec::Save(Image *image, char const *path)
bool ZedImageCodec::Save(char const *path, ResourceCodecData* data)
{ {
UNUSED(path);
UNUSED(path, data);
/* FIXME: do we need to implement this? */ /* FIXME: do we need to implement this? */
return true; return true;
} }


+ 26
- 21
src/image/codec/zed-palette-image.cpp View File

@@ -1,16 +1,19 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
// 2014 Benjamin Huet <huet.benjamin@gmail.com>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>


#include "../../image/image-private.h"
#include "../../image/resource-private.h"


namespace lol namespace lol
{ {
@@ -19,12 +22,12 @@ namespace lol
* Image implementation class * Image implementation class
*/ */


class ZedPaletteImageCodec : public ImageCodec
class ZedPaletteImageCodec : public ResourceCodec
{ {
public: public:
virtual char const *GetName() { return "<ZedPaletteImageCodec>"; } virtual char const *GetName() { return "<ZedPaletteImageCodec>"; }
virtual bool Load(Image *image, char const *path);
virtual bool Save(Image *image, char const *path);
virtual ResourceCodecData* Load(char const *path);
virtual bool Save(char const *path, ResourceCodecData* data);
}; };


DECLARE_IMAGE_CODEC(ZedPaletteImageCodec, 10) DECLARE_IMAGE_CODEC(ZedPaletteImageCodec, 10)
@@ -33,16 +36,16 @@ DECLARE_IMAGE_CODEC(ZedPaletteImageCodec, 10)
* Public Image class * Public Image class
*/ */


bool ZedPaletteImageCodec::Load(Image *image, char const *path)
ResourceCodecData* ZedPaletteImageCodec::Load(char const *path)
{ {
if (!lol::String(path).ends_with(".pal")) if (!lol::String(path).ends_with(".pal"))
return false;
return nullptr;


File file; File file;
file.Open(path, FileAccess::Read, true); file.Open(path, FileAccess::Read, true);


//Put file in memory
long file_size = file.GetSize();
// Put file in memory
long file_size = file.size();
array<uint8_t> file_buffer; array<uint8_t> file_buffer;
file_buffer.resize(file_size); file_buffer.resize(file_size);
file.Read((uint8_t*)&file_buffer[0], file_size); file.Read((uint8_t*)&file_buffer[0], file_size);
@@ -53,16 +56,18 @@ bool ZedPaletteImageCodec::Load(Image *image, char const *path)
int32_t tex_size = 2; int32_t tex_size = 2;
while (tex_size < tex_sqrt) while (tex_size < tex_sqrt)
tex_size <<= 1; tex_size <<= 1;
image->m_data->m_size = ivec2(tex_size);
auto data = new ResourceImageData(new image(ivec2(tex_size)));
auto image = data->m_image;
#else #else
int32_t tex_sqrt = file_size / 3; int32_t tex_sqrt = file_size / 3;
int32_t tex_size = 2; int32_t tex_size = 2;
while (tex_size < tex_sqrt) while (tex_size < tex_sqrt)
tex_size <<= 1; tex_size <<= 1;
image->SetSize(ivec2(tex_size, 1));
auto data = new ResourceImageData(new image(ivec2(tex_size, 1)));
auto image = data->m_image;
#endif #endif


u8vec4 *pixels = image->Lock<PixelFormat::RGBA_8>();
u8vec4 *pixels = image->lock<PixelFormat::RGBA_8>();
for (int i = 0; i < file_buffer.count();) for (int i = 0; i < file_buffer.count();)
{ {
pixels->r = file_buffer[i++]; pixels->r = file_buffer[i++];
@@ -71,14 +76,14 @@ bool ZedPaletteImageCodec::Load(Image *image, char const *path)
pixels->a = (i == 0) ? 0 : 255; pixels->a = (i == 0) ? 0 : 255;
++pixels; ++pixels;
} }
image->Unlock(pixels);
image->unlock(pixels);


return true;
return data;
} }


bool ZedPaletteImageCodec::Save(Image *image, char const *path)
bool ZedPaletteImageCodec::Save(char const *path, ResourceCodecData* data)
{ {
UNUSED(path);
UNUSED(path, data);
/* FIXME: do we need to implement this? */ /* FIXME: do we need to implement this? */
return true; return true;
} }


+ 47
- 45
src/image/combine.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -33,18 +35,18 @@ enum class MergeMode
}; };


template<PixelFormat FORMAT, MergeMode MODE> template<PixelFormat FORMAT, MergeMode MODE>
static Image GenericMerge(Image &src1, Image &src2, float alpha)
static image generic_merge(image &src1, image &src2, float alpha)
{ {
typedef typename PixelType<FORMAT>::type pixel_t; typedef typename PixelType<FORMAT>::type pixel_t;


ASSERT(src1.GetSize() == src2.GetSize());
int const count = src1.GetSize().x * src2.GetSize().y;
ASSERT(src1.size() == src2.size());
int const count = src1.size().x * src2.size().y;


Image dst(src1.GetSize());
image dst(src1.size());


pixel_t const *src1p = src1.Lock<FORMAT>();
pixel_t const *src2p = src2.Lock<FORMAT>();
pixel_t *dstp = dst.Lock<FORMAT>();
pixel_t const *src1p = src1.lock<FORMAT>();
pixel_t const *src2p = src2.lock<FORMAT>();
pixel_t *dstp = dst.lock<FORMAT>();


for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
{ {
@@ -71,80 +73,80 @@ static Image GenericMerge(Image &src1, Image &src2, float alpha)
dstp[n] = lol::abs(src1p[n] - src2p[n]); dstp[n] = lol::abs(src1p[n] - src2p[n]);
} }


src1.Unlock(src1p);
src2.Unlock(src2p);
dst.Unlock(dstp);
src1.unlock(src1p);
src2.unlock(src2p);
dst.unlock(dstp);


return dst; return dst;
} }


template<MergeMode MODE> template<MergeMode MODE>
static Image GenericMerge(Image &src1, Image &src2, float alpha)
static image generic_merge(image &src1, image &src2, float alpha)
{ {
bool gray1 = src1.GetFormat() == PixelFormat::Y_8
|| src1.GetFormat() == PixelFormat::Y_F32;
bool gray2 = src2.GetFormat() == PixelFormat::Y_8
|| src2.GetFormat() == PixelFormat::Y_F32;
bool gray1 = src1.format() == PixelFormat::Y_8
|| src1.format() == PixelFormat::Y_F32;
bool gray2 = src2.format() == PixelFormat::Y_8
|| src2.format() == PixelFormat::Y_F32;
if (gray1 && gray2) if (gray1 && gray2)
return GenericMerge<PixelFormat::Y_F32, MODE>(src1, src2, alpha);
return generic_merge<PixelFormat::Y_F32, MODE>(src1, src2, alpha);
else else
return GenericMerge<PixelFormat::RGBA_F32, MODE>(src1, src2, alpha);
return generic_merge<PixelFormat::RGBA_F32, MODE>(src1, src2, alpha);


} }


Image Image::Merge(Image &src1, Image &src2, float alpha)
image image::Merge(image &src1, image &src2, float alpha)
{ {
return GenericMerge<MergeMode::Mix>(src1, src2, alpha);
return generic_merge<MergeMode::Mix>(src1, src2, alpha);
} }


Image Image::Mean(Image &src1, Image &src2)
image image::Mean(image &src1, image &src2)
{ {
return GenericMerge<MergeMode::Mix>(src1, src2, 0.5f);
return generic_merge<MergeMode::Mix>(src1, src2, 0.5f);
} }


Image Image::Min(Image &src1, Image &src2)
image image::Min(image &src1, image &src2)
{ {
return GenericMerge<MergeMode::Min>(src1, src2, 0.0f);
return generic_merge<MergeMode::Min>(src1, src2, 0.0f);
} }


Image Image::Max(Image &src1, Image &src2)
image image::Max(image &src1, image &src2)
{ {
return GenericMerge<MergeMode::Max>(src1, src2, 0.0f);
return generic_merge<MergeMode::Max>(src1, src2, 0.0f);
} }


Image Image::Overlay(Image &src1, Image &src2)
image image::Overlay(image &src1, image &src2)
{ {
return GenericMerge<MergeMode::Overlay>(src1, src2, 0.0f);
return generic_merge<MergeMode::Overlay>(src1, src2, 0.0f);
} }


Image Image::Screen(Image &src1, Image &src2)
image image::Screen(image &src1, image &src2)
{ {
return GenericMerge<MergeMode::Screen>(src1, src2, 0.0f);
return generic_merge<MergeMode::Screen>(src1, src2, 0.0f);
} }


Image Image::Divide(Image &src1, Image &src2)
image image::Divide(image &src1, image &src2)
{ {
return GenericMerge<MergeMode::Divide>(src1, src2, 0.0f);
return generic_merge<MergeMode::Divide>(src1, src2, 0.0f);
} }


Image Image::Multiply(Image &src1, Image &src2)
image image::Multiply(image &src1, image &src2)
{ {
return GenericMerge<MergeMode::Multiply>(src1, src2, 0.0f);
return generic_merge<MergeMode::Multiply>(src1, src2, 0.0f);
} }


Image Image::Add(Image &src1, Image &src2)
image image::Add(image &src1, image &src2)
{ {
return GenericMerge<MergeMode::Add>(src1, src2, 0.0f);
return generic_merge<MergeMode::Add>(src1, src2, 0.0f);
} }


Image Image::Sub(Image &src1, Image &src2)
image image::Sub(image &src1, image &src2)
{ {
return GenericMerge<MergeMode::Sub>(src1, src2, 0.0f);
return generic_merge<MergeMode::Sub>(src1, src2, 0.0f);
} }


Image Image::Difference(Image &src1, Image &src2)
image image::Difference(image &src1, image &src2)
{ {
return GenericMerge<MergeMode::Difference>(src1, src2, 0.0f);
return generic_merge<MergeMode::Difference>(src1, src2, 0.0f);
} }


} /* namespace lol */ } /* namespace lol */


+ 17
- 15
src/image/crop.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -19,20 +21,20 @@
namespace lol namespace lol
{ {


Image Image::Crop(ibox2 box) const
image image::Crop(ibox2 box) const
{ {
ivec2 const srcsize = GetSize();
ivec2 const srcsize = size();
ivec2 const dstsize = box.extent(); ivec2 const dstsize = box.extent();


Image dst(dstsize);
PixelFormat format = GetFormat();
image dst(dstsize);
PixelFormat fmt = format();


if (format != PixelFormat::Unknown)
if (fmt != PixelFormat::Unknown)
{ {
dst.SetFormat(format);
uint8_t const *srcp = (uint8_t const *)m_data->m_pixels[(int)format];
uint8_t *dstp = (uint8_t *)dst.m_data->m_pixels[(int)format];
uint8_t bpp = BytesPerPixel(format);
dst.set_format(fmt);
uint8_t const *srcp = (uint8_t const *)m_data->m_pixels[(int)fmt];
uint8_t *dstp = (uint8_t *)dst.m_data->m_pixels[(int)fmt];
uint8_t bpp = BytesPerPixel(fmt);


int len = dstsize.x; int len = dstsize.x;




+ 37
- 35
src/image/dither/dbs.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2015 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -24,44 +26,44 @@ namespace lol


/* FIXME: though the algorithm is supposed to stop, we do not have a real, /* FIXME: though the algorithm is supposed to stop, we do not have a real,
* guaranteed stop condition here. */ * guaranteed stop condition here. */
Image Image::DitherDbs() const
image image::dither_dbs() const
{ {
ivec2 size = GetSize();
ivec2 isize = size();


/* Build our human visual system kernel. */ /* Build our human visual system kernel. */
array2d<float> kernel;
kernel.resize(ivec2(NN, NN));
array2d<float> ker;
ker.resize(ivec2(NN, NN));
float t = 0.f; float t = 0.f;
for (int j = 0; j < NN; j++) for (int j = 0; j < NN; j++)
for (int i = 0; i < NN; i++) for (int i = 0; i < NN; i++)
{ {
vec2 v = vec2(i - N, j - N); vec2 v = vec2(i - N, j - N);
kernel[i][j] = exp(-sqlength(v / 1.6f) / 2.f)
+ exp(-sqlength(v / 0.6f) / 2.f);
t += kernel[i][j];
ker[i][j] = exp(-sqlength(v / 1.6f) / 2.f)
+ exp(-sqlength(v / 0.6f) / 2.f);
t += ker[i][j];
} }


for (int j = 0; j < NN; j++) for (int j = 0; j < NN; j++)
for (int i = 0; i < NN; i++) for (int i = 0; i < NN; i++)
kernel[i][j] /= t;
ker[i][j] /= t;


/* A list of cells in our picture. If no change is done to a cell /* A list of cells in our picture. If no change is done to a cell
* for two iterations, we stop considering changes to it. */ * for two iterations, we stop considering changes to it. */
ivec2 const csize = (size + ivec2(CELL - 1)) / CELL;
ivec2 const csize = (isize + ivec2(CELL - 1)) / CELL;
array2d<int> changelist(csize); array2d<int> changelist(csize);
memset(changelist.data(), 0, changelist.bytes()); memset(changelist.data(), 0, changelist.bytes());


Image dst = *this;
dst.SetFormat(PixelFormat::Y_F32);
image dst = *this;
dst.set_format(PixelFormat::Y_F32);


Image tmp1 = dst.Convolution(kernel);
array2d<float> &tmp1data = tmp1.Lock2D<PixelFormat::Y_F32>();
image tmp1 = dst.Convolution(ker);
array2d<float> &tmp1data = tmp1.lock2d<PixelFormat::Y_F32>();


dst = dst.DitherRandom();
array2d<float> &dstdata = dst.Lock2D<PixelFormat::Y_F32>();
dst = dst.dither_random();
array2d<float> &dstdata = dst.lock2d<PixelFormat::Y_F32>();


Image tmp2 = dst.Convolution(kernel);
array2d<float> &tmp2data = tmp2.Lock2D<PixelFormat::Y_F32>();
image tmp2 = dst.Convolution(ker);
array2d<float> &tmp2data = tmp2.lock2d<PixelFormat::Y_F32>();


for (int run = 0, last_change = 0; ; ++run) for (int run = 0, last_change = 0; ; ++run)
{ {
@@ -84,7 +86,7 @@ Image Image::DitherDbs() const
ivec2 const pos(cx * CELL + pixel % CELL, ivec2 const pos(cx * CELL + pixel % CELL,
cy * CELL + pixel / CELL); cy * CELL + pixel / CELL);


if (!(pos >= ivec2(0)) || !(pos < size))
if (!(pos >= ivec2(0)) || !(pos < isize))
continue; continue;


/* The best operation we can do */ /* The best operation we can do */
@@ -103,7 +105,7 @@ Image Image::DitherDbs() const


for (ivec2 const op : op_list) for (ivec2 const op : op_list)
{ {
if (!(pos + op >= ivec2(0)) || !(pos + op < size))
if (!(pos + op >= ivec2(0)) || !(pos + op < isize))
continue; continue;


bool flip = (op == ivec2(0)); bool flip = (op == ivec2(0));
@@ -115,9 +117,9 @@ Image Image::DitherDbs() const


/* TODO: implement min/max for 3+ arguments */ /* TODO: implement min/max for 3+ arguments */
int imin = max(max(-N, op.x - N), -pos.x); int imin = max(max(-N, op.x - N), -pos.x);
int imax = min(min(N + 1, op.x + NN - N), size.x - pos.x);
int imax = min(min(N + 1, op.x + NN - N), isize.x - pos.x);
int jmin = max(max(-N, op.y - N), -pos.y); int jmin = max(max(-N, op.y - N), -pos.y);
int jmax = min(min(N + 1, op.y + NN - N), size.y - pos.y);
int jmax = min(min(N + 1, op.y + NN - N), isize.y - pos.y);


float error = 0.f; float error = 0.f;
for (int j = jmin; j < jmax; j++) for (int j = jmin; j < jmax; j++)
@@ -125,9 +127,9 @@ Image Image::DitherDbs() const
{ {
ivec2 pos2 = pos + ivec2(i, j); ivec2 pos2 = pos + ivec2(i, j);


float m = kernel[i + N][j + N];
float m = ker[i + N][j + N];
if (!flip) if (!flip)
m -= kernel[i - op.x + N][j - op.y + N];
m -= ker[i - op.x + N][j - op.y + N];
float p = tmp1data[pos2]; float p = tmp1data[pos2];
float q1 = tmp2data[pos2]; float q1 = tmp2data[pos2];
float q2 = q1 + m * (d2 - d); float q2 = q1 + m * (d2 - d);
@@ -154,13 +156,13 @@ Image Image::DitherDbs() const
for (int i = -N; i <= N; i++) for (int i = -N; i <= N; i++)
{ {
ivec2 off(i, j); ivec2 off(i, j);
float delta = (d2 - d) * kernel[i + N][j + N];
float delta = (d2 - d) * ker[i + N][j + N];


if (pos + off >= ivec2(0) && pos + off < size)
if (pos + off >= ivec2(0) && pos + off < isize)
tmp2data[pos + off] += delta; tmp2data[pos + off] += delta;


if (!flip && pos + off + best_op >= ivec2(0) if (!flip && pos + off + best_op >= ivec2(0)
&& pos + off + best_op < size)
&& pos + off + best_op < isize)
tmp2data[pos + off + best_op] -= delta; tmp2data[pos + off + best_op] -= delta;
} }


@@ -173,9 +175,9 @@ Image Image::DitherDbs() const
++changelist[cx][cy]; ++changelist[cx][cy];
} }


tmp1.Unlock2D(tmp1data);
tmp2.Unlock2D(tmp2data);
dst.Unlock2D(dstdata);
tmp1.unlock2d(tmp1data);
tmp2.unlock2d(tmp2data);
dst.unlock2d(dstdata);


return dst; return dst;
} }


+ 24
- 22
src/image/dither/ediff.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -23,49 +25,49 @@ namespace lol
* Making the matrix generic is not terribly slower: the performance * Making the matrix generic is not terribly slower: the performance
* hit is around 4% for Floyd-Steinberg and 13% for JaJuNi, with the * hit is around 4% for Floyd-Steinberg and 13% for JaJuNi, with the
* benefit of a lot less code. */ * benefit of a lot less code. */
Image Image::DitherEdiff(array2d<float> const &kernel, ScanMode scan) const
image image::dither_ediff(array2d<float> const &ker, ScanMode scan) const
{ {
Image dst = *this;
image dst = *this;


ivec2 size = dst.GetSize();
ivec2 ksize = kernel.size();
ivec2 isize = dst.size();
ivec2 ksize = ker.size();


int kx; int kx;
for (kx = 0; kx < ksize.x; kx++) for (kx = 0; kx < ksize.x; kx++)
if (kernel[kx][0] > 0.f)
if (ker[kx][0] > 0.f)
break; break;


float *pixels = dst.Lock<PixelFormat::Y_F32>();
for (int y = 0; y < size.y; y++)
float *pixels = dst.lock<PixelFormat::Y_F32>();
for (int y = 0; y < isize.y; y++)
{ {
bool reverse = (y & 1) && (scan == ScanMode::Serpentine); bool reverse = (y & 1) && (scan == ScanMode::Serpentine);


for (int x = 0; x < size.x; x++)
for (int x = 0; x < isize.x; x++)
{ {
int x2 = reverse ? size.x - 1 - x : x;
int x2 = reverse ? isize.x - 1 - x : x;
int s = reverse ? -1 : 1; int s = reverse ? -1 : 1;


float p = pixels[y * size.x + x2];
float p = pixels[y * isize.x + x2];
float q = p < 0.5f ? 0.f : 1.f; float q = p < 0.5f ? 0.f : 1.f;
pixels[y * size.x + x2] = q;
pixels[y * isize.x + x2] = q;


float e = (p - q); float e = (p - q);


for (int j = 0; j < ksize.y && y < size.y - j; j++)
for (int j = 0; j < ksize.y && y < isize.y - j; j++)
for (int i = 0; i < ksize.x; i++) for (int i = 0; i < ksize.x; i++)
{ {
if (j == 0 && i <= kx) if (j == 0 && i <= kx)
continue; continue;


if (x + i - kx < 0 || x + i - kx >= size.x)
if (x + i - kx < 0 || x + i - kx >= isize.x)
continue; continue;


pixels[(y + j) * size.x + x2 + (i - kx) * s]
+= e * kernel[i][j];
pixels[(y + j) * isize.x + x2 + (i - kx) * s]
+= e * ker[i][j];
} }
} }
} }
dst.Unlock(pixels);
dst.unlock(pixels);


return dst; return dst;
} }


+ 28
- 26
src/image/dither/ordered.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -17,51 +19,51 @@
namespace lol namespace lol
{ {


static Image DitherHelper(Image const &image, array2d<float> const &kernel,
float scale, float angle);
static image dither_helper(image const &img, array2d<float> const &ker,
float scale, float angle);


Image Image::DitherOrdered(array2d<float> const &kernel) const
image image::dither_ordered(array2d<float> const &ker) const
{ {
return DitherHelper(*this, kernel, 1.0f, 0.0f);
return dither_helper(*this, ker, 1.0f, 0.0f);
} }


Image Image::DitherHalftone(float radius, float angle) const
image image::dither_halftone(float radius, float angle) const
{ {
/* Increasing the precision is necessary or the rotation will look /* Increasing the precision is necessary or the rotation will look
* like crap. So we create a kernel PRECISION times larger, and ask * like crap. So we create a kernel PRECISION times larger, and ask
* the ditherer to scale it by 1/PRECISION. */ * the ditherer to scale it by 1/PRECISION. */
float const PRECISION = 4.f; float const PRECISION = 4.f;
int k = (radius * PRECISION * lol::sqrt(2.f) + 0.5f); int k = (radius * PRECISION * lol::sqrt(2.f) + 0.5f);
array2d<float> kernel = Image::HalftoneKernel(ivec2(k, k));
array2d<float> ker = image::kernel::halftone(ivec2(k, k));


return DitherHelper(*this, kernel, 1.f / PRECISION, angle + F_PI / 4.f);
return dither_helper(*this, ker, 1.f / PRECISION, angle + F_PI / 4.f);
} }


static Image DitherHelper(Image const &image, array2d<float> const &kernel,
float scale, float angle)
static image dither_helper(image const &img, array2d<float> const &ker,
float scale, float angle)
{ {
ivec2 size = image.GetSize();
ivec2 ksize = kernel.size();
ivec2 isize = img.size();
ivec2 ksize = ker.size();


float cost = lol::cos(angle); float cost = lol::cos(angle);
float sint = lol::sin(angle); float sint = lol::sin(angle);


Image ret = image;
float *dstp = ret.Lock<PixelFormat::Y_F32>();
image ret = img;
float *dstp = ret.lock<PixelFormat::Y_F32>();


for (int y = 0; y < size.y; y++)
for (int y = 0; y < isize.y; y++)
{ {
for (int x = 0; x < size.x; x++)
for (int x = 0; x < isize.x; x++)
{ {
int kx = (int)((cost * x - sint * y + 2 * size.x * size.y) / scale) % ksize.x;
int ky = (int)((cost * y + sint * x + 2 * size.x * size.y) / scale) % ksize.y;
int kx = (int)((cost * x - sint * y + 2 * isize.x * isize.y) / scale) % ksize.x;
int ky = (int)((cost * y + sint * x + 2 * isize.x * isize.y) / scale) % ksize.y;


float p = dstp[y * size.x + x];
dstp[y * size.x + x] = (p > kernel[kx][ky]) ? 1.f : 0.f;
float p = dstp[y * isize.x + x];
dstp[y * isize.x + x] = (p > ker[kx][ky]) ? 1.f : 0.f;
} }
} }


ret.Unlock(dstp);
ret.unlock(dstp);


return ret; return ret;
} }


+ 14
- 12
src/image/dither/ostromoukhov.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -69,13 +71,13 @@ static inline vec3 GetDiffusion(float v)
return ret; return ret;
} }


Image Image::DitherOstromoukhov(ScanMode scan) const
image image::dither_ostromoukhov(ScanMode scan) const
{ {
Image dst = *this;
image dst = *this;


float *pixels = dst.Lock<PixelFormat::Y_F32>();
int w = dst.GetSize().x;
int h = dst.GetSize().y;
float *pixels = dst.lock<PixelFormat::Y_F32>();
int w = dst.size().x;
int h = dst.size().y;


for (int y = 0; y < h; y++) for (int y = 0; y < h; y++)
{ {
@@ -103,7 +105,7 @@ Image Image::DitherOstromoukhov(ScanMode scan) const
} }
} }


dst.Unlock(pixels);
dst.unlock(pixels);


return dst; return dst;
} }


+ 13
- 11
src/image/dither/random.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -17,19 +19,19 @@
namespace lol namespace lol
{ {


Image Image::DitherRandom() const
image image::dither_random() const
{ {
Image dst = *this;
image dst = *this;


float *pixels = dst.Lock<PixelFormat::Y_F32>();
int count = GetSize().x * GetSize().y;
float *pixels = dst.lock<PixelFormat::Y_F32>();
int count = size().x * size().y;


for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
{ {
pixels[n] = (pixels[n] > lol::rand(0.5f)) ? 1.f : 0.f; pixels[n] = (pixels[n] > lol::rand(0.5f)) ? 1.f : 0.f;
} }


dst.Unlock(pixels);
dst.unlock(pixels);


return dst; return dst;
} }


+ 50
- 48
src/image/filter/colors.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -17,34 +19,34 @@
namespace lol namespace lol
{ {


Image Image::Brightness(float val) const
image image::Brightness(float val) const
{ {
Image ret = *this;
int count = GetSize().x * GetSize().y;
image ret = *this;
int count = size().x * size().y;


if (GetFormat() == PixelFormat::Y_8 || GetFormat() == PixelFormat::Y_F32)
if (format() == PixelFormat::Y_8 || format() == PixelFormat::Y_F32)
{ {
float *pixels = ret.Lock<PixelFormat::Y_F32>();
float *pixels = ret.lock<PixelFormat::Y_F32>();
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
pixels[n] = lol::clamp(pixels[n] + val, 0.f, 1.f); pixels[n] = lol::clamp(pixels[n] + val, 0.f, 1.f);
ret.Unlock(pixels);
ret.unlock(pixels);
} }
else else
{ {
vec4 *pixels = ret.Lock<PixelFormat::RGBA_F32>();
vec4 *pixels = ret.lock<PixelFormat::RGBA_F32>();
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
pixels[n] = vec4(lol::clamp(pixels[n].rgb + vec3(val), 0.f, 1.f), pixels[n] = vec4(lol::clamp(pixels[n].rgb + vec3(val), 0.f, 1.f),
pixels[n].a); pixels[n].a);
ret.Unlock(pixels);
ret.unlock(pixels);
} }


return ret; return ret;
} }


Image Image::Contrast(float val) const
image image::Contrast(float val) const
{ {
Image ret = *this;
int count = GetSize().x * GetSize().y;
image ret = *this;
int count = size().x * size().y;


if (val >= 0.f) if (val >= 0.f)
{ {
@@ -58,22 +60,22 @@ Image Image::Contrast(float val) const
val = lol::clamp(1.f + val, 0.f, 1.f); val = lol::clamp(1.f + val, 0.f, 1.f);
} }


if (GetFormat() == PixelFormat::Y_8 || GetFormat() == PixelFormat::Y_F32)
if (format() == PixelFormat::Y_8 || format() == PixelFormat::Y_F32)
{ {
float add = -0.5f * val + 0.5f; float add = -0.5f * val + 0.5f;
float *pixels = ret.Lock<PixelFormat::Y_F32>();
float *pixels = ret.lock<PixelFormat::Y_F32>();
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
pixels[n] = lol::clamp(pixels[n] * val + add, 0.f, 1.f); pixels[n] = lol::clamp(pixels[n] * val + add, 0.f, 1.f);
ret.Unlock(pixels);
ret.unlock(pixels);
} }
else else
{ {
vec3 add = vec3(-0.5f * val + 0.5f); vec3 add = vec3(-0.5f * val + 0.5f);
vec4 *pixels = ret.Lock<PixelFormat::RGBA_F32>();
vec4 *pixels = ret.lock<PixelFormat::RGBA_F32>();
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
pixels[n] = vec4(lol::clamp(pixels[n].rgb * val + add, 0.f, 1.f), pixels[n] = vec4(lol::clamp(pixels[n].rgb * val + add, 0.f, 1.f),
pixels[n].a); pixels[n].a);
ret.Unlock(pixels);
ret.unlock(pixels);
} }


return ret; return ret;
@@ -83,16 +85,16 @@ Image Image::Contrast(float val) const
* TODO: the current approach is naive; we should use the histogram in order * TODO: the current approach is naive; we should use the histogram in order
* to decide how to change the contrast. * to decide how to change the contrast.
*/ */
Image Image::AutoContrast() const
image image::AutoContrast() const
{ {
Image ret = *this;
image ret = *this;


float min_val = 1.f, max_val = 0.f; float min_val = 1.f, max_val = 0.f;
int count = GetSize().x * GetSize().y;
int count = size().x * size().y;


if (GetFormat() == PixelFormat::Y_8 || GetFormat() == PixelFormat::Y_F32)
if (format() == PixelFormat::Y_8 || format() == PixelFormat::Y_F32)
{ {
float *pixels = ret.Lock<PixelFormat::Y_F32>();
float *pixels = ret.lock<PixelFormat::Y_F32>();
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
{ {
min_val = lol::min(min_val, pixels[n]); min_val = lol::min(min_val, pixels[n]);
@@ -103,11 +105,11 @@ Image Image::AutoContrast() const
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
pixels[n] = (pixels[n] - min_val) * t; pixels[n] = (pixels[n] - min_val) * t;


ret.Unlock(pixels);
ret.unlock(pixels);
} }
else else
{ {
vec4 *pixels = ret.Lock<PixelFormat::RGBA_F32>();
vec4 *pixels = ret.lock<PixelFormat::RGBA_F32>();
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
{ {
min_val = lol::min(min_val, pixels[n].r); min_val = lol::min(min_val, pixels[n].r);
@@ -125,60 +127,60 @@ Image Image::AutoContrast() const
(pixels[n].b - min_val) * t, (pixels[n].b - min_val) * t,
pixels[n].a);; pixels[n].a);;


ret.Unlock(pixels);
ret.unlock(pixels);
} }


return ret; return ret;
} }


Image Image::Invert() const
image image::Invert() const
{ {
Image ret = *this;
int count = GetSize().x * GetSize().y;
image ret = *this;
int count = size().x * size().y;


if (GetFormat() == PixelFormat::Y_8 || GetFormat() == PixelFormat::Y_F32)
if (format() == PixelFormat::Y_8 || format() == PixelFormat::Y_F32)
{ {
float *pixels = ret.Lock<PixelFormat::Y_F32>();
float *pixels = ret.lock<PixelFormat::Y_F32>();
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
pixels[n] = 1.f - pixels[n]; pixels[n] = 1.f - pixels[n];
ret.Unlock(pixels);
ret.unlock(pixels);
} }
else else
{ {
vec4 *pixels = ret.Lock<PixelFormat::RGBA_F32>();
vec4 *pixels = ret.lock<PixelFormat::RGBA_F32>();
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
pixels[n] = vec4(vec3(1.f) -pixels[n].rgb, pixels[n].a); pixels[n] = vec4(vec3(1.f) -pixels[n].rgb, pixels[n].a);
ret.Unlock(pixels);
ret.unlock(pixels);
} }


return ret; return ret;
} }


Image Image::Threshold(float val) const
image image::Threshold(float val) const
{ {
Image ret = *this;
int count = GetSize().x * GetSize().y;
image ret = *this;
int count = size().x * size().y;


float *pixels = ret.Lock<PixelFormat::Y_F32>();
float *pixels = ret.lock<PixelFormat::Y_F32>();
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
pixels[n] = pixels[n] > val ? 1.f : 0.f; pixels[n] = pixels[n] > val ? 1.f : 0.f;
ret.Unlock(pixels);
ret.unlock(pixels);


return ret; return ret;
} }


Image Image::Threshold(vec3 val) const
image image::Threshold(vec3 val) const
{ {
Image ret = *this;
int count = GetSize().x * GetSize().y;
image ret = *this;
int count = size().x * size().y;


vec4 *pixels = ret.Lock<PixelFormat::RGBA_F32>();
vec4 *pixels = ret.lock<PixelFormat::RGBA_F32>();
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
pixels[n] = vec4(pixels[n].r > val.r ? 1.f : 0.f, pixels[n] = vec4(pixels[n].r > val.r ? 1.f : 0.f,
pixels[n].g > val.g ? 1.f : 0.f, pixels[n].g > val.g ? 1.f : 0.f,
pixels[n].b > val.b ? 1.f : 0.f, pixels[n].b > val.b ? 1.f : 0.f,
pixels[n].a); pixels[n].a);
ret.Unlock(pixels);
ret.unlock(pixels);


return ret; return ret;
} }


+ 53
- 51
src/image/filter/convolution.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -17,21 +19,21 @@
namespace lol namespace lol
{ {


static Image SepConv(Image &src, array<float> const &hvec,
static image SepConv(image &src, array<float> const &hvec,
array<float> const &vvec); array<float> const &vvec);
static Image NonSepConv(Image &src, array2d<float> const &kernel);
static image NonSepConv(image &src, array2d<float> const &in_kernel);


Image Image::Convolution(array2d<float> const &kernel)
image image::Convolution(array2d<float> const &in_kernel)
{ {
/* Find the cell with the largest value */ /* Find the cell with the largest value */
ivec2 ksize = kernel.size();
ivec2 ksize = in_kernel.size();
int bestx = -1, besty = -1; int bestx = -1, besty = -1;
float tmp = 0.f; float tmp = 0.f;
for (int dy = 0; dy < ksize.y; ++dy) for (int dy = 0; dy < ksize.y; ++dy)
for (int dx = 0; dx < ksize.x; ++dx) for (int dx = 0; dx < ksize.x; ++dx)
if (lol::sq(kernel[dx][dy]) > tmp)
if (lol::sq(in_kernel[dx][dy]) > tmp)
{ {
tmp = sq(kernel[dx][dy]);
tmp = sq(in_kernel[dx][dy]);
bestx = dx; bestx = dx;
besty = dy; besty = dy;
} }
@@ -52,8 +54,8 @@ Image Image::Convolution(array2d<float> const &kernel)
if (dx == bestx) if (dx == bestx)
continue; continue;


float p = kernel[dx][dy] * kernel[bestx][besty];
float q = kernel[dx][besty] * kernel[bestx][dy];
float p = in_kernel[dx][dy] * in_kernel[bestx][besty];
float q = in_kernel[dx][besty] * in_kernel[bestx][dy];


if (lol::abs(p - q) > 1.0e-8f) if (lol::abs(p - q) > 1.0e-8f)
separable = false; separable = false;
@@ -65,29 +67,29 @@ Image Image::Convolution(array2d<float> const &kernel)
/* Matrix rank is 1! Separate the filter. */ /* Matrix rank is 1! Separate the filter. */
array<float> hvec, vvec; array<float> hvec, vvec;


float norm = 1.0f / lol::sqrt(lol::abs(kernel[bestx][besty]));
float norm = 1.0f / lol::sqrt(lol::abs(in_kernel[bestx][besty]));
for (int dx = 0; dx < ksize.x; dx++) for (int dx = 0; dx < ksize.x; dx++)
hvec << norm * kernel[dx][besty];
hvec << norm * in_kernel[dx][besty];
for (int dy = 0; dy < ksize.y; dy++) for (int dy = 0; dy < ksize.y; dy++)
vvec << norm * kernel[bestx][dy];
vvec << norm * in_kernel[bestx][dy];


return SepConv(*this, hvec, vvec); return SepConv(*this, hvec, vvec);
} }
else else
{ {
return NonSepConv(*this, kernel);
return NonSepConv(*this, in_kernel);
} }
} }


Image Image::Sharpen(array2d<float> const &kernel)
image image::Sharpen(array2d<float> const &in_kernel)
{ {
ivec2 ksize = kernel.size();
ivec2 ksize = in_kernel.size();
array2d<float> newkernel(ksize); array2d<float> newkernel(ksize);


for (int dy = 0; dy < ksize.y; ++dy) for (int dy = 0; dy < ksize.y; ++dy)
for (int dx = 0; dx < ksize.x; ++dx) for (int dx = 0; dx < ksize.x; ++dx)
{ {
newkernel[dx][dy] = - kernel[dx][dy];
newkernel[dx][dy] = - in_kernel[dx][dy];
if (dx == ksize.x / 2 && dy == ksize.y / 2) if (dx == ksize.x / 2 && dy == ksize.y / 2)
newkernel[dx][dy] += 2.f; newkernel[dx][dy] += 2.f;
} }
@@ -96,16 +98,16 @@ Image Image::Sharpen(array2d<float> const &kernel)
} }


template<PixelFormat FORMAT, int WRAP_X, int WRAP_Y> template<PixelFormat FORMAT, int WRAP_X, int WRAP_Y>
static Image NonSepConv(Image &src, array2d<float> const &kernel)
static image NonSepConv(image &src, array2d<float> const &in_kernel)
{ {
typedef typename PixelType<FORMAT>::type pixel_t; typedef typename PixelType<FORMAT>::type pixel_t;


ivec2 const size = src.GetSize();
ivec2 const ksize = kernel.size();
Image dst(size);
ivec2 const size = src.size();
ivec2 const ksize = in_kernel.size();
image dst(size);


array2d<pixel_t> const &srcp = src.Lock2D<FORMAT>();
array2d<pixel_t> &dstp = dst.Lock2D<FORMAT>();
array2d<pixel_t> const &srcp = src.lock2d<FORMAT>();
array2d<pixel_t> &dstp = dst.lock2d<FORMAT>();


for (int y = 0; y < size.y; y++) for (int y = 0; y < size.y; y++)
{ {
@@ -123,7 +125,7 @@ static Image NonSepConv(Image &src, array2d<float> const &kernel)


for (int dx = 0; dx < ksize.x; dx++) for (int dx = 0; dx < ksize.x; dx++)
{ {
float f = kernel[dx][dy];
float f = in_kernel[dx][dy];


int x2 = x + dx - ksize.x / 2; int x2 = x + dx - ksize.x / 2;
if (x2 < 0) if (x2 < 0)
@@ -139,33 +141,33 @@ static Image NonSepConv(Image &src, array2d<float> const &kernel)
} }
} }


src.Unlock2D(srcp);
dst.Unlock2D(dstp);
src.unlock2d(srcp);
dst.unlock2d(dstp);


return dst; return dst;
} }


static Image NonSepConv(Image &src, array2d<float> const &kernel)
static image NonSepConv(image &src, array2d<float> const &in_kernel)
{ {
bool const wrap_x = src.GetWrapX() == WrapMode::Repeat; bool const wrap_x = src.GetWrapX() == WrapMode::Repeat;
bool const wrap_y = src.GetWrapY() == WrapMode::Repeat; bool const wrap_y = src.GetWrapY() == WrapMode::Repeat;


if (src.GetFormat() == PixelFormat::Y_8
|| src.GetFormat() == PixelFormat::Y_F32)
if (src.format() == PixelFormat::Y_8
|| src.format() == PixelFormat::Y_F32)
{ {
if (wrap_x) if (wrap_x)
{ {
if (wrap_y) if (wrap_y)
return NonSepConv<PixelFormat::Y_F32, 1, 1>(src, kernel);
return NonSepConv<PixelFormat::Y_F32, 1, 1>(src, in_kernel);
else else
return NonSepConv<PixelFormat::Y_F32, 1, 0>(src, kernel);
return NonSepConv<PixelFormat::Y_F32, 1, 0>(src, in_kernel);
} }
else else
{ {
if (wrap_y) if (wrap_y)
return NonSepConv<PixelFormat::Y_F32, 0, 1>(src, kernel);
return NonSepConv<PixelFormat::Y_F32, 0, 1>(src, in_kernel);
else else
return NonSepConv<PixelFormat::Y_F32, 0, 0>(src, kernel);
return NonSepConv<PixelFormat::Y_F32, 0, 0>(src, in_kernel);
} }
} }
else else
@@ -173,32 +175,32 @@ static Image NonSepConv(Image &src, array2d<float> const &kernel)
if (wrap_x) if (wrap_x)
{ {
if (wrap_y) if (wrap_y)
return NonSepConv<PixelFormat::RGBA_F32, 1, 1>(src, kernel);
return NonSepConv<PixelFormat::RGBA_F32, 1, 1>(src, in_kernel);
else else
return NonSepConv<PixelFormat::RGBA_F32, 1, 0>(src, kernel);
return NonSepConv<PixelFormat::RGBA_F32, 1, 0>(src, in_kernel);
} }
else else
{ {
if (wrap_y) if (wrap_y)
return NonSepConv<PixelFormat::RGBA_F32, 0, 1>(src, kernel);
return NonSepConv<PixelFormat::RGBA_F32, 0, 1>(src, in_kernel);
else else
return NonSepConv<PixelFormat::RGBA_F32, 0, 0>(src, kernel);
return NonSepConv<PixelFormat::RGBA_F32, 0, 0>(src, in_kernel);
} }
} }
} }


template<PixelFormat FORMAT, int WRAP_X, int WRAP_Y> template<PixelFormat FORMAT, int WRAP_X, int WRAP_Y>
static Image SepConv(Image &src, array<float> const &hvec,
static image SepConv(image &src, array<float> const &hvec,
array<float> const &vvec) array<float> const &vvec)
{ {
typedef typename PixelType<FORMAT>::type pixel_t; typedef typename PixelType<FORMAT>::type pixel_t;


ivec2 const size = src.GetSize();
ivec2 const size = src.size();
ivec2 const ksize(hvec.count(), vvec.count()); ivec2 const ksize(hvec.count(), vvec.count());
Image dst(size);
image dst(size);


array2d<pixel_t> const &srcp = src.Lock2D<FORMAT>();
array2d<pixel_t> &dstp = dst.Lock2D<FORMAT>();
array2d<pixel_t> const &srcp = src.lock2d<FORMAT>();
array2d<pixel_t> &dstp = dst.lock2d<FORMAT>();


array2d<pixel_t> tmp(size); array2d<pixel_t> tmp(size);


@@ -244,20 +246,20 @@ static Image SepConv(Image &src, array<float> const &hvec,
} }
} }


src.Unlock2D(srcp);
dst.Unlock2D(dstp);
src.unlock2d(srcp);
dst.unlock2d(dstp);


return dst; return dst;
} }


static Image SepConv(Image &src, array<float> const &hvec,
static image SepConv(image &src, array<float> const &hvec,
array<float> const &vvec) array<float> const &vvec)
{ {
bool const wrap_x = src.GetWrapX() == WrapMode::Repeat; bool const wrap_x = src.GetWrapX() == WrapMode::Repeat;
bool const wrap_y = src.GetWrapY() == WrapMode::Repeat; bool const wrap_y = src.GetWrapY() == WrapMode::Repeat;


if (src.GetFormat() == PixelFormat::Y_8
|| src.GetFormat() == PixelFormat::Y_F32)
if (src.format() == PixelFormat::Y_8
|| src.format() == PixelFormat::Y_F32)
{ {
if (wrap_x) if (wrap_x)
{ {


+ 76
- 74
src/image/filter/dilate.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -22,115 +24,115 @@
namespace lol namespace lol
{ {


Image Image::Dilate()
image image::Dilate()
{ {
ivec2 const size = GetSize();
Image ret(size);
ivec2 isize = size();
image ret(isize);


if (GetFormat() == PixelFormat::Y_8 || GetFormat() == PixelFormat::Y_F32)
if (format() == PixelFormat::Y_8 || format() == PixelFormat::Y_F32)
{ {
float const *srcp = Lock<PixelFormat::Y_F32>();
float *dstp = ret.Lock<PixelFormat::Y_F32>();
float const *srcp = lock<PixelFormat::Y_F32>();
float *dstp = ret.lock<PixelFormat::Y_F32>();


for (int y = 0; y < size.y; ++y)
for (int x = 0; x < size.x; ++x)
for (int y = 0; y < isize.y; ++y)
for (int x = 0; x < isize.x; ++x)
{ {
int y2 = lol::max(y - 1, 0); int y2 = lol::max(y - 1, 0);
int x2 = lol::max(x - 1, 0); int x2 = lol::max(x - 1, 0);
int y3 = lol::min(y + 1, size.y - 1);
int x3 = lol::min(x + 1, size.x - 1);
float t = srcp[y * size.x + x];
t = lol::max(t, srcp[y * size.x + x2]);
t = lol::max(t, srcp[y * size.x + x3]);
t = lol::max(t, srcp[y2 * size.x + x]);
t = lol::max(t, srcp[y3 * size.x + x]);
dstp[y * size.x + x] = t;
int y3 = lol::min(y + 1, isize.y - 1);
int x3 = lol::min(x + 1, isize.x - 1);
float t = srcp[y * isize.x + x];
t = lol::max(t, srcp[y * isize.x + x2]);
t = lol::max(t, srcp[y * isize.x + x3]);
t = lol::max(t, srcp[y2 * isize.x + x]);
t = lol::max(t, srcp[y3 * isize.x + x]);
dstp[y * isize.x + x] = t;
} }


Unlock(srcp);
ret.Unlock(dstp);
unlock(srcp);
ret.unlock(dstp);
} }
else else
{ {
vec4 const *srcp = Lock<PixelFormat::RGBA_F32>();
vec4 *dstp = ret.Lock<PixelFormat::RGBA_F32>();
vec4 const *srcp = lock<PixelFormat::RGBA_F32>();
vec4 *dstp = ret.lock<PixelFormat::RGBA_F32>();


for (int y = 0; y < size.y; ++y)
for (int x = 0; x < size.x; ++x)
for (int y = 0; y < isize.y; ++y)
for (int x = 0; x < isize.x; ++x)
{ {
int y2 = lol::max(y - 1, 0); int y2 = lol::max(y - 1, 0);
int x2 = lol::max(x - 1, 0); int x2 = lol::max(x - 1, 0);
int y3 = lol::min(y + 1, size.y - 1);
int x3 = lol::min(x + 1, size.x - 1);
vec3 t = srcp[y * size.x + x].rgb;
t = lol::max(t, srcp[y * size.x + x2].rgb);
t = lol::max(t, srcp[y * size.x + x3].rgb);
t = lol::max(t, srcp[y2 * size.x + x].rgb);
t = lol::max(t, srcp[y3 * size.x + x].rgb);
dstp[y * size.x + x] = vec4(t, srcp[y * size.x + x].a);
int y3 = lol::min(y + 1, isize.y - 1);
int x3 = lol::min(x + 1, isize.x - 1);
vec3 t = srcp[y * isize.x + x].rgb;
t = lol::max(t, srcp[y * isize.x + x2].rgb);
t = lol::max(t, srcp[y * isize.x + x3].rgb);
t = lol::max(t, srcp[y2 * isize.x + x].rgb);
t = lol::max(t, srcp[y3 * isize.x + x].rgb);
dstp[y * isize.x + x] = vec4(t, srcp[y * isize.x + x].a);
} }


Unlock(srcp);
ret.Unlock(dstp);
unlock(srcp);
ret.unlock(dstp);
} }


return ret; return ret;
} }


Image Image::Erode()
image image::Erode()
{ {
ivec2 const size = GetSize();
Image ret(size);
ivec2 isize = size();
image ret(isize);


if (GetFormat() == PixelFormat::Y_8 || GetFormat() == PixelFormat::Y_F32)
if (format() == PixelFormat::Y_8 || format() == PixelFormat::Y_F32)
{ {
float const *srcp = Lock<PixelFormat::Y_F32>();
float *dstp = ret.Lock<PixelFormat::Y_F32>();
float const *srcp = lock<PixelFormat::Y_F32>();
float *dstp = ret.lock<PixelFormat::Y_F32>();


for (int y = 0; y < size.y; ++y)
for (int x = 0; x < size.x; ++x)
for (int y = 0; y < isize.y; ++y)
for (int x = 0; x < isize.x; ++x)
{ {
int y2 = lol::max(y - 1, 0); int y2 = lol::max(y - 1, 0);
int x2 = lol::max(x - 1, 0); int x2 = lol::max(x - 1, 0);
int y3 = lol::min(y + 1, size.y - 1);
int x3 = lol::min(x + 1, size.x - 1);
float t = srcp[y * size.x + x];
t = lol::max(t, srcp[y * size.x + x2]);
t = lol::max(t, srcp[y * size.x + x3]);
t = lol::max(t, srcp[y2 * size.x + x]);
t = lol::max(t, srcp[y3 * size.x + x]);
dstp[y * size.x + x] = t;
int y3 = lol::min(y + 1, isize.y - 1);
int x3 = lol::min(x + 1, isize.x - 1);
float t = srcp[y * isize.x + x];
t = lol::max(t, srcp[y * isize.x + x2]);
t = lol::max(t, srcp[y * isize.x + x3]);
t = lol::max(t, srcp[y2 * isize.x + x]);
t = lol::max(t, srcp[y3 * isize.x + x]);
dstp[y * isize.x + x] = t;
} }


Unlock(srcp);
ret.Unlock(dstp);
unlock(srcp);
ret.unlock(dstp);
} }
else else
{ {
vec4 const *srcp = Lock<PixelFormat::RGBA_F32>();
vec4 *dstp = ret.Lock<PixelFormat::RGBA_F32>();
vec4 const *srcp = lock<PixelFormat::RGBA_F32>();
vec4 *dstp = ret.lock<PixelFormat::RGBA_F32>();


for (int y = 0; y < size.y; ++y)
for (int x = 0; x < size.x; ++x)
for (int y = 0; y < isize.y; ++y)
for (int x = 0; x < isize.x; ++x)
{ {
int y2 = lol::max(y - 1, 0); int y2 = lol::max(y - 1, 0);
int x2 = lol::max(x - 1, 0); int x2 = lol::max(x - 1, 0);
int y3 = lol::min(y + 1, size.y - 1);
int x3 = lol::min(x + 1, size.x - 1);
vec3 t = srcp[y * size.x + x].rgb;
t = lol::min(t, srcp[y * size.x + x2].rgb);
t = lol::min(t, srcp[y * size.x + x3].rgb);
t = lol::min(t, srcp[y2 * size.x + x].rgb);
t = lol::min(t, srcp[y3 * size.x + x].rgb);
dstp[y * size.x + x] = vec4(t, srcp[y * size.x + x].a);
int y3 = lol::min(y + 1, isize.y - 1);
int x3 = lol::min(x + 1, isize.x - 1);
vec3 t = srcp[y * isize.x + x].rgb;
t = lol::min(t, srcp[y * isize.x + x2].rgb);
t = lol::min(t, srcp[y * isize.x + x3].rgb);
t = lol::min(t, srcp[y2 * isize.x + x].rgb);
t = lol::min(t, srcp[y3 * isize.x + x].rgb);
dstp[y * isize.x + x] = vec4(t, srcp[y * isize.x + x].a);
} }


Unlock(srcp);
ret.Unlock(dstp);
unlock(srcp);
ret.unlock(dstp);
} }


return ret; return ret;


+ 54
- 52
src/image/filter/median.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -33,38 +35,38 @@ static int cmpfloat(void const *i1, void const *i2)
return (a > b) - (a < b); return (a > b) - (a < b);
} }


Image Image::Median(ivec2 ksize) const
image image::Median(ivec2 ksize) const
{ {
ivec2 const size = GetSize();
Image tmp = *this;
Image ret(size);
ivec2 const isize = size();
image tmp = *this;
image ret(isize);


if (GetFormat() == PixelFormat::Y_8 || GetFormat() == PixelFormat::Y_F32)
if (format() == PixelFormat::Y_8 || format() == PixelFormat::Y_F32)
{ {
ivec2 const lsize = 2 * ksize + ivec2(1); ivec2 const lsize = 2 * ksize + ivec2(1);
array2d<float> list(lsize); array2d<float> list(lsize);


float *srcp = tmp.Lock<PixelFormat::Y_F32>();
float *dstp = ret.Lock<PixelFormat::Y_F32>();
float *srcp = tmp.lock<PixelFormat::Y_F32>();
float *dstp = ret.lock<PixelFormat::Y_F32>();


for (int y = 0; y < size.y; y++)
for (int y = 0; y < isize.y; y++)
{ {
for (int x = 0; x < size.x; x++)
for (int x = 0; x < isize.x; x++)
{ {
/* Make a list of neighbours */ /* Make a list of neighbours */
for (int j = -ksize.y; j <= ksize.y; j++) for (int j = -ksize.y; j <= ksize.y; j++)
{ {
int y2 = y + j; int y2 = y + j;
if (y2 < 0) y2 = size.y - 1 - ((-y2 - 1) % size.y);
else if (y2 > 0) y2 = y2 % size.y;
if (y2 < 0) y2 = isize.y - 1 - ((-y2 - 1) % isize.y);
else if (y2 > 0) y2 = y2 % isize.y;


for (int i = -ksize.x; i <= ksize.x; i++) for (int i = -ksize.x; i <= ksize.x; i++)
{ {
int x2 = x + i; int x2 = x + i;
if (x2 < 0) x2 = size.x - 1 - ((-x2 - 1) % size.x);
else if (x2 > 0) x2 = x2 % size.x;
if (x2 < 0) x2 = isize.x - 1 - ((-x2 - 1) % isize.x);
else if (x2 > 0) x2 = x2 % isize.x;


list[i + ksize.x][j + ksize.y] = srcp[y2 * size.x + x2];
list[i + ksize.x][j + ksize.y] = srcp[y2 * isize.x + x2];
} }
} }


@@ -72,39 +74,39 @@ Image Image::Median(ivec2 ksize) const
qsort(&list[0][0], lsize.x * lsize.y, sizeof(float), cmpfloat); qsort(&list[0][0], lsize.x * lsize.y, sizeof(float), cmpfloat);


/* Store the median value */ /* Store the median value */
dstp[y * size.x + x] = *(&list[0][0] + lsize.x * lsize.y / 2);
dstp[y * isize.x + x] = *(&list[0][0] + lsize.x * lsize.y / 2);
} }
} }


tmp.Unlock(srcp);
ret.Unlock(dstp);
tmp.unlock(srcp);
ret.unlock(dstp);
} }
else else
{ {
ivec2 const lsize = 2 * ksize + ivec2(1); ivec2 const lsize = 2 * ksize + ivec2(1);
array2d<vec3> list(lsize); array2d<vec3> list(lsize);


vec4 *srcp = tmp.Lock<PixelFormat::RGBA_F32>();
vec4 *dstp = ret.Lock<PixelFormat::RGBA_F32>();
vec4 *srcp = tmp.lock<PixelFormat::RGBA_F32>();
vec4 *dstp = ret.lock<PixelFormat::RGBA_F32>();


for (int y = 0; y < size.y; y++)
for (int y = 0; y < isize.y; y++)
{ {
for (int x = 0; x < size.x; x++)
for (int x = 0; x < isize.x; x++)
{ {
/* Make a list of neighbours */ /* Make a list of neighbours */
for (int j = -ksize.y; j <= ksize.y; j++) for (int j = -ksize.y; j <= ksize.y; j++)
{ {
int y2 = y + j; int y2 = y + j;
if (y2 < 0) y2 = size.y - 1 - ((-y2 - 1) % size.y);
else if (y2 > 0) y2 = y2 % size.y;
if (y2 < 0) y2 = isize.y - 1 - ((-y2 - 1) % isize.y);
else if (y2 > 0) y2 = y2 % isize.y;


for (int i = -ksize.x; i <= ksize.x; i++) for (int i = -ksize.x; i <= ksize.x; i++)
{ {
int x2 = x + i; int x2 = x + i;
if (x2 < 0) x2 = size.x - 1 - ((-x2 - 1) % size.x);
else if (x2 > 0) x2 = x2 % size.x;
if (x2 < 0) x2 = isize.x - 1 - ((-x2 - 1) % isize.x);
else if (x2 > 0) x2 = x2 % isize.x;


list[i + ksize.x][j + ksize.y] = srcp[y2 * size.x + x2].rgb;
list[i + ksize.x][j + ksize.y] = srcp[y2 * isize.x + x2].rgb;
} }
} }


@@ -139,26 +141,26 @@ Image Image::Median(ivec2 ksize) const
} }


/* Store the median value */ /* Store the median value */
dstp[y * size.x + x] = vec4(median, srcp[y * size.x + x].a);
dstp[y * isize.x + x] = vec4(median, srcp[y * isize.x + x].a);
} }
} }


tmp.Unlock(srcp);
ret.Unlock(dstp);
tmp.unlock(srcp);
ret.unlock(dstp);
} }


return ret; return ret;
} }


Image Image::Median(array2d<float> const &kernel) const
image image::Median(array2d<float> const &kernel) const
{ {
ivec2 const size = GetSize();
Image tmp = *this;
Image ret(size);
ivec2 const isize = size();
image tmp = *this;
image ret(isize);


/* FIXME: TODO */ /* FIXME: TODO */
#if 0 #if 0
if (GetFormat() == PixelFormat::Y_8 || GetFormat() == PixelFormat::Y_F32)
if (format() == PixelFormat::Y_8 || format() == PixelFormat::Y_F32)
{ {
} }
else else
@@ -167,27 +169,27 @@ Image Image::Median(array2d<float> const &kernel) const
ivec2 const ksize = kernel.size(); ivec2 const ksize = kernel.size();
array2d<vec3> list(ksize); array2d<vec3> list(ksize);


vec4 *srcp = tmp.Lock<PixelFormat::RGBA_F32>();
vec4 *dstp = ret.Lock<PixelFormat::RGBA_F32>();
vec4 *srcp = tmp.lock<PixelFormat::RGBA_F32>();
vec4 *dstp = ret.lock<PixelFormat::RGBA_F32>();


for (int y = 0; y < size.y; y++)
for (int y = 0; y < isize.y; y++)
{ {
for (int x = 0; x < size.x; x++)
for (int x = 0; x < isize.x; x++)
{ {
/* Make a list of neighbours */ /* Make a list of neighbours */
for (int j = 0; j < ksize.y; j++) for (int j = 0; j < ksize.y; j++)
{ {
int y2 = y + j - ksize.y / 2; int y2 = y + j - ksize.y / 2;
if (y2 < 0) y2 = size.y - 1 - ((-y2 - 1) % size.y);
else if (y2 > 0) y2 = y2 % size.y;
if (y2 < 0) y2 = isize.y - 1 - ((-y2 - 1) % isize.y);
else if (y2 > 0) y2 = y2 % isize.y;


for (int i = 0; i < ksize.x; i++) for (int i = 0; i < ksize.x; i++)
{ {
int x2 = x + i - ksize.x / 2; int x2 = x + i - ksize.x / 2;
if (x2 < 0) x2 = size.x - 1 - ((-x2 - 1) % size.x);
else if (x2 > 0) x2 = x2 % size.x;
if (x2 < 0) x2 = isize.x - 1 - ((-x2 - 1) % isize.x);
else if (x2 > 0) x2 = x2 % isize.x;


list[i][j] = srcp[y2 * size.x + x2].rgb;
list[i][j] = srcp[y2 * isize.x + x2].rgb;
} }
} }


@@ -222,12 +224,12 @@ Image Image::Median(array2d<float> const &kernel) const
} }


/* Store the median value */ /* Store the median value */
dstp[y * size.x + x] = vec4(median, srcp[y * size.x + x].a);
dstp[y * isize.x + x] = vec4(median, srcp[y * isize.x + x].a);
} }
} }


tmp.Unlock(srcp);
ret.Unlock(dstp);
tmp.unlock(srcp);
ret.unlock(dstp);
} }


return ret; return ret;


+ 18
- 16
src/image/filter/yuv.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -17,28 +19,28 @@
namespace lol namespace lol
{ {


Image Image::YUVToRGB() const
image image::YUVToRGB() const
{ {
Image ret = *this;
int count = GetSize().x * GetSize().y;
image ret = *this;
int count = size().x * size().y;


vec4 *pixels = ret.Lock<PixelFormat::RGBA_F32>();
vec4 *pixels = ret.lock<PixelFormat::RGBA_F32>();
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
pixels[n] = Color::YUVToRGB(pixels[n]); pixels[n] = Color::YUVToRGB(pixels[n]);
ret.Unlock(pixels);
ret.unlock(pixels);


return ret; return ret;
} }


Image Image::RGBToYUV() const
image image::RGBToYUV() const
{ {
Image ret = *this;
int count = GetSize().x * GetSize().y;
image ret = *this;
int count = size().x * size().y;


vec4 *pixels = ret.Lock<PixelFormat::RGBA_F32>();
vec4 *pixels = ret.lock<PixelFormat::RGBA_F32>();
for (int n = 0; n < count; ++n) for (int n = 0; n < count; ++n)
pixels[n] = Color::RGBToYUV(pixels[n]); pixels[n] = Color::RGBToYUV(pixels[n]);
ret.Unlock(pixels);
ret.unlock(pixels);


return ret; return ret;
} }


+ 3
- 36
src/image/image-private.h View File

@@ -43,12 +43,12 @@ public:
array2d<typename PixelType<T>::type> m_array2d; array2d<typename PixelType<T>::type> m_array2d;
}; };


class ImageData
class image_data
{ {
friend class Image;
friend class image;


public: public:
ImageData()
image_data()
: m_size(0, 0), : m_size(0, 0),
m_wrap_x(WrapMode::Clamp), m_wrap_x(WrapMode::Clamp),
m_wrap_y(WrapMode::Clamp), m_wrap_y(WrapMode::Clamp),
@@ -66,38 +66,5 @@ public:
PixelFormat m_format; PixelFormat m_format;
}; };


class ImageCodec
{
public:
virtual char const *GetName() { return "<ImageCodec>"; }
virtual bool Load(Image *image, char const *path) = 0;
virtual bool Save(Image *image, char const *path) = 0;

/* TODO: this should become more fine-grained */
int m_priority;
};

#define REGISTER_IMAGE_CODEC(name) \
extern ImageCodec *Register##name(); \
{ \
/* Insert image codecs in a sorted list */ \
ImageCodec *codec = Register##name(); \
int i = 0, prio = codec->m_priority; \
for ( ; i < codeclist.count(); ++i) \
{ \
if (codeclist[i]->m_priority <= prio) \
break; \
} \
codeclist.insert(codec, i); \
}

#define DECLARE_IMAGE_CODEC(name, priority) \
ImageCodec *Register##name() \
{ \
ImageCodec *ret = new name(); \
ret->m_priority = priority; \
return ret; \
}

} /* namespace lol */ } /* namespace lol */



+ 63
- 143
src/image/image.cpp View File

@@ -1,7 +1,7 @@
// //
// Lol Engine // Lol Engine
// //
// Copyright © 2010—2016 Sam Hocevar <sam@hocevar.net>
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
// //
// Lol Engine is free software. It comes without any warranty, to // Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it // the extent permitted by applicable law. You can redistribute it
@@ -19,89 +19,34 @@
namespace lol namespace lol
{ {


/* HACK: We cannot make this an ImageLoader member function, because the
* REGISTER_IMAGE_CODEC macro forward-declares free functions from
* the "lol" namespace. An apparent bug in Visual Studio's compiler
* makes it think these functions are actually in the top-level
* namespace when the forward declaration is in a class member function.
* To avoid the problem, we make the forward declaration in a free
* function.
* The bug was reported to Microsoft and fixed by them, but the fix
* is not yet available.
* https://connect.microsoft.com/VisualStudio/feedback/details/730878/ */
static bool RegisterAllCodecs(array<ImageCodec *> &codeclist)
{
#if defined __ANDROID__
REGISTER_IMAGE_CODEC(AndroidImageCodec)
#endif
#if defined LOL_USE_GDIPLUS
REGISTER_IMAGE_CODEC(GdiPlusImageCodec)
#endif
#if defined __APPLE__ && defined __MACH__ && defined __arm__
REGISTER_IMAGE_CODEC(IosImageCodec)
#endif
#if defined LOL_USE_SDL_IMAGE
REGISTER_IMAGE_CODEC(SdlImageCodec)
#endif
#if defined LOL_USE_IMLIB2
REGISTER_IMAGE_CODEC(Imlib2ImageCodec)
#endif
REGISTER_IMAGE_CODEC(DummyImageCodec)
REGISTER_IMAGE_CODEC(ZedImageCodec)
REGISTER_IMAGE_CODEC(ZedPaletteImageCodec)
REGISTER_IMAGE_CODEC(OricImageCodec)

return true;
}

/* /*
* Our static image loader
* Public image class
*/ */


static class ImageLoader
image::image()
: m_data(new image_data())
{ {
friend class Image;

public:
inline ImageLoader()
{
RegisterAllCodecs(m_codecs);
}

private:
array<ImageCodec *> m_codecs;
map<String, Image *> m_images;
} }
g_image_loader;


/*
* Public Image class
*/

Image::Image()
: m_data(new ImageData())
{
}

Image::Image(char const *path)
: m_data(new ImageData())
image::image(char const *path)
: m_data(new image_data())
{ {
Load(path);
load(path);
} }


Image::Image(ivec2 size)
: m_data(new ImageData())
image::image(ivec2 size)
: m_data(new image_data())
{ {
SetSize(size);
resize(size);
} }


Image::Image (Image const &other)
: m_data(new ImageData())
image::image (image const &other)
: m_data(new image_data())
{ {
Copy(other); Copy(other);
} }


Image & Image::operator =(Image other)
image & image::operator =(image other)
{ {
/* Since the argument is passed by value, we’re assured it’s a new /* Since the argument is passed by value, we’re assured it’s a new
* object and we can safely swap our m_data pointers. */ * object and we can safely swap our m_data pointers. */
@@ -109,7 +54,7 @@ Image & Image::operator =(Image other)
return *this; return *this;
} }


Image::~Image()
image::~image()
{ {
for (int k : m_data->m_pixels.keys()) for (int k : m_data->m_pixels.keys())
delete m_data->m_pixels[k]; delete m_data->m_pixels[k];
@@ -117,85 +62,67 @@ Image::~Image()
delete m_data; delete m_data;
} }


void Image::DummyFill()
{
//TODO: This is not very beautiful
for (auto codec : g_image_loader.m_codecs)
{
if (String(codec->GetName()).contains("Dummy"))
{
codec->Load(this, nullptr);
return;
}
}
}

void Image::Copy(uint8_t* pixels, ivec2 const& size, PixelFormat fmt)
void image::Copy(uint8_t* src_pixels, ivec2 const& size, PixelFormat fmt)
{ {
ASSERT(fmt != PixelFormat::Unknown); ASSERT(fmt != PixelFormat::Unknown);
SetSize(size);
SetFormat(fmt);
memcpy(m_data->m_pixels[(int)fmt]->data(), pixels,
resize(size);
set_format(fmt);
memcpy(m_data->m_pixels[(int)fmt]->data(), src_pixels,
size.x * size.y * BytesPerPixel(fmt)); size.x * size.y * BytesPerPixel(fmt));
} }


void Image::Copy(Image const &other)
void image::Copy(image const &src)
{ {
ivec2 size = other.GetSize();
PixelFormat fmt = other.GetFormat();
ivec2 size = src.size();
PixelFormat fmt = src.format();


SetSize(size);
resize(size);
if (fmt != PixelFormat::Unknown) if (fmt != PixelFormat::Unknown)
{ {
SetFormat(fmt);
set_format(fmt);
memcpy(m_data->m_pixels[(int)fmt]->data(), memcpy(m_data->m_pixels[(int)fmt]->data(),
other.m_data->m_pixels[(int)fmt]->data(),
src.m_data->m_pixels[(int)fmt]->data(),
size.x * size.y * BytesPerPixel(fmt)); size.x * size.y * BytesPerPixel(fmt));
} }
} }


bool Image::Load(char const *path)
void image::DummyFill()
{ {
ImageCodec* last_codec = nullptr;
for (auto codec : g_image_loader.m_codecs)
{
last_codec = codec;
if (codec->Load(this, path))
{
msg::info("Image::Load: Codec %s succesfully loaded %s.\n", codec->GetName(), path);
return true;
}
}

//Log error, because we shouldn't be here
msg::error("Image::Load: Last codec %s, Error loading image %s.\n", last_codec->GetName(), path);
return false;
load("DUMMY");
} }


bool Image::Save(char const *path)
bool image::load(char const *path)
{ {
ImageCodec* last_codec = nullptr;
for (auto codec : g_image_loader.m_codecs)
auto resource = ResourceLoader::Load(path);
if (resource == nullptr)
return false;

auto image_resource = dynamic_cast<ResourceImageData*>(resource);
if (image_resource == nullptr)
{ {
last_codec = codec;
if (codec->Save(this, path))
{
msg::info("Image::Save: Codec %s succesfully saved %s.\n", codec->GetName(), path);
return true;
}
delete image_resource;
return false;
} }


//Log error, because we shouldn't be here
msg::error("Image::Save: Last codec %s, Error saving image %s.\n", last_codec->GetName(), path);
return false;
Copy(*image_resource->m_image);
delete image_resource;
return true;
} }


ivec2 Image::GetSize() const
bool image::save(char const *path)
{
auto data = new ResourceImageData(new image(*this));
auto result = ResourceLoader::Save(path, data);
delete data;
return result;
}

ivec2 image::size() const
{ {
return m_data->m_size; return m_data->m_size;
} }


void Image::SetSize(ivec2 size)
void image::resize(ivec2 size)
{ {
ASSERT(size.x > 0); ASSERT(size.x > 0);
ASSERT(size.y > 0); ASSERT(size.y > 0);
@@ -215,40 +142,40 @@ void Image::SetSize(ivec2 size)
} }


/* Wrap-around mode for some operations */ /* Wrap-around mode for some operations */
WrapMode Image::GetWrapX() const
WrapMode image::GetWrapX() const
{ {
return m_data->m_wrap_x; return m_data->m_wrap_x;
} }


WrapMode Image::GetWrapY() const
WrapMode image::GetWrapY() const
{ {
return m_data->m_wrap_y; return m_data->m_wrap_y;
} }


void Image::SetWrap(WrapMode wrap_x, WrapMode wrap_y)
void image::SetWrap(WrapMode wrap_x, WrapMode wrap_y)
{ {
m_data->m_wrap_x = wrap_x; m_data->m_wrap_x = wrap_x;
m_data->m_wrap_y = wrap_y; m_data->m_wrap_y = wrap_y;
} }


/* The Lock() method */
template<PixelFormat T> typename PixelType<T>::type *Image::Lock()
/* The lock() method */
template<PixelFormat T> typename PixelType<T>::type *image::lock()
{ {
SetFormat(T);
set_format(T);


return (typename PixelType<T>::type *)m_data->m_pixels[(int)T]->data(); return (typename PixelType<T>::type *)m_data->m_pixels[(int)T]->data();
} }


/* The Lock2D() method */
void *Image::Lock2DHelper(PixelFormat T)
/* The lock2d() method */
void *image::lock2d_helper(PixelFormat T)
{ {
SetFormat(T);
set_format(T);


return m_data->m_pixels[(int)T]->data2d(); return m_data->m_pixels[(int)T]->data2d();
} }


template<typename T> template<typename T>
void Image::Unlock2D(array2d<T> const &array)
void image::unlock2d(array2d<T> const &array)
{ {
ASSERT(m_data->m_pixels.has_key((int)m_data->m_format)); ASSERT(m_data->m_pixels.has_key((int)m_data->m_format));
ASSERT(array.data() == m_data->m_pixels[(int)m_data->m_format]->data()); ASSERT(array.data() == m_data->m_pixels[(int)m_data->m_format]->data());
@@ -256,9 +183,9 @@ void Image::Unlock2D(array2d<T> const &array)


/* Explicit specialisations for the above templates */ /* Explicit specialisations for the above templates */
#define _T(T) \ #define _T(T) \
template PixelType<T>::type *Image::Lock<T>(); \
template array2d<PixelType<T>::type> &Image::Lock2D<T>(); \
template void Image::Unlock2D(array2d<PixelType<T>::type> const &array);
template PixelType<T>::type *image::lock<T>(); \
template array2d<PixelType<T>::type> &image::lock2d<T>(); \
template void image::unlock2d(array2d<PixelType<T>::type> const &array);
_T(PixelFormat::Y_8) _T(PixelFormat::Y_8)
_T(PixelFormat::RGB_8) _T(PixelFormat::RGB_8)
_T(PixelFormat::RGBA_8) _T(PixelFormat::RGBA_8)
@@ -268,25 +195,18 @@ _T(PixelFormat::RGBA_F32)
#undef _T #undef _T


/* Special case for the "any" format: return the last active buffer */ /* Special case for the "any" format: return the last active buffer */
void *Image::Lock()
void *image::lock()
{ {
ASSERT(m_data->m_format != PixelFormat::Unknown); ASSERT(m_data->m_format != PixelFormat::Unknown);


return m_data->m_pixels[(int)m_data->m_format]->data(); return m_data->m_pixels[(int)m_data->m_format]->data();
} }


void Image::Unlock(void const *pixels)
void image::unlock(void const *pixels)
{ {
ASSERT(m_data->m_pixels.has_key((int)m_data->m_format)); ASSERT(m_data->m_pixels.has_key((int)m_data->m_format));
ASSERT(pixels == m_data->m_pixels[(int)m_data->m_format]->data()); ASSERT(pixels == m_data->m_pixels[(int)m_data->m_format]->data());
} }


bool Image::RetrieveTiles(array<ivec2, ivec2>& tiles) const
{
/* TODO: re-implement this */
//return m_data->m_codecdata->RetrieveTiles(tiles);
return false;
}

} /* namespace lol */ } /* namespace lol */



+ 15
- 13
src/image/kernel.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -17,7 +19,7 @@
namespace lol namespace lol
{ {


array2d<float> Image::BayerKernel(ivec2 size)
array2d<float> image::kernel::bayer(ivec2 size)
{ {
array2d<float> ret(size); array2d<float> ret(size);


@@ -46,7 +48,7 @@ array2d<float> Image::BayerKernel(ivec2 size)
return ret; return ret;
} }


array2d<float> Image::HalftoneKernel(ivec2 size)
array2d<float> image::kernel::halftone(ivec2 size)
{ {
array2d<float> ret(size); array2d<float> ret(size);


@@ -72,10 +74,10 @@ array2d<float> Image::HalftoneKernel(ivec2 size)
ret[x][y] = flip ? 10.f - r : r; ret[x][y] = flip ? 10.f - r : r;
} }


return NormalizeKernel(ret);
return normalize(ret);
} }


array2d<float> Image::BlueNoiseKernel(ivec2 size, ivec2 gsize)
array2d<float> image::kernel::blue_noise(ivec2 size, ivec2 gsize)
{ {
float const epsilon = 1.f / (size.x * size.y + 1); float const epsilon = 1.f / (size.x * size.y + 1);
gsize = lol::min(size, gsize); gsize = lol::min(size, gsize);
@@ -180,7 +182,7 @@ static int cmpdot(const void *p1, const void *p2)
return ((Dot const *)p1)->val > ((Dot const *)p2)->val; return ((Dot const *)p1)->val > ((Dot const *)p2)->val;
} }


array2d<float> Image::NormalizeKernel(array2d<float> const &kernel)
array2d<float> image::kernel::normalize(array2d<float> const &kernel)
{ {
ivec2 size = kernel.size(); ivec2 size = kernel.size();


@@ -209,7 +211,7 @@ array2d<float> Image::NormalizeKernel(array2d<float> const &kernel)
return dst; return dst;
} }


array2d<float> Image::EdiffKernel(EdiffAlgorithm algorithm)
array2d<float> image::kernel::ediff(EdiffAlgorithm algorithm)
{ {
switch (algorithm) switch (algorithm)
{ {
@@ -270,7 +272,7 @@ array2d<float> Image::EdiffKernel(EdiffAlgorithm algorithm)
* there is little chance that any value below 0.2 will be useful. */ * there is little chance that any value below 0.2 will be useful. */
#define BLUR_EPSILON 0.2f #define BLUR_EPSILON 0.2f


array2d<float> Image::GaussianKernel(vec2 radius, float angle, vec2 delta)
array2d<float> image::kernel::gaussian(vec2 radius, float angle, vec2 delta)
{ {
array2d<float> kernel; array2d<float> kernel;




+ 1
- 1
src/image/movie.cpp View File

@@ -60,7 +60,7 @@ Movie::~Movie()
delete m_data; delete m_data;
} }


void Movie::Feed(Image const &image)
void Movie::Feed(image const &image)
{ {
#if LOL_USE_FFMPEG #if LOL_USE_FFMPEG




+ 12
- 10
src/image/noise.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -17,10 +19,10 @@
namespace lol namespace lol
{ {


bool Image::RenderRandom(ivec2 size)
bool image::RenderRandom(ivec2 size)
{ {
SetSize(size);
vec4 *pixels = Lock<PixelFormat::RGBA_F32>();
resize(size);
vec4 *pixels = lock<PixelFormat::RGBA_F32>();


for (int n = 0; n < size.x * size.y; ++n) for (int n = 0; n < size.x * size.y; ++n)
pixels[n] = vec4(lol::rand(1.f), pixels[n] = vec4(lol::rand(1.f),
@@ -28,7 +30,7 @@ bool Image::RenderRandom(ivec2 size)
lol::rand(1.f), lol::rand(1.f),
1.f); 1.f);


Unlock(pixels);
unlock(pixels);


return true; return true;
} }


+ 33
- 33
src/image/pixel.cpp View File

@@ -1,7 +1,7 @@
// //
// Lol Engine // Lol Engine
// //
// Copyright © 2004—2015 Sam Hocevar <sam@hocevar.net>
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
// //
// Lol Engine is free software. It comes without any warranty, to // Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it // the extent permitted by applicable law. You can redistribute it
@@ -60,7 +60,7 @@ static u8vec4 f32tou8(vec4 pixel)
* Pixel-level image manipulation * Pixel-level image manipulation
*/ */


PixelFormat Image::GetFormat() const
PixelFormat image::format() const
{ {
return m_data->m_format; return m_data->m_format;
} }
@@ -81,41 +81,41 @@ PixelFormat Image::GetFormat() const
* x lossless conversion (u8 to float) * x lossless conversion (u8 to float)
* # lossy conversion (dithering and/or convert color→gray) * # lossy conversion (dithering and/or convert color→gray)
*/ */
void Image::SetFormat(PixelFormat fmt)
void image::set_format(PixelFormat fmt)
{ {
PixelFormat old_fmt = m_data->m_format; PixelFormat old_fmt = m_data->m_format;


/* Preliminary intermediate conversions */ /* Preliminary intermediate conversions */
if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::Y_F32) if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::Y_F32)
SetFormat(PixelFormat::RGBA_F32);
set_format(PixelFormat::RGBA_F32);
else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::Y_F32) else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::Y_F32)
SetFormat(PixelFormat::RGBA_F32);
set_format(PixelFormat::RGBA_F32);
else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGBA_8) else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGBA_8)
SetFormat(PixelFormat::RGBA_F32);
set_format(PixelFormat::RGBA_F32);
else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGB_8) else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGB_8)
SetFormat(PixelFormat::RGBA_F32);
set_format(PixelFormat::RGBA_F32);
else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::RGBA_8) else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::RGBA_8)
SetFormat(PixelFormat::RGBA_F32);
set_format(PixelFormat::RGBA_F32);
else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::Y_F32) else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::Y_F32)
SetFormat(PixelFormat::RGB_F32);
set_format(PixelFormat::RGB_F32);
else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::RGB_8) else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::RGB_8)
SetFormat(PixelFormat::RGB_F32);
set_format(PixelFormat::RGB_F32);
else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::Y_8) else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::Y_8)
SetFormat(PixelFormat::RGB_F32);
set_format(PixelFormat::RGB_F32);
else if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::Y_8) else if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::Y_8)
SetFormat(PixelFormat::RGB_F32);
set_format(PixelFormat::RGB_F32);
else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::Y_8) else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::Y_8)
SetFormat(PixelFormat::Y_F32);
set_format(PixelFormat::Y_F32);
else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::Y_8) else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::Y_8)
SetFormat(PixelFormat::Y_F32);
set_format(PixelFormat::Y_F32);


old_fmt = m_data->m_format; old_fmt = m_data->m_format;


/* Set the new active pixel format */ /* Set the new active pixel format */
m_data->m_format = fmt; m_data->m_format = fmt;


ivec2 size = GetSize();
int count = size.x * size.y;
ivec2 isize = size();
int count = isize.x * isize.y;


/* If we never used this format, allocate a new buffer: we will /* If we never used this format, allocate a new buffer: we will
* obviously need it. */ * obviously need it. */
@@ -131,17 +131,17 @@ void Image::SetFormat(PixelFormat fmt)
case PixelFormat::Unknown: case PixelFormat::Unknown:
break; break;
case PixelFormat::Y_8: case PixelFormat::Y_8:
data = new PixelData<PixelFormat::Y_8>(size); break;
data = new PixelData<PixelFormat::Y_8>(isize); break;
case PixelFormat::RGB_8: case PixelFormat::RGB_8:
data = new PixelData<PixelFormat::RGB_8>(size); break;
data = new PixelData<PixelFormat::RGB_8>(isize); break;
case PixelFormat::RGBA_8: case PixelFormat::RGBA_8:
data = new PixelData<PixelFormat::RGBA_8>(size); break;
data = new PixelData<PixelFormat::RGBA_8>(isize); break;
case PixelFormat::Y_F32: case PixelFormat::Y_F32:
data = new PixelData<PixelFormat::Y_F32>(size); break;
data = new PixelData<PixelFormat::Y_F32>(isize); break;
case PixelFormat::RGB_F32: case PixelFormat::RGB_F32:
data = new PixelData<PixelFormat::RGB_F32>(size); break;
data = new PixelData<PixelFormat::RGB_F32>(isize); break;
case PixelFormat::RGBA_F32: case PixelFormat::RGBA_F32:
data = new PixelData<PixelFormat::RGBA_F32>(size); break;
data = new PixelData<PixelFormat::RGBA_F32>(isize); break;
} }
#if __GNUC__ #if __GNUC__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@@ -314,31 +314,31 @@ void Image::SetFormat(PixelFormat fmt)
#if 0 #if 0
init_tables(); init_tables();


for (int y = 0; y < size.y; y++)
for (int x = 0; x < size.x; x++)
for (int y = 0; y < isize.y; y++)
for (int x = 0; x < isize.x; x++)
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
double p, e; double p, e;
uint8_t d; uint8_t d;


p = src[4 * (y * size.x + x) + i];
p = src[4 * (y * isize.x + x) + i];


if (p < 0.) d = 0.; if (p < 0.) d = 0.;
else if (p > 1.) d = 255; else if (p > 1.) d = 255;
else d = (int)(255.999 * pow(p, 1. / global_gamma)); else d = (int)(255.999 * pow(p, 1. / global_gamma));


dest[4 * (y * size.x + x) + i] = d;
dest[4 * (y * isize.x + x) + i] = d;


e = (p - u8tof32(d)) / 16; e = (p - u8tof32(d)) / 16;
if (x < size.x - 1)
src[4 * (y * size.x + x + 1) + i] += e * 7;
if (y < size.y - 1)
if (x < isize.x - 1)
src[4 * (y * isize.x + x + 1) + i] += e * 7;
if (y < isize.y - 1)
{ {
if (x > 0) if (x > 0)
src[4 * ((y + 1) * size.x + x - 1) + i] += e * 3;
src[4 * ((y + 1) * size.x + x) + i] += e * 5;
if (x < size.x - 1)
src[4 * ((y + 1) * size.x + x + 1) + i] += e;
src[4 * ((y + 1) * isize.x + x - 1) + i] += e * 3;
src[4 * ((y + 1) * isize.x + x) + i] += e * 5;
if (x < isize.x - 1)
src[4 * ((y + 1) * isize.x + x + 1) + i] += e;
} }
} }
#endif #endif


+ 25
- 23
src/image/resample.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2004—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -17,10 +19,10 @@
namespace lol namespace lol
{ {


static Image ResizeBicubic(Image &image, ivec2 size);
static Image ResizeBresenham(Image &image, ivec2 size);
static image ResizeBicubic(image &src, ivec2 size);
static image ResizeBresenham(image &src, ivec2 size);


Image Image::Resize(ivec2 size, ResampleAlgorithm algorithm)
image image::Resize(ivec2 size, ResampleAlgorithm algorithm)
{ {
switch (algorithm) switch (algorithm)
{ {
@@ -32,13 +34,13 @@ Image Image::Resize(ivec2 size, ResampleAlgorithm algorithm)
} }
} }


static Image ResizeBicubic(Image &image, ivec2 size)
static image ResizeBicubic(image &src, ivec2 size)
{ {
Image dst(size);
ivec2 const oldsize = image.GetSize();
image dst(size);
ivec2 const oldsize = src.size();


vec4 const *srcp = image.Lock<PixelFormat::RGBA_F32>();
vec4 *dstp = dst.Lock<PixelFormat::RGBA_F32>();
vec4 const *srcp = src.lock<PixelFormat::RGBA_F32>();
vec4 *dstp = dst.lock<PixelFormat::RGBA_F32>();


float scalex = size.x > 1 ? (oldsize.x - 1.f) / (size.x - 1) : 1.f; float scalex = size.x > 1 ? (oldsize.x - 1.f) / (size.x - 1) : 1.f;
float scaley = size.y > 1 ? (oldsize.y - 1.f) / (size.y - 1) : 1.f; float scaley = size.y > 1 ? (oldsize.y - 1.f) / (size.y - 1) : 1.f;
@@ -121,8 +123,8 @@ static Image ResizeBicubic(Image &image, ivec2 size)
} }
} }


dst.Unlock(dstp);
image.Unlock(srcp);
dst.unlock(dstp);
src.unlock(srcp);


return dst; return dst;
} }
@@ -134,14 +136,14 @@ static Image ResizeBicubic(Image &image, ivec2 size)
/* FIXME: the algorithm does not handle alpha components properly. Resulting /* FIXME: the algorithm does not handle alpha components properly. Resulting
* alpha should be the mean alpha value of the neightbouring pixels, but * alpha should be the mean alpha value of the neightbouring pixels, but
* the colour components should be weighted with the alpha value. */ * the colour components should be weighted with the alpha value. */
static Image ResizeBresenham(Image &image, ivec2 size)
static image ResizeBresenham(image &src, ivec2 size)
{ {
Image dst(size);
ivec2 const oldsize = image.GetSize();
image dst(size);
ivec2 const oldsize = src.size();
float const invswsh = 1.0f / (oldsize.x * oldsize.y); float const invswsh = 1.0f / (oldsize.x * oldsize.y);


vec4 const *srcp = image.Lock<PixelFormat::RGBA_F32>();
vec4 *dstp = dst.Lock<PixelFormat::RGBA_F32>();
vec4 const *srcp = src.lock<PixelFormat::RGBA_F32>();
vec4 *dstp = dst.lock<PixelFormat::RGBA_F32>();


array<vec4> aline, line; array<vec4> aline, line;
aline.resize(size.x); aline.resize(size.x);
@@ -198,8 +200,8 @@ static Image ResizeBresenham(Image &image, ivec2 size)
dstp[y * size.x + x] = aline[x] * invswsh; dstp[y * size.x + x] = aline[x] * invswsh;
} }


dst.Unlock(dstp);
image.Unlock(srcp);
dst.unlock(dstp);
src.unlock(srcp);


return dst; return dst;
} }


+ 57
- 0
src/image/resource-private.h View File

@@ -0,0 +1,57 @@
//
// Lol Engine
//
// Copyright: (c) 2016—2017 Sam Hocevar <sam@hocevar.net>
// Copyright © 2016—2017 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
//

#pragma once

//
// The ResourceCodecData class
// ------------------------
//

namespace lol
{

class ResourceCodec
{
public:
virtual char const *GetName() { return "<ResourceCodec>"; }
virtual ResourceCodecData* Load(char const *path) = 0;
virtual bool Save(char const *path, ResourceCodecData* data) = 0;

/* TODO: this should become more fine-grained */
int m_priority;
};

#define REGISTER_IMAGE_CODEC(name) \
extern ResourceCodec *Register##name(); \
{ \
/* Insert image codecs in a sorted list */ \
ResourceCodec *codec = Register##name(); \
int i = 0, prio = codec->m_priority; \
for ( ; i < codeclist.count(); ++i) \
{ \
if (codeclist[i]->m_priority <= prio) \
break; \
} \
codeclist.insert(codec, i); \
}

#define DECLARE_IMAGE_CODEC(name, priority) \
ResourceCodec *Register##name() \
{ \
ResourceCodec *ret = new name(); \
ret->m_priority = priority; \
return ret; \
}

} /* namespace lol */


+ 121
- 0
src/image/resource.cpp View File

@@ -0,0 +1,121 @@
//
// Lol Engine
//
// Copyright © 2016—2017 Sam Hocevar <sam@hocevar.net>
// Copyright © 2016—2017 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#include <lol/engine-internal.h>

#include "resource-private.h"

#include <algorithm> /* for std::swap */

namespace lol
{

/* HACK: We cannot make this an ImageLoader member function, because the
* REGISTER_IMAGE_CODEC macro forward-declares free functions from
* the "lol" namespace. An apparent bug in Visual Studio's compiler
* makes it think these functions are actually in the top-level
* namespace when the forward declaration is in a class member function.
* To avoid the problem, we make the forward declaration in a free
* function.
* The bug was reported to Microsoft and fixed by them, but the fix
* is not yet available.
* https://connect.microsoft.com/VisualStudio/feedback/details/730878/ */
static bool RegisterAllCodecs(array<ResourceCodec *> &codeclist)
{
#if defined __ANDROID__
REGISTER_IMAGE_CODEC(AndroidImageCodec)
#endif
#if defined LOL_USE_GDIPLUS
REGISTER_IMAGE_CODEC(GdiPlusImageCodec)
#endif
#if defined __APPLE__ && defined __MACH__ && defined __arm__
REGISTER_IMAGE_CODEC(IosImageCodec)
#endif
#if defined LOL_USE_SDL_IMAGE
REGISTER_IMAGE_CODEC(SdlImageCodec)
#endif
#if defined LOL_USE_IMLIB2
REGISTER_IMAGE_CODEC(Imlib2ImageCodec)
#endif
REGISTER_IMAGE_CODEC(ZedImageCodec)
REGISTER_IMAGE_CODEC(ZedPaletteImageCodec)
REGISTER_IMAGE_CODEC(OricImageCodec)

REGISTER_IMAGE_CODEC(DummyImageCodec)

return true;
}

/*
* Our static image loader
*/

static class StaticResourceLoader
{
friend class ResourceLoader;

public:
inline StaticResourceLoader()
{
RegisterAllCodecs(m_codecs);
}

private:
array<ResourceCodec *> m_codecs;
}
g_resource_loader;

/*
* The public resource loader
*/

ResourceCodecData* ResourceLoader::Load(char const *path)
{
ResourceCodec* last_codec = nullptr;
for (auto codec : g_resource_loader.m_codecs)
{
last_codec = codec;
auto data = codec->Load(path);
if (data != nullptr)
{
msg::info("image::Load: Codec %s succesfully loaded %s.\n", codec->GetName(), path);
return data;
}
}

//Log error, because we shouldn't be here
msg::error("image::Load: Last codec %s, Error loading resource %s.\n", last_codec->GetName(), path);
return nullptr;
}

bool ResourceLoader::Save(char const *path, ResourceCodecData* data)
{
ResourceCodec* last_codec = nullptr;
for (auto codec : g_resource_loader.m_codecs)
{
last_codec = codec;
if (codec->Save(path, data))
{
msg::info("image::Save: Codec %s succesfully saved %s.\n", codec->GetName(), path);
return true;
}
}

//Log error, because we shouldn't be here
msg::error("image::Save: Last codec %s, Error saving resource %s.\n", last_codec->GetName(), path);
return false;
}


} /* namespace lol */


+ 11
- 1
src/input/input.cpp View File

@@ -36,6 +36,16 @@ String InputDevice::GetText()
return ret; return ret;
} }


bool InputDevice::IsTextInputActive()
{
return m_input_active;
}

void InputDevice::SetTextInputActive(bool status)
{
m_input_active = status;
}

void InputDeviceInternal::AddKey(int index, const char* name) void InputDeviceInternal::AddKey(int index, const char* name)
{ {
if (index == -1) if (index == -1)
@@ -104,7 +114,7 @@ InputDeviceInternal* InputDeviceInternal::CreateStandardMouse()
mouse->AddAxis(g_name_mouse_axis_y.C()); mouse->AddAxis(g_name_mouse_axis_y.C());
mouse->AddAxis(g_name_mouse_axis_xpixel.C()); mouse->AddAxis(g_name_mouse_axis_xpixel.C());
mouse->AddAxis(g_name_mouse_axis_ypixel.C()); mouse->AddAxis(g_name_mouse_axis_ypixel.C());
mouse->AddAxis(g_name_mouse_axis_scroll.C());
mouse->AddAxis(g_name_mouse_axis_scroll.C(), .0000001f);


mouse->AddCursor(g_name_mouse_cursor.C()); mouse->AddCursor(g_name_mouse_cursor.C());




+ 6
- 1
src/input/input.h View File

@@ -98,6 +98,8 @@ public:


/** Gets the latest contents of text input. */ /** Gets the latest contents of text input. */
String GetText(); String GetText();
bool IsTextInputActive();
void SetTextInputActive(bool status);


/** Gets the current value of the given axis. Devices should try to /** Gets the current value of the given axis. Devices should try to
* clamp this value between -1 and 1, though it is not guaranteed. */ * clamp this value between -1 and 1, though it is not guaranteed. */
@@ -199,6 +201,7 @@ protected:


/** Text input state */ /** Text input state */
String m_text; String m_text;
bool m_input_active;


/** Axis states (value and sensitivity) */ /** Axis states (value and sensitivity) */
array<float, float> m_axis; array<float, float> m_axis;
@@ -208,7 +211,9 @@ protected:


static bool m_capturemouse; static bool m_capturemouse;


InputDevice(String const &name) : m_name(name)
InputDevice(String const &name)
: m_name(name),
m_input_active(false)
{ {
devices.push_unique(this); devices.push_unique(this);
} }


+ 4
- 1
src/lol-core.vcxproj View File

@@ -148,6 +148,7 @@
<ClCompile Include="image\noise.cpp" /> <ClCompile Include="image\noise.cpp" />
<ClCompile Include="image\pixel.cpp" /> <ClCompile Include="image\pixel.cpp" />
<ClCompile Include="image\resample.cpp" /> <ClCompile Include="image\resample.cpp" />
<ClCompile Include="image\resource.cpp" />
<ClCompile Include="input\controller.cpp" /> <ClCompile Include="input\controller.cpp" />
<ClCompile Include="input\input.cpp" /> <ClCompile Include="input\input.cpp" />
<ClCompile Include="light.cpp" /> <ClCompile Include="light.cpp" />
@@ -238,6 +239,7 @@
<ClInclude Include="forge.h" /> <ClInclude Include="forge.h" />
<ClInclude Include="gradient.h" /> <ClInclude Include="gradient.h" />
<ClInclude Include="image\image-private.h" /> <ClInclude Include="image\image-private.h" />
<ClInclude Include="image\resource-private.h" />
<ClInclude Include="input\controller.h" /> <ClInclude Include="input\controller.h" />
<ClInclude Include="input\input.h" /> <ClInclude Include="input\input.h" />
<ClInclude Include="input\input_internal.h" /> <ClInclude Include="input\input_internal.h" />
@@ -285,6 +287,7 @@
<ClInclude Include="lol\image\image.h" /> <ClInclude Include="lol\image\image.h" />
<ClInclude Include="lol\image\movie.h" /> <ClInclude Include="lol\image\movie.h" />
<ClInclude Include="lol\image\pixel.h" /> <ClInclude Include="lol\image\pixel.h" />
<ClInclude Include="lol\image\resource.h" />
<ClInclude Include="lol\math\all.h" /> <ClInclude Include="lol\math\all.h" />
<ClInclude Include="lol\math\arraynd.h" /> <ClInclude Include="lol\math\arraynd.h" />
<ClInclude Include="lol\math\bigint.h" /> <ClInclude Include="lol\math\bigint.h" />
@@ -397,4 +400,4 @@
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
<Import Project="$(LolDir)\build\msbuild\lolfx.targets" /> <Import Project="$(LolDir)\build\msbuild\lolfx.targets" />
</ImportGroup> </ImportGroup>
</Project>
</Project>

+ 150
- 89
src/lol/debug/lines.h View File

@@ -22,96 +22,157 @@ namespace lol


namespace Debug namespace Debug
{ {
class DrawContext
{
public:
class Data
{
public:
vec4 m_color = vec4(1.f);
float m_duration = 0.0f;
int m_mask = 0;
float m_segment_size = 8;


//Resets draw infos
void DrawSetupReset();
//Sets draw infos
void DrawSetupTime(float new_time);
void DrawSetupMask(int new_mask);
void DrawSetupSegment(float segment_size);
void DrawSetupColor(vec4 color);
void DrawSetup(float new_time, int new_mask, float segment_size, vec4 color);

//Screen to world conversion
vec3 WorldToScreen(vec3 pos);
vec3 WorldToScreen(vec3 pos, mat4 view_proj);
vec3 WorldToScreen(vec4 pos);
vec3 WorldToScreen(vec4 pos, mat4 view_proj);
vec3 ScreenToWorld(vec2 pos, float z=-1.f);
vec3 ScreenToWorld(vec3 pos);
vec3 ScreenToWorld(vec2 pos, mat4 inv_view_proj, float z=-1.f);
vec3 ScreenToWorld(vec3 pos, mat4 inv_view_proj);
vec3 ScreenToWorld(vec3 pos, mat4 view, mat4 proj);

//Draw stuff in World
//-- LINE
void DrawLine(vec3 a, vec3 b);
void DrawLine(vec2 a, vec3 b, float az=-1.f);
void DrawLine(vec2 a, vec2 b, float az=-1.f, float bz=-1.f);
void DrawLine(vec3 a, vec3 b, vec4 color);
void DrawLine(vec2 a, vec3 b, vec4 color, float az=-1.f);
void DrawLine(vec2 a, vec2 b, vec4 color, float az=-1.f, float bz=-1.f);
//-- GIZMO
void DrawGizmo(vec3 pos, vec3 x, vec3 y, vec3 z, float size);
void DrawGizmo(vec2 pos, vec3 x, vec3 y, vec3 z, float size, float posz = -1.f);
//-- GRID
void DrawGrid(vec3 pos, vec3 x, vec3 y, vec3 z, float size, bool draw_3d=false);
//-- ARROW
void DrawArrow(vec3 a, vec3 b, vec2 s);
void DrawArrow(vec2 a, vec3 b, vec2 s, float az=-1.f);
void DrawArrow(vec2 a, vec2 b, vec2 s, float az=-1.f, float bz=-1.f);
void DrawArrow(vec3 a, vec3 b, vec3 s);
void DrawArrow(vec2 a, vec3 b, vec3 s, float az=-1.f);
void DrawArrow(vec2 a, vec2 b, vec3 s, float az=-1.f, float bz=-1.f);
void DrawArrow(vec3 a, vec3 b, vec3 s, vec4 color);
void DrawArrow(vec2 a, vec3 b, vec3 s, vec4 color, float az=-1.f);
void DrawArrow(vec2 a, vec2 b, vec3 s, vec4 color, float az=-1.f, float bz=-1.f);
//-- BOX
void DrawBox(box3 a);
void DrawBox(box2 a);
void DrawBox(box3 a, vec4 color);
void DrawBox(box2 a, vec4 color);
void DrawBox(vec3 a, vec3 b);
void DrawBox(vec2 a, vec2 b);
void DrawBox(vec2 a, float s);
void DrawBox(vec3 a, vec3 b, vec4 color);
void DrawBox(vec2 a, vec2 b, vec4 color);
void DrawBox(vec2 a, float s, vec4 color);
void DrawBox(box3 a, mat4 transform);
void DrawBox(box2 a, mat2 transform);
void DrawBox(box3 a, mat4 transform, vec4 color);
void DrawBox(box2 a, mat2 transform, vec4 color);
void DrawBox(vec3 a, vec3 b, mat4 transform);
void DrawBox(vec2 a, vec2 b, mat2 transform);
void DrawBox(vec2 a, float s, mat2 transform);
void DrawBox(vec3 a, vec3 b, mat4 transform, vec4 color);
void DrawBox(vec2 a, vec2 b, mat2 transform, vec4 color);
void DrawBox(vec2 a, float s, mat2 transform, vec4 color);
//-- CIRCLE
void DrawCircle(vec2 a, float s);
void DrawCircle(vec3 a, vec3 n);
void DrawCircle(vec2 a, vec2 s);
void DrawCircle(vec3 a, vec3 n, vec4 color);
void DrawCircle(vec2 a, vec2 s, vec4 color);
void DrawCircle(vec3 a, vec3 x, vec3 y);
void DrawCircle(vec2 a, vec2 x, vec2 y);
void DrawCircle(vec3 a, vec3 x, vec3 y, vec4 color);
void DrawCircle(vec2 a, vec2 x, vec2 y, vec4 color);
//-- SPHERE
void DrawSphere(vec3 a, float s);
void DrawSphere(vec3 a, float s, vec4 color);
void DrawSphere(vec3 a, vec3 x, vec3 y, vec3 z);
void DrawSphere(vec3 a, vec3 x, vec3 y, vec3 z, vec4 color);
//-- CAPSULE
void DrawCapsule(vec3 a, float s, vec3 h);
void DrawCapsule(vec3 a, float s, vec3 h, vec4 color);
void DrawCapsule(vec3 a, vec3 x, vec3 y, vec3 z, vec3 h);
void DrawCapsule(vec3 a, vec3 x, vec3 y, vec3 z, vec3 h, vec4 color);
//-- VIEW PROJ
void DrawViewProj(mat4 view_proj);
void DrawViewProj(mat4 view_proj, vec4 color);
void DrawViewProj(mat4 view, mat4 proj);
void DrawViewProj(mat4 view, mat4 proj, vec4 color);
Data() {}
Data(vec4 color, float duration = -1.f, int mask = 0xFFFFFFFF, float segment_size = 1.f)
{
m_color = color;
m_duration = duration;
m_mask = mask;
m_segment_size = segment_size;
}
inline Data& operator=(vec4 const& color) { m_color = color; return *this; }
};

private:
static Data m_global;
Data m_previous;
Data m_current;

DrawContext(vec4 color, float duration, int mask, float segment_size)
{
//Store old datas
m_previous.m_color = m_global.m_color;
m_previous.m_duration = m_global.m_duration;
m_previous.m_mask = m_global.m_mask;
m_previous.m_segment_size = m_global.m_segment_size;

//Create new one
SetColor(color);
SetDuration(duration);
SetMask(mask);
SetSegmentSize(segment_size);
}

public:
~DrawContext()
{
m_global.m_color = m_previous.m_color;
m_global.m_duration = m_previous.m_duration;
m_global.m_mask = m_previous.m_mask;
m_global.m_segment_size = m_previous.m_segment_size;
}

static DrawContext New(vec4 color, float duration = -1.f, int mask = 0xFFFFFFFF, float segment_size = 1.f)
{
return DrawContext(color, duration, mask, segment_size);
}

static DrawContext New(DrawContext& dc)
{
return DrawContext(dc.m_current.m_color, dc.m_current.m_duration, dc.m_current.m_mask, dc.m_current.m_segment_size);
}

static Data GetGlobalData() { return m_global; }

//Setup methods
void SetColor(vec4 color) { m_global.m_color = m_current.m_color = color; }
void SetDuration(float duration) { m_global.m_duration = m_current.m_duration = duration; }
void SetMask(int mask) { m_global.m_mask = m_current.m_mask = mask; }
void SetSegmentSize(float segment_size) { m_global.m_segment_size = m_current.m_segment_size = segment_size; }
};

//Screen to world conversion
vec3 WorldToScreen(vec3 pos);
vec3 WorldToScreen(vec3 pos, mat4 view_proj);
vec3 WorldToScreen(vec4 pos);
vec3 WorldToScreen(vec4 pos, mat4 view_proj);
vec3 ScreenToWorld(vec2 pos, float z=-1.f);
vec3 ScreenToWorld(vec3 pos);
vec3 ScreenToWorld(vec2 pos, mat4 inv_view_proj, float z=-1.f);
vec3 ScreenToWorld(vec3 pos, mat4 inv_view_proj);
vec3 ScreenToWorld(vec3 pos, mat4 view, mat4 proj);

//Draw stuff in World
//Draw stuff in World
//-- LINE
void DrawLine(vec3 a, vec3 b, DrawContext::Data data);
void DrawLine(vec2 a, vec3 b, DrawContext::Data data, float az = -1.f);
void DrawLine(vec2 a, vec2 b, DrawContext::Data data, float az = -1.f, float bz = -1.f);
void DrawLine(vec3 a, vec3 b);
void DrawLine(vec2 a, vec3 b, float az = -1.f);
void DrawLine(vec2 a, vec2 b, float az = -1.f, float bz = -1.f);
//-- GIZMO
void DrawGizmo(vec3 pos, vec3 x, vec3 y, vec3 z, float size);
void DrawGizmo(vec2 pos, vec3 x, vec3 y, vec3 z, float size, float posz = -1.f);
//-- GRID
void DrawGrid(vec3 pos, vec3 x, vec3 y, vec3 z, float size, bool draw_3d=false);
//-- ARROW
void DrawArrow(vec3 a, vec3 b, vec2 s);
void DrawArrow(vec2 a, vec3 b, vec2 s, float az=-1.f);
void DrawArrow(vec2 a, vec2 b, vec2 s, float az=-1.f, float bz=-1.f);
void DrawArrow(vec3 a, vec3 b, vec3 s);
void DrawArrow(vec2 a, vec3 b, vec3 s, float az=-1.f);
void DrawArrow(vec2 a, vec2 b, vec3 s, float az=-1.f, float bz=-1.f);
void DrawArrow(vec3 a, vec3 b, vec3 s, DrawContext::Data data);
void DrawArrow(vec2 a, vec3 b, vec3 s, DrawContext::Data data, float az=-1.f);
void DrawArrow(vec2 a, vec2 b, vec3 s, DrawContext::Data data, float az=-1.f, float bz=-1.f);
//-- BOX
void DrawBox(box3 a);
void DrawBox(box2 a);
void DrawBox(box3 a, DrawContext::Data data);
void DrawBox(box2 a, DrawContext::Data data);
void DrawBox(vec3 a, vec3 b);
void DrawBox(vec2 a, vec2 b);
void DrawBox(vec2 a, float s);
void DrawBox(vec3 a, vec3 b, DrawContext::Data data);
void DrawBox(vec2 a, vec2 b, DrawContext::Data data);
void DrawBox(vec2 a, float s, DrawContext::Data data);
void DrawBox(box3 a, mat4 transform);
void DrawBox(box2 a, mat2 transform);
void DrawBox(box3 a, mat4 transform, DrawContext::Data data);
void DrawBox(box2 a, mat2 transform, DrawContext::Data data);
void DrawBox(vec3 a, vec3 b, mat4 transform);
void DrawBox(vec2 a, vec2 b, mat2 transform);
void DrawBox(vec2 a, float s, mat2 transform);
void DrawBox(vec3 a, vec3 b, mat4 transform, DrawContext::Data data);
void DrawBox(vec2 a, vec2 b, mat2 transform, DrawContext::Data data);
void DrawBox(vec2 a, float s, mat2 transform, DrawContext::Data data);
//-- CIRCLE
void DrawCircle(vec2 a, float s);
void DrawCircle(vec3 a, vec3 n);
void DrawCircle(vec2 a, vec2 s);
void DrawCircle(vec3 a, vec3 n, DrawContext::Data data);
void DrawCircle(vec2 a, vec2 s, DrawContext::Data data);
void DrawCircle(vec3 a, vec3 x, vec3 y);
void DrawCircle(vec2 a, vec2 x, vec2 y);
void DrawCircle(vec3 a, vec3 x, vec3 y, DrawContext::Data data);
void DrawCircle(vec2 a, vec2 x, vec2 y, DrawContext::Data data);
//-- SPHERE
void DrawSphere(vec3 a, float s);
void DrawSphere(vec3 a, float s, DrawContext::Data data);
void DrawSphere(vec3 a, vec3 x, vec3 y, vec3 z);
void DrawSphere(vec3 a, vec3 x, vec3 y, vec3 z, DrawContext::Data data);
//-- CAPSULE
void DrawCapsule(vec3 a, float s, vec3 h);
void DrawCapsule(vec3 a, float s, vec3 h, DrawContext::Data data);
void DrawCapsule(vec3 a, vec3 x, vec3 y, vec3 z, vec3 h);
void DrawCapsule(vec3 a, vec3 x, vec3 y, vec3 z, vec3 h, DrawContext::Data data);
//-- VIEW PROJ
void DrawViewProj(mat4 view_proj);
void DrawViewProj(mat4 view_proj, DrawContext::Data data);
void DrawViewProj(mat4 view, mat4 proj);
void DrawViewProj(mat4 view, mat4 proj, DrawContext::Data data);


} /* namespace Debug */ } /* namespace Debug */




+ 1
- 0
src/lol/engine-internal.h View File

@@ -36,4 +36,5 @@


#include <lol/public.h> #include <lol/public.h>
#include <lol/extras.h> #include <lol/extras.h>
#include <lol/legacy.h>



+ 1
- 0
src/lol/engine.h View File

@@ -31,4 +31,5 @@


#include <lol/public.h> #include <lol/public.h>
#include <lol/extras.h> #include <lol/extras.h>
#include <lol/legacy.h>



+ 1
- 1
src/lol/gpu/framebuffer.h View File

@@ -103,7 +103,7 @@ public:
TextureUniform GetTextureUniform() const; TextureUniform GetTextureUniform() const;
ivec2 GetSize() const; ivec2 GetSize() const;


class Image GetImage() const;
class image GetImage() const;


void Bind(); void Bind();
void Unbind(); void Unbind();


+ 4
- 0
src/lol/gpu/rendercontext.h View File

@@ -36,6 +36,8 @@ public:
void SetDepthMask(DepthMask mask); void SetDepthMask(DepthMask mask);
void SetCullMode(CullMode mode); void SetCullMode(CullMode mode);
void SetPolygonMode(PolygonMode mode); void SetPolygonMode(PolygonMode mode);
void SetScissorMode(ScissorMode mode);
void SetScissorRect(vec4 rect);


ibox2 GetViewport(); ibox2 GetViewport();
vec4 GetClearColor(); vec4 GetClearColor();
@@ -50,6 +52,8 @@ public:
DepthMask GetDepthMask(); DepthMask GetDepthMask();
CullMode GetCullMode(); CullMode GetCullMode();
PolygonMode GetPolygonMode(); PolygonMode GetPolygonMode();
ScissorMode GetScissorMode();
vec4 GetScissorRect();


private: private:
RenderContextData *m_data; RenderContextData *m_data;


+ 12
- 0
src/lol/gpu/renderer.h View File

@@ -123,6 +123,13 @@ enum class AlphaFunc : uint8_t
Always, Always,
}; };


/* A safe enum to indicate the depth mask. */
enum class ScissorMode : uint8_t
{
Disabled,
Enabled,
};

class Renderer class Renderer
{ {
private: private:
@@ -176,6 +183,11 @@ public:
void SetPolygonMode(PolygonMode mode); void SetPolygonMode(PolygonMode mode);
PolygonMode GetPolygonMode() const; PolygonMode GetPolygonMode() const;


void SetScissorMode(ScissorMode mode);
void SetScissorRect(vec4 rect);
ScissorMode GetScissorMode() const;
vec4 GetScissorRect() const;

private: private:
RendererData *m_data; RendererData *m_data;
}; };


+ 1
- 0
src/lol/image/all.h View File

@@ -15,5 +15,6 @@
#include <lol/image/pixel.h> #include <lol/image/pixel.h>
#include <lol/image/color.h> #include <lol/image/color.h>
#include <lol/image/image.h> #include <lol/image/image.h>
#include <lol/image/resource.h>
#include <lol/image/movie.h> #include <lol/image/movie.h>



+ 74
- 71
src/lol/image/image.h View File

@@ -1,7 +1,7 @@
// //
// Lol Engine // Lol Engine
// //
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
// //
// Lol Engine is free software. It comes without any warranty, to // Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it // the extent permitted by applicable law. You can redistribute it
@@ -13,7 +13,7 @@
#pragma once #pragma once


// //
// The Image class
// The image class
// --------------- // ---------------
// //


@@ -58,117 +58,120 @@ enum class EdiffAlgorithm : uint8_t
Lite, Lite,
}; };


//Image -----------------------------------------------------------------------
class Image
// image -----------------------------------------------------------------------
class image
{ {
public: public:
Image();
Image(ivec2 size);
image();
image(ivec2 size);
/* XXX: use of this ctor should be discouraged, as it will not /* XXX: use of this ctor should be discouraged, as it will not
* return information about a possible error. */ * return information about a possible error. */
Image(char const *path);
image(char const *path);


/* Rule of three */ /* Rule of three */
Image(Image const &other);
Image & operator =(Image other);
~Image();
image(image const &other);
image & operator =(image other);
~image();


void DummyFill(); void DummyFill();
void Copy(uint8_t* pixels, ivec2 const& size, PixelFormat fmt); void Copy(uint8_t* pixels, ivec2 const& size, PixelFormat fmt);
void Copy(Image const &other);
bool Load(char const *path);
bool Save(char const *path);
void Copy(image const &other);
bool load(char const *path);
bool save(char const *path);


/* Low level access */ /* Low level access */
ivec2 GetSize() const;
void SetSize(ivec2);
ivec2 size() const;
void resize(ivec2);


PixelFormat GetFormat() const;
void SetFormat(PixelFormat fmt);
PixelFormat format() const;
void set_format(PixelFormat fmt);


WrapMode GetWrapX() const; WrapMode GetWrapX() const;
WrapMode GetWrapY() const; WrapMode GetWrapY() const;
void SetWrap(WrapMode wrap_x, WrapMode wrap_y); void SetWrap(WrapMode wrap_x, WrapMode wrap_y);


/* Lock continuous arrays of pixels for writing */ /* Lock continuous arrays of pixels for writing */
template<PixelFormat T> typename PixelType<T>::type *Lock();
void *Lock();
void Unlock(void const *pixels);
template<PixelFormat T> typename PixelType<T>::type *lock();
void *lock();
void unlock(void const *pixels);


/* Lock 2D arrays of pixels for writing */ /* Lock 2D arrays of pixels for writing */
template<PixelFormat T> template<PixelFormat T>
inline array2d<typename PixelType<T>::type> &Lock2D()
inline array2d<typename PixelType<T>::type> &lock2d()
{ {
/* Hack: this indirection is needed because of a Visual Studio ICE */ /* Hack: this indirection is needed because of a Visual Studio ICE */
return *(array2d<typename PixelType<T>::type> *)Lock2DHelper(T);
return *(array2d<typename PixelType<T>::type> *)lock2d_helper(T);
} }


template<typename T> template<typename T>
void Unlock2D(array2d<T> const &);

/* XXX: this does not belong here */
bool RetrieveTiles(array<ivec2, ivec2>& tiles) const;
void unlock2d(array2d<T> const &);


/* Image processing kernels */ /* Image processing kernels */
static array2d<float> BayerKernel(ivec2 size);
static array2d<float> HalftoneKernel(ivec2 size);
static array2d<float> BlueNoiseKernel(ivec2 size,
ivec2 gsize = ivec2(7, 7));
static array2d<float> EdiffKernel(EdiffAlgorithm algorithm);
static array2d<float> NormalizeKernel(array2d<float> const &kernel);
static array2d<float> GaussianKernel(vec2 radius,
float angle = 0.f,
vec2 delta = vec2(0.f, 0.f));
struct kernel
{
kernel() = delete;

static array2d<float> normalize(array2d<float> const &kernel);

static array2d<float> bayer(ivec2 size);
static array2d<float> halftone(ivec2 size);
static array2d<float> blue_noise(ivec2 size,
ivec2 gsize = ivec2(7, 7));
static array2d<float> ediff(EdiffAlgorithm algorithm);
static array2d<float> gaussian(vec2 radius,
float angle = 0.f,
vec2 delta = vec2(0.f, 0.f));
};


/* Rendering */ /* Rendering */
bool RenderRandom(ivec2 size); bool RenderRandom(ivec2 size);


/* Resize and crop */ /* Resize and crop */
Image Resize(ivec2 size, ResampleAlgorithm algorithm);
Image Crop(ibox2 box) const;
image Resize(ivec2 size, ResampleAlgorithm algorithm);
image Crop(ibox2 box) const;


/* Image processing */ /* Image processing */
Image AutoContrast() const;
Image Brightness(float val) const;
Image Contrast(float val) const;
Image Convolution(array2d<float> const &kernel);
Image Dilate();
Image Erode();
Image Invert() const;
Image Median(ivec2 radii) const;
Image Median(array2d<float> const &kernel) const;
Image Sharpen(array2d<float> const &kernel);
Image Threshold(float val) const;
Image Threshold(vec3 val) const;
Image RGBToYUV() const;
Image YUVToRGB() const;
image AutoContrast() const;
image Brightness(float val) const;
image Contrast(float val) const;
image Convolution(array2d<float> const &kernel);
image Dilate();
image Erode();
image Invert() const;
image Median(ivec2 radii) const;
image Median(array2d<float> const &kernel) const;
image Sharpen(array2d<float> const &kernel);
image Threshold(float val) const;
image Threshold(vec3 val) const;
image RGBToYUV() const;
image YUVToRGB() const;


/* Dithering */ /* Dithering */
Image DitherRandom() const;
Image DitherEdiff(array2d<float> const &kernel,
ScanMode scan = ScanMode::Raster) const;
Image DitherOstromoukhov(ScanMode scan = ScanMode::Raster) const;
Image DitherOrdered(array2d<float> const &kernel) const;
Image DitherHalftone(float radius, float angle) const;
Image DitherDbs() const;
image dither_random() const;
image dither_ediff(array2d<float> const &kernel,
ScanMode scan = ScanMode::Raster) const;
image dither_ostromoukhov(ScanMode scan = ScanMode::Raster) const;
image dither_ordered(array2d<float> const &kernel) const;
image dither_halftone(float radius, float angle) const;
image dither_dbs() const;


/* Combine images */ /* Combine images */
static Image Merge(Image &src1, Image &src2, float alpha);
static Image Mean(Image &src1, Image &src2);
static Image Min(Image &src1, Image &src2);
static Image Max(Image &src1, Image &src2);
static Image Overlay(Image &src1, Image &src2);
static Image Screen(Image &src1, Image &src2);
static Image Multiply(Image &src1, Image &src2);
static Image Divide(Image &src1, Image &src2);
static Image Add(Image &src1, Image &src2);
static Image Sub(Image &src1, Image &src2);
static Image Difference(Image &src1, Image &src2);
static image Merge(image &src1, image &src2, float alpha);
static image Mean(image &src1, image &src2);
static image Min(image &src1, image &src2);
static image Max(image &src1, image &src2);
static image Overlay(image &src1, image &src2);
static image Screen(image &src1, image &src2);
static image Multiply(image &src1, image &src2);
static image Divide(image &src1, image &src2);
static image Add(image &src1, image &src2);
static image Sub(image &src1, image &src2);
static image Difference(image &src1, image &src2);


private: private:
void *Lock2DHelper(PixelFormat T);
void *lock2d_helper(PixelFormat T);


class ImageData *m_data;
class image_data *m_data;
}; };


} /* namespace lol */ } /* namespace lol */


+ 1
- 1
src/lol/image/movie.h View File

@@ -34,7 +34,7 @@ public:
#endif #endif
~Movie(); ~Movie();


void Feed(Image const &image);
void Feed(image const &image);


private: private:
class MovieData *m_data; class MovieData *m_data;


+ 74
- 0
src/lol/image/resource.h View File

@@ -0,0 +1,74 @@
//
// Lol Engine
//
// Copyright © 2016—2017 Sam Hocevar <sam@hocevar.net>
// Copyright © 2016—2017 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#pragma once

//
// The Resource class
// ---------------
//

#include <lol/math/arraynd.h>
#include <lol/math/vector.h>
#include <lol/math/geometry.h>
#include <lol/image/pixel.h>

namespace lol
{
//ResourceCodecData -----------------------------------------------------------
class ResourceCodecData
{
public:
ResourceCodecData() { }
virtual ~ResourceCodecData() { }
};

//ResourceImageData -----------------------------------------------------------
class ResourceImageData : public ResourceCodecData
{
public:
ResourceImageData(image* img)
{
m_image = img;
}

virtual ~ResourceImageData()
{
if (m_image)
delete m_image;
}

image* m_image = nullptr;
};

//ResourceImageData -----------------------------------------------------------
class ResourceTilesetData : public ResourceImageData
{
public:
ResourceTilesetData(image* img)
: ResourceImageData(img)
{ }

array<ivec2, ivec2> m_tiles;
};

//ResourceLoader --------------------------------------------------------------
class ResourceLoader
{
public:
static ResourceCodecData* Load(char const *path);
static bool Save(char const *path, ResourceCodecData* data);
};

} /* namespace lol */


+ 26
- 0
src/lol/legacy.h View File

@@ -0,0 +1,26 @@
//
// Lol Engine
//
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#pragma once

//
// Legacy types that will disappear one day
// ----------------------------------------
//

namespace lol
{

typedef image Image;

} /* namespace lol */


+ 9
- 7
src/lol/sys/file.h View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#pragma once #pragma once
@@ -81,7 +83,7 @@ public:
int WriteString(const String &buf); int WriteString(const String &buf);
long int GetPosFromStart(); long int GetPosFromStart();
void SetPosFromStart(long int pos); void SetPosFromStart(long int pos);
long int GetSize();
long int size();
long int GetModificationTime(); long int GetModificationTime();


private: private:


+ 5
- 5
src/lol/sys/threadtypes.h View File

@@ -124,16 +124,16 @@ public:
{ } { }


//Returns a dummy image, and start a job to load the image on a thread //Returns a dummy image, and start a job to load the image on a thread
Image* Load(const lol::String& path);
bool CheckStatus(Image* image);
image* Load(const lol::String& path);
bool CheckStatus(image* img);


protected: protected:
virtual void TreatResult(ThreadJob* result); virtual void TreatResult(ThreadJob* result);


private: private:
Image m_dummy_image;
map<String, Image*> m_images;
array<Image*> m_loaded_images;
image m_dummy_image;
map<String, image*> m_images;
array<image*> m_loaded_images;
}; };


} /* namespace lol */ } /* namespace lol */


+ 78
- 2
src/lolimgui.cpp View File

@@ -18,6 +18,72 @@


using namespace lol; using namespace lol;


//Imgui extension ---------------------------------------------------------------------------------
namespace ImGui
{
IMGUI_API void SetNextWindowDockingAndSize(const ImVec2& size, ImGuiSetDock dock, const ImVec2& padding, ImGuiSetCond cond)
{
SetNextWindowDockingAndSize(size, dock, ImVec4(vec2(padding).xyxy), cond);
}
IMGUI_API void SetNextWindowDockingAndSize(const ImVec2& size, ImGuiSetDock dock, const ImVec4& padding, ImGuiSetCond cond)
{
vec4 pdg = padding;
vec2 vsz = vec2(Video::GetSize());
vec2 ctr = pdg.xy + (((vsz - pdg.zw) - pdg.xy) * .5f);
vec2 pos = vec2();

switch (dock)
{
case ImGuiSetDock_Center: pos = vec2(ctr.x - (size.x * .5f), ctr.y - (size.y * .5f)); break;
case ImGuiSetDock_Top: pos = vec2(ctr.x - (size.x * .5f), pdg.y); break;
case ImGuiSetDock_TopRight: pos = vec2(vsz.x - (size.x + pdg.z), pdg.y); break;
case ImGuiSetDock_Right: pos = vec2(vsz.x - (size.x + pdg.z), ctr.y - (size.y * .5f)); break;
case ImGuiSetDock_BottomRight: pos = vec2(vsz.x - (size.x + pdg.z), vsz.y - (size.y + pdg.w)); break;
case ImGuiSetDock_Bottom: pos = vec2(ctr.x - (size.x * .5f), vsz.y - (size.y + pdg.w)); break;
case ImGuiSetDock_BottomLeft: pos = vec2(pdg.x, vsz.y - (size.y + pdg.w)); break;
case ImGuiSetDock_Left: pos = vec2(pdg.x, ctr.y - (size.y * .5f)); break;
case ImGuiSetDock_TopLeft: pos = vec2(pdg.x, pdg.y); break;
}

ImGui::SetNextWindowPos(pos, cond);
ImGui::SetNextWindowSize(size, cond);
}

IMGUI_API void SetNextWindowDocking(ImGuiSetDock dock, const ImVec2& padding, ImGuiSetCond cond)
{
SetNextWindowDocking(dock, ImVec4(vec2(padding).xyxy), cond);
}
IMGUI_API void SetNextWindowDocking(ImGuiSetDock dock, const ImVec4& padding, ImGuiSetCond cond)
{
vec2 vsz = vec2(Video::GetSize());
vec2 size = vec2();
vec2 pos = vec2();
vec4 pdg = padding;

switch (dock)
{
case ImGuiSetDock_Center: size = vsz - vec2(pdg.x + pdg.z, pdg.y + pdg.w); break;
case ImGuiSetDock_Top: size = vec2(vsz.x - (pdg.x + pdg.z), vsz.y *.5f - pdg.y); break;
case ImGuiSetDock_TopRight: size = vec2(vsz.x *.5f - pdg.z, vsz.y *.5f - pdg.y); break;
case ImGuiSetDock_Right: size = vec2(vsz.x *.5f - pdg.z, vsz.y - (pdg.y + pdg.w)); break;
case ImGuiSetDock_BottomRight: size = vec2(vsz.x *.5f - pdg.z, vsz.y *.5f - pdg.w); break;
case ImGuiSetDock_Bottom: size = vec2(vsz.x - (pdg.x + pdg.z), vsz.y *.5f - pdg.w); break;
case ImGuiSetDock_BottomLeft: size = vec2(vsz.x *.5f - pdg.x, vsz.y *.5f - pdg.w); break;
case ImGuiSetDock_Left: size = vec2(vsz.x *.5f - pdg.x, vsz.y - (pdg.y + pdg.w)); break;
case ImGuiSetDock_TopLeft: size = vec2(vsz.x *.5f - pdg.x, vsz.y *.5f - pdg.y); break;
}

SetNextWindowDockingAndSize(size, dock, padding, cond);
}

IMGUI_API float GetMainMenuBarHeight()
{
ImGuiContext& g = *GImGui;
return g.FontBaseSize + g.Style.FramePadding.y * 2.0f;
}
}

//LolImGui ----------------------------------------------------------------------------------------
#define Line(s) ((s) + "\n") #define Line(s) ((s) + "\n")


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -227,6 +293,8 @@ void LolImGui::TickGame(float seconds)
} }
} }


m_keyboard->SetTextInputActive(io.WantTextInput);

//Update text input //Update text input
String text = m_keyboard->GetText(); String text = m_keyboard->GetText();
//text.case_change(io.KeyShift); //text.case_change(io.KeyShift);
@@ -342,6 +410,7 @@ void LolImGui::RenderDrawListsMethod(ImDrawData* draw_data)
RenderContext rc; RenderContext rc;
rc.SetCullMode(CullMode::Disabled); rc.SetCullMode(CullMode::Disabled);
rc.SetDepthFunc(DepthFunc::Disabled); rc.SetDepthFunc(DepthFunc::Disabled);
rc.SetScissorMode(ScissorMode::Enabled);


m_shader->Bind(); m_shader->Bind();
for (int n = 0; n < draw_data->CmdListsCount; n++) for (int n = 0; n < draw_data->CmdListsCount; n++)
@@ -375,9 +444,14 @@ void LolImGui::RenderDrawListsMethod(ImDrawData* draw_data)
m_vdecl->SetStream(vbo, m_attribs[0], m_attribs[1], m_attribs[2]); m_vdecl->SetStream(vbo, m_attribs[0], m_attribs[1], m_attribs[2]);


const ImDrawIdx* idx_buffer_offset = 0; const ImDrawIdx* idx_buffer_offset = 0;
for (size_t cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
{ {
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[(int)cmd_i]; const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[(int)cmd_i];
TextureImage* image = (TextureImage*)pcmd->TextureId;
if (image) image->Bind();

rc.SetScissorRect(vec4(pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w));

#ifdef SHOW_IMGUI_DEBUG #ifdef SHOW_IMGUI_DEBUG
//----------------------------------------------------------------- //-----------------------------------------------------------------
//<Debug render> -------------------------------------------------- //<Debug render> --------------------------------------------------
@@ -419,11 +493,13 @@ void LolImGui::RenderDrawListsMethod(ImDrawData* draw_data)
//<\Debug render> ------------------------------------------------- //<\Debug render> -------------------------------------------------
//----------------------------------------------------------------- //-----------------------------------------------------------------
#endif //SHOW_IMGUI_DEBUG #endif //SHOW_IMGUI_DEBUG
Debug::DrawLine(vec2::zero, vec2::axis_x, Color::green);
//Debug::DrawLine(vec2::zero, vec2::axis_x /*, Color::green*/);


m_vdecl->DrawIndexedElements(MeshPrimitive::Triangles, pcmd->ElemCount, (const short*)idx_buffer_offset); m_vdecl->DrawIndexedElements(MeshPrimitive::Triangles, pcmd->ElemCount, (const short*)idx_buffer_offset);


idx_buffer_offset += pcmd->ElemCount; idx_buffer_offset += pcmd->ElemCount;

if (image) image->Unbind();
} }


m_vdecl->Unbind(); m_vdecl->Unbind();


+ 39
- 1
src/lolimgui.h View File

@@ -12,12 +12,50 @@


#pragma once #pragma once


#define IM_VEC2_CLASS_EXTRA ImVec2(const lol::vec2 &v) { x = v.x; y = v.y; } \
ImVec2(const lol::ivec2 &v) : ImVec2(lol::vec2(v)) { } \
operator lol::vec2() const { return lol::vec2(x, y); } \
operator lol::ivec2() const { return lol::ivec2(lol::vec2(x, y)); }

#define IM_VEC4_CLASS_EXTRA ImVec4(const lol::vec4 &v) { x = v.x; y = v.y; z = v.z; w = v.w; } \
ImVec4(const lol::ivec4 &v) : ImVec4(lol::vec4(v)) { } \
operator lol::vec4() const { return lol::vec4(x, y, z, w); } \
operator lol::ivec4() const { return lol::ivec4(lol::vec4(x, y, z, w)); }

#include "imgui.h" #include "imgui.h"


#undef IM_VEC2_CLASS_EXTRA
#undef IM_VEC4_CLASS_EXTRA

//Imgui extension ---------------------------------------------------------------------------------
typedef int ImGuiSetDock; // condition flags for Set*() // enum ImGuiSetCond_

enum ImGuiSetDock_
{
ImGuiSetDock_Center,
ImGuiSetDock_Top,
ImGuiSetDock_TopRight,
ImGuiSetDock_Right,
ImGuiSetDock_BottomRight,
ImGuiSetDock_Bottom,
ImGuiSetDock_BottomLeft,
ImGuiSetDock_Left,
ImGuiSetDock_TopLeft,
};

namespace ImGui
{
IMGUI_API void SetNextWindowDockingAndSize(const ImVec2& size, ImGuiSetDock dock, const ImVec2& padding, ImGuiSetCond cond = 0);
IMGUI_API void SetNextWindowDockingAndSize(const ImVec2& size, ImGuiSetDock dock, const ImVec4& padding = ImVec4(0, 0, 0, 0), ImGuiSetCond cond = 0);
IMGUI_API void SetNextWindowDocking(ImGuiSetDock dock, const ImVec2& padding, ImGuiSetCond cond = 0);
IMGUI_API void SetNextWindowDocking(ImGuiSetDock dock, const ImVec4& padding = ImVec4(0, 0, 0, 0), ImGuiSetCond cond = 0);
IMGUI_API float GetMainMenuBarHeight();
}

//LolImGui ----------------------------------------------------------------------------------------
namespace lol namespace lol
{ {


//LolImGui --------------------------------------------------------------------
class LolImGui : public Entity class LolImGui : public Entity
{ {
typedef Entity super; typedef Entity super;


+ 8
- 6
src/lolua/baselua.cpp View File

@@ -40,8 +40,9 @@ class LuaBaseData
int status = luaL_dostring(l, s.C()); int status = luaL_dostring(l, s.C());
if (status == 1) if (status == 1)
{ {
LuaString error; error.Get(l, -1);
msg::error("Lua error %s\n", error().C());
auto stack = LuaStack::Begin(l, -1);
auto error = stack.Get<String>();
msg::error("Lua error %s\n", error.C());
lua_pop(l, 1); lua_pop(l, 1);
} }
return status; return status;
@@ -53,8 +54,8 @@ class LuaBaseData
if (lua_isnoneornil(l, 1)) if (lua_isnoneornil(l, 1))
return LUA_ERRFILE; return LUA_ERRFILE;


LuaCharPtr var; var.Get(l, 1);
char const *filename = var;// lua_tostring(l, 1);
auto stack = LuaStack::Begin(l);
char const *filename = stack.Get<char const*>();
int status = LUA_ERRFILE; int status = LUA_ERRFILE;


File f; File f;
@@ -76,8 +77,9 @@ class LuaBaseData
msg::error("could not find Lua file %s\n", filename); msg::error("could not find Lua file %s\n", filename);
else if (status == 1) else if (status == 1)
{ {
LuaString error; error.Get(l, -1);
msg::error("Lua error %s\n", error().C());
stack.SetIndex(-1);
auto error = stack.Get<String>();
msg::error("Lua error %s\n", error.C());
lua_pop(l, 1); lua_pop(l, 1);
} }




+ 378
- 781
src/lolua/baselua.h
File diff suppressed because it is too large
View File


+ 18
- 13
src/platform/sdl/sdlinput.cpp View File

@@ -251,6 +251,13 @@ void SdlInputData::Tick(float seconds)


m_mouse->SetAxis(4, 0); m_mouse->SetAxis(4, 0);


# if !LOL_USE_OLD_SDL
if (m_keyboard->IsTextInputActive())
SDL_StartTextInput();
else
SDL_StopTextInput();
# endif

/* Handle keyboard and WM events */ /* Handle keyboard and WM events */
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
@@ -271,10 +278,10 @@ void SdlInputData::Tick(float seconds)
# endif # endif
{ {
//Lock management //Lock management
# if defined SDLOL_CapsLock && defined SDLOL_ScrollLock && defined SDLOL_NumLockClear
case SDLOL_CapsLock: case SDLOL_CapsLock:
case SDLOL_ScrollLock: case SDLOL_ScrollLock:
case SDLOL_NumLockClear: case SDLOL_NumLockClear:
# if defined SDLOL_CapsLock && defined SDLOL_ScrollLock && defined SDLOL_NumLockClear
//Update status on key down only //Update status on key down only
if (event.type == SDL_KEYDOWN) if (event.type == SDL_KEYDOWN)
{ {
@@ -306,19 +313,9 @@ void SdlInputData::Tick(float seconds)
# else # else
if (ScanCodeIsValid(sc)) if (ScanCodeIsValid(sc))
{ {
//Set key updates the corresponding key
m_keyboard->SetKey(sc, event.type == SDL_KEYDOWN); m_keyboard->SetKey(sc, event.type == SDL_KEYDOWN);
if (event.type == SDL_KEYDOWN
&& !m_keyboard->GetKey(SDLOL_RCtrl)
&& !m_keyboard->GetKey(SDLOL_LCtrl)
&& !m_keyboard->GetKey(SDLOL_RAlt)
&& !m_keyboard->GetKey(SDLOL_LAlt))
{
String str = ScanCodeToText(sc);
str.case_change(m_keyboard->GetKey(SDLOL_CapsLockStatus)
^ (m_keyboard->GetKey(SDLOL_RShift)
|| m_keyboard->GetKey(SDLOL_LShift)));
m_keyboard->AddText(str);
}

/* DEBUG STUFF /* DEBUG STUFF
msg::info("Repeat: 0x%02x : %s/%s/%s/%i\n", msg::info("Repeat: 0x%02x : %s/%s/%s/%i\n",
(int)m_keyboard, ScanCodeToText(sc).C(), ScanCodeToName(sc).C(), (int)m_keyboard, ScanCodeToText(sc).C(), ScanCodeToName(sc).C(),
@@ -334,6 +331,14 @@ void SdlInputData::Tick(float seconds)
} }
break; break;


# if !LOL_USE_OLD_SDL
//case SDL_TEXTEDITING: //TODO: handle that ?
case SDL_TEXTINPUT:
m_keyboard->AddText(event.text.text);
break;

# endif

# if LOL_USE_OLD_SDL # if LOL_USE_OLD_SDL
case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONUP:


+ 12
- 51
src/scene.cpp View File

@@ -168,10 +168,10 @@ private:
/* Old line API <P0, P1, COLOR, TIME, MASK> */ /* Old line API <P0, P1, COLOR, TIME, MASK> */
struct line_api struct line_api
{ {
float m_time, m_segment_size;
vec4 m_color;
//float m_duration, m_segment_size;
//vec4 m_color;
array<vec3, vec3, vec4, float, int, bool, bool> m_lines; array<vec3, vec3, vec4, float, int, bool, bool> m_lines;
int m_mask, m_debug_mask;
int /*m_mask,*/ m_debug_mask;
Shader *m_shader; Shader *m_shader;
VertexDeclaration *m_vdecl; VertexDeclaration *m_vdecl;
} }
@@ -241,11 +241,6 @@ Scene::Scene(ivec2 size)
data->m_line_api.m_vdecl = new VertexDeclaration(VertexStream<vec4,vec4>(VertexUsage::Position, VertexUsage::Color)); data->m_line_api.m_vdecl = new VertexDeclaration(VertexStream<vec4,vec4>(VertexUsage::Position, VertexUsage::Color));


data->m_line_api.m_debug_mask = 1; data->m_line_api.m_debug_mask = 1;

SetLineTime();
SetLineMask();
SetLineSegmentSize();
SetLineColor();
} }


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -533,56 +528,19 @@ void Scene::AddTile(TileSet *tileset, int id, mat4 model)
} }


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Scene::SetLineTime(float new_time)
{
ASSERT(!!data, "Trying to access a non-ready scene");

data->m_line_api.m_time = new_time;
}

void Scene::SetLineMask(int new_mask)
{
ASSERT(!!data, "Trying to access a non-ready scene");

data->m_line_api.m_mask = new_mask;
}

void Scene::SetLineSegmentSize(float new_segment_size)
{
ASSERT(!!data, "Trying to access a non-ready scene");

data->m_line_api.m_segment_size = new_segment_size;
}

void Scene::SetLineColor(vec4 new_color)
{
ASSERT(!!data, "Trying to access a non-ready scene");

data->m_line_api.m_color = new_color;
}

//-----------------------------------------------------------------------------
float Scene::GetLineSegmentSize()
{
ASSERT(!!data, "Trying to access a non-ready scene");

return data->m_line_api.m_segment_size;
}

vec4 Scene::GetLineColor()
void Scene::AddLine(vec3 a, vec3 b, vec4 color)
{ {
ASSERT(!!data, "Trying to access a non-ready scene"); ASSERT(!!data, "Trying to access a non-ready scene");


return data->m_line_api.m_color;
data->m_line_api.m_lines.push(a, b, color, -1.f, 0xFFFFFFFF, false, false);
} }


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void Scene::AddLine(vec3 a, vec3 b, vec4 color)
void Scene::AddLine(vec3 a, vec3 b, vec4 color, float duration, int mask)
{ {
ASSERT(!!data, "Trying to access a non-ready scene"); ASSERT(!!data, "Trying to access a non-ready scene");


data->m_line_api.m_lines.push(a, b, color,
data->m_line_api.m_time, data->m_line_api.m_mask, false, false);
data->m_line_api.m_lines.push(a, b, color, duration, mask, false, false);
} }


//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -765,7 +723,7 @@ void Scene::render_tiles() // XXX: rename to Blit()


if (!data->m_tile_api.m_shader) if (!data->m_tile_api.m_shader)
data->m_tile_api.m_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_tile)); data->m_tile_api.m_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_tile));
if (!data->m_tile_api.m_palette_shader)
if (!data->m_tile_api.m_palette_shader && data->m_tile_api.m_palettes.count())
data->m_tile_api.m_palette_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_palette)); data->m_tile_api.m_palette_shader = Shader::Create(LOLFX_RESOURCE_NAME(gpu_palette));


for (int p = 0; p < 2; p++) for (int p = 0; p < 2; p++)
@@ -791,7 +749,7 @@ void Scene::render_tiles() // XXX: rename to Blit()
shader->SetUniform(uni_mat, mat4(1.f)); shader->SetUniform(uni_mat, mat4(1.f));


uni_tex = shader->GetUniformLocation("u_texture"); uni_tex = shader->GetUniformLocation("u_texture");
uni_pal = data->m_tile_api.m_palette_shader->GetUniformLocation("u_palette");
uni_pal = data->m_tile_api.m_palette_shader ? data->m_tile_api.m_palette_shader->GetUniformLocation("u_palette") : ShaderUniform();
uni_texsize = shader->GetUniformLocation("u_texsize"); uni_texsize = shader->GetUniformLocation("u_texsize");


for (int buf = 0, i = 0, n; i < tiles.count(); i = n, buf += 2) for (int buf = 0, i = 0, n; i < tiles.count(); i = n, buf += 2)
@@ -851,6 +809,9 @@ void Scene::render_tiles() // XXX: rename to Blit()
tiles.empty(); tiles.empty();


shader->Unbind(); shader->Unbind();

if (!data->m_tile_api.m_palette_shader)
break;
} }


#if (defined LOL_USE_GLEW || defined HAVE_GL_2X) && !defined HAVE_GLES_2X #if (defined LOL_USE_GLEW || defined HAVE_GL_2X) && !defined HAVE_GLES_2X


+ 1
- 7
src/scene.h View File

@@ -234,14 +234,8 @@ public:
void AddTile(TileSet *tileset, int id, mat4 model); void AddTile(TileSet *tileset, int id, mat4 model);


public: public:
void SetLineTime(float new_time = -1.f);
void SetLineMask(int new_mask = 0xFFFFFFFF);
void SetLineSegmentSize(float new_segment_size = 1.f);
void SetLineColor(vec4 new_color = vec4(1.f));

float GetLineSegmentSize();
vec4 GetLineColor();
void AddLine(vec3 a, vec3 b, vec4 color); void AddLine(vec3 a, vec3 b, vec4 color);
void AddLine(vec3 a, vec3 b, vec4 color, float duration, int mask);


void AddLight(Light *light); void AddLight(Light *light);
array<Light *> const &GetLights(); array<Light *> const &GetLights();


+ 11
- 9
src/sys/file.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -182,7 +184,7 @@ class FileData
#endif #endif
} }


long int GetSize()
long int size()
{ {
#if __ANDROID__ #if __ANDROID__
return 0; return 0;
@@ -321,9 +323,9 @@ void File::SetPosFromStart(long int pos)
} }


//-- //--
long int File::GetSize()
long int File::size()
{ {
return m_data->GetSize();
return m_data->size();
} }


//-- //--


+ 7
- 0
src/sys/init.cpp View File

@@ -104,6 +104,13 @@ void init(int argc, char *argv[],
rootdir += "../src/"; /* FIXME: use SEPARATOR? */ rootdir += "../src/"; /* FIXME: use SEPARATOR? */
add_data_dir(rootdir); add_data_dir(rootdir);


/* This data dir is for submodule support stuff */
rootdir = solutiondir;
if (rootdir.count() && rootdir.last() != SEPARATOR)
rootdir += SEPARATOR;
rootdir += "./lol/src/"; /* FIXME: use SEPARATOR? */
add_data_dir(rootdir);

/* This data dir is for project-specific stuff */ /* This data dir is for project-specific stuff */
rootdir = projectdir; rootdir = projectdir;
if (rootdir.count() && rootdir.last() != SEPARATOR) if (rootdir.count() && rootdir.last() != SEPARATOR)


+ 2
- 2
src/sys/threadtypes.cpp View File

@@ -1,7 +1,7 @@
// //
// Lol Engine // Lol Engine
// //
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
// © 2014—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com> // © 2014—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
// //
// Lol Engine is free software. It comes without any warranty, to // Lol Engine is free software. It comes without any warranty, to
@@ -175,7 +175,7 @@ public:
protected: protected:
virtual bool DoWork() virtual bool DoWork()
{ {
return m_image.Load(m_path.C());
return m_image.load(m_path.C());
} }


String m_path; String m_path;


+ 7
- 7
src/t/image/image.cpp View File

@@ -1,7 +1,7 @@
// //
// Lol Engine — Unit tests // Lol Engine — Unit tests
// //
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
// //
// Lol Engine is free software. It comes without any warranty, to // Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it // the extent permitted by applicable law. You can redistribute it
@@ -23,13 +23,13 @@ lolunit_declare_fixture(image_test)
{ {
lolunit_declare_test(open_image) lolunit_declare_test(open_image)
{ {
Image image("data/gradient.png");
image img("data/gradient.png");


ivec2 size = image.GetSize();
lolunit_assert_equal(size.x, 256);
lolunit_assert_equal(size.y, 16);
ivec2 isize = img.size();
lolunit_assert_equal(isize.x, 256);
lolunit_assert_equal(isize.y, 16);


u8vec4 *data = image.Lock<PixelFormat::RGBA_8>();
u8vec4 *data = img.lock<PixelFormat::RGBA_8>();
lolunit_assert(data); lolunit_assert(data);


lolunit_assert_equal((int)data[0].r, 0x00); lolunit_assert_equal((int)data[0].r, 0x00);
@@ -40,7 +40,7 @@ lolunit_declare_fixture(image_test)
lolunit_assert_equal((int)data[255].g, 0xff); lolunit_assert_equal((int)data[255].g, 0xff);
lolunit_assert_equal((int)data[255].b, 0xff); lolunit_assert_equal((int)data[255].b, 0xff);


image.Unlock(data);
img.unlock(data);
} }
}; };




+ 40
- 20
src/textureimage.cpp View File

@@ -1,11 +1,13 @@
// //
// Lol Engine
// Lol Engine
// //
// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
// //


#include <lol/engine-internal.h> #include <lol/engine-internal.h>
@@ -44,10 +46,10 @@ TextureImage::TextureImage(char const *path)
Init(path); Init(path);
} }


TextureImage::TextureImage(char const *path, Image* image)
TextureImage::TextureImage(char const *path, image* img)
: m_data(GetNewData()) : m_data(GetNewData())
{ {
Init(path, image);
Init(path, img);
} }


TextureImage::~TextureImage() TextureImage::~TextureImage()
@@ -57,16 +59,28 @@ TextureImage::~TextureImage()


void TextureImage::Init(char const *path) void TextureImage::Init(char const *path)
{ {
Init(path, new Image(path));
Init(path, ResourceLoader::Load(path));
} }


void TextureImage::Init(char const *path, Image* image)
void TextureImage::Init(char const *path, ResourceCodecData* loaded_data)
{
//Load image if available
auto image_data = dynamic_cast<ResourceImageData*>(loaded_data);
if (image_data != nullptr)
{
Init(path, new image(*image_data->m_image));
}

delete image_data;
}

void TextureImage::Init(char const *path, image* img)
{ {
m_data->m_name = String("<textureimage> ") + path; m_data->m_name = String("<textureimage> ") + path;


m_data->m_texture = nullptr; m_data->m_texture = nullptr;
m_data->m_image = image;
m_data->m_image_size = m_data->m_image->GetSize();
m_data->m_image = img;
m_data->m_image_size = m_data->m_image->size();
m_data->m_texture_size = ivec2(PotUp(m_data->m_image_size.x), m_data->m_texture_size = ivec2(PotUp(m_data->m_image_size.x),
PotUp(m_data->m_image_size.y)); PotUp(m_data->m_image_size.y));


@@ -99,13 +113,13 @@ void TextureImage::TickDraw(float seconds, Scene &scene)
m_data->m_texture = nullptr; m_data->m_texture = nullptr;
} }


PixelFormat format = m_data->m_image->GetFormat();
PixelFormat format = m_data->m_image->format();
int planes = BytesPerPixel(format); int planes = BytesPerPixel(format);


int w = m_data->m_texture_size.x; int w = m_data->m_texture_size.x;
int h = m_data->m_texture_size.y; int h = m_data->m_texture_size.y;


uint8_t *pixels = (uint8_t *)m_data->m_image->Lock();
uint8_t *pixels = (uint8_t *)m_data->m_image->lock();
bool resized = false; bool resized = false;
if (w != m_data->m_image_size.x || h != m_data->m_image_size.y) if (w != m_data->m_image_size.x || h != m_data->m_image_size.y)
{ {
@@ -117,6 +131,7 @@ void TextureImage::TickDraw(float seconds, Scene &scene)
pixels = tmp; pixels = tmp;
resized = false; resized = false;
} }
/* FIXME: no unlock? */


m_data->m_texture = new Texture(ivec2(w, h), format); m_data->m_texture = new Texture(ivec2(w, h), format);
m_data->m_texture->SetData(pixels); m_data->m_texture->SetData(pixels);
@@ -134,12 +149,12 @@ char const *TextureImage::GetName()
return m_data->m_name.C(); return m_data->m_name.C();
} }


void TextureImage::UpdateTexture(Image* image)
void TextureImage::UpdateTexture(image* img)
{ {
m_data->m_image = image;
m_data->m_image_size = m_data->m_image->GetSize();
m_data->m_image = img;
m_data->m_image_size = m_data->m_image->size();
m_data->m_texture_size = ivec2(PotUp(m_data->m_image_size.x), m_data->m_texture_size = ivec2(PotUp(m_data->m_image_size.x),
PotUp(m_data->m_image_size.y));
PotUp(m_data->m_image_size.y));
} }


Texture * TextureImage::GetTexture() Texture * TextureImage::GetTexture()
@@ -152,16 +167,21 @@ Texture const * TextureImage::GetTexture() const
return m_data->m_texture; return m_data->m_texture;
} }


Image * TextureImage::GetImage()
image * TextureImage::GetImage()
{ {
return m_data->m_image; return m_data->m_image;
} }


Image const * TextureImage::GetImage() const
image const * TextureImage::GetImage() const
{ {
return m_data->m_image; return m_data->m_image;
} }


ivec2 TextureImage::GetImageSize() const
{
return m_data->m_image_size;
}

ivec2 TextureImage::GetTextureSize() const ivec2 TextureImage::GetTextureSize() const
{ {
return m_data->m_texture_size; return m_data->m_texture_size;


+ 8
- 5
src/textureimage.h View File

@@ -18,6 +18,7 @@
// zero, the texture is freed. // zero, the texture is freed.
// //


#include <lol/image/resource.h>
#include <lol/image/image.h> #include <lol/image/image.h>
#include <lol/gpu/texture.h> #include <lol/gpu/texture.h>


@@ -38,12 +39,13 @@ protected:


public: public:
TextureImage(char const *path); TextureImage(char const *path);
TextureImage(char const *path, Image* image);
TextureImage(char const *path, image* img);
virtual ~TextureImage(); virtual ~TextureImage();


protected: protected:
void Init(char const *path); void Init(char const *path);
virtual void Init(char const *path, Image* image);
virtual void Init(char const *path, ResourceCodecData* loaded_data);
virtual void Init(char const *path, image* img);


protected: protected:
virtual void TickDraw(float seconds, Scene &scene); virtual void TickDraw(float seconds, Scene &scene);
@@ -52,11 +54,12 @@ public:
/* Inherited from Entity */ /* Inherited from Entity */
virtual char const *GetName(); virtual char const *GetName();


void UpdateTexture(Image* image);
void UpdateTexture(image* img);
Texture * GetTexture(); Texture * GetTexture();
Texture const * GetTexture() const; Texture const * GetTexture() const;
Image * GetImage();
Image const * GetImage() const;
image * GetImage();
image const * GetImage() const;
ivec2 GetImageSize() const;
ivec2 GetTextureSize() const; ivec2 GetTextureSize() const;
void Bind(); void Bind();
void Unbind(); void Unbind();


+ 4
- 4
src/tiler.h View File

@@ -30,10 +30,10 @@ public:
static TileSet *Register(char const *path, ivec2 size, ivec2 count); static TileSet *Register(char const *path, ivec2 size, ivec2 count);
static TileSet *Register(String const &path); static TileSet *Register(String const &path);
static TileSet *Register(char const *path); static TileSet *Register(char const *path);
static TileSet *Register(String const &path, Image* image, ivec2 size, ivec2 count);
static TileSet *Register(char const *path, Image* image, ivec2 size, ivec2 count);
static TileSet *Register(String const &path, Image* image);
static TileSet *Register(char const *path, Image* image);
static TileSet *Register(String const &path, image* img, ivec2 size, ivec2 count);
static TileSet *Register(char const *path, image* img, ivec2 size, ivec2 count);
static TileSet *Register(String const &path, image* img);
static TileSet *Register(char const *path, image* img);
static void Deregister(TileSet *); static void Deregister(TileSet *);


private: private:


+ 52
- 11
src/tileset.cpp View File

@@ -46,25 +46,25 @@ protected:
*/ */


TileSet::TileSet(char const *path) TileSet::TileSet(char const *path)
: TextureImage(path),
: m_tileset_data(new TileSetData()),
m_palette(nullptr),
TextureImage(path)
{
}

TileSet::TileSet(char const *path, Image* image)
: TextureImage(path, image),
m_tileset_data(new TileSetData()), m_tileset_data(new TileSetData()),
m_palette(nullptr) m_palette(nullptr)
{ {
array<ivec2, ivec2> tiles;
if (m_data->m_image->RetrieveTiles(tiles))
for (int i = 0; i < tiles.count(); i++)
define_tile(ibox2(tiles[0].m1, tiles[0].m1 + tiles[0].m2));
} }


TileSet::TileSet(char const *path, Image* image)
: TextureImage(path, image),
TileSet::TileSet(char const *path, Image* image, array<ivec2, ivec2>& tiles)
: TextureImage(path, image),
m_tileset_data(new TileSetData()), m_tileset_data(new TileSetData()),
m_palette(nullptr) m_palette(nullptr)
{ {
array<ivec2, ivec2> tiles;
if (m_data->m_image->RetrieveTiles(tiles))
for (int i = 0; i < tiles.count(); i++)
define_tile(ibox2(tiles[0].m1, tiles[0].m1 + tiles[0].m2));
define_tile(tiles);
} }


TileSet::TileSet(char const *path, ivec2 size, ivec2 count) TileSet::TileSet(char const *path, ivec2 size, ivec2 count)
@@ -118,6 +118,20 @@ TileSet::~TileSet()
delete m_tileset_data; delete m_tileset_data;
} }


void TileSet::Init(char const *path, ResourceCodecData* loaded_data)
{
//Load tileset if available
auto tileset_data = dynamic_cast<ResourceTilesetData*>(loaded_data);
if (tileset_data != nullptr)
{
define_tile(tileset_data->m_tiles);
}

m_data->m_name = String("<tileset> ") + path;

super::Init(path, loaded_data);
}

void TileSet::Init(char const *path, Image* image) void TileSet::Init(char const *path, Image* image)
{ {
super::Init(path, image); super::Init(path, image);
@@ -132,6 +146,11 @@ char const *TileSet::GetName()
} }


//New methods ----------------------------------------------------------------- //New methods -----------------------------------------------------------------
void TileSet::clear_all()
{
m_tileset_data->m_tiles.empty();
}

int TileSet::define_tile(ibox2 rect) int TileSet::define_tile(ibox2 rect)
{ {
m_tileset_data->m_tiles.push(rect, m_tileset_data->m_tiles.push(rect,
@@ -152,6 +171,18 @@ void TileSet::define_tile(ivec2 count)
} }
} }


void TileSet::define_tile(array<ibox2>& tiles)
{
for (int i = 0; i < tiles.count(); i++)
define_tile(tiles[i]);
}

void TileSet::define_tile(array<ivec2, ivec2>& tiles)
{
for (int i = 0; i < tiles.count(); i++)
define_tile(ibox2(tiles[i].m1, tiles[i].m1 + tiles[i].m2));
}

int TileSet::GetTileCount() const int TileSet::GetTileCount() const
{ {
return m_tileset_data->m_tiles.count(); return m_tileset_data->m_tiles.count();
@@ -162,6 +193,16 @@ ivec2 TileSet::GetTileSize(int tileid) const
return m_tileset_data->m_tiles[tileid].m1.extent(); return m_tileset_data->m_tiles[tileid].m1.extent();
} }


ibox2 TileSet::GetTilePixel(int tileid) const
{
return m_tileset_data->m_tiles[tileid].m1;
}

box2 TileSet::GetTileTexel(int tileid) const
{
return m_tileset_data->m_tiles[tileid].m2;
}

//Palette --------------------------------------------------------------------- //Palette ---------------------------------------------------------------------
void TileSet::SetPalette(TileSet* palette) void TileSet::SetPalette(TileSet* palette)
{ {


+ 10
- 3
src/tileset.h View File

@@ -42,26 +42,33 @@ class TileSet : public TextureImage


public: public:
TileSet(char const *path); TileSet(char const *path);
TileSet(char const *path, Image* image);
TileSet(char const *path, image* img);
TileSet(char const *path, image* img, array<ivec2, ivec2>& tiles);


/* Old style: path to PNG file */ /* Old style: path to PNG file */
TileSet(char const *path, ivec2 size, ivec2 count); TileSet(char const *path, ivec2 size, ivec2 count);
TileSet(char const *path, Image* image, ivec2 size, ivec2 count);
TileSet(char const *path, image* img, ivec2 size, ivec2 count);


virtual ~TileSet(); virtual ~TileSet();


protected: protected:
virtual void Init(char const *path, Image* image);
virtual void Init(char const *path, ResourceCodecData* loaded_data);
virtual void Init(char const *path, image* img);


public: public:
/* Inherited from Entity */ /* Inherited from Entity */
virtual char const *GetName(); virtual char const *GetName();


/* New methods */ /* New methods */
void clear_all();
int define_tile(ibox2 rect); int define_tile(ibox2 rect);
void define_tile(ivec2 count); void define_tile(ivec2 count);
void define_tile(array<ibox2>& tiles);
void define_tile(array<ivec2, ivec2>& tiles);
int GetTileCount() const; int GetTileCount() const;
ivec2 GetTileSize(int tileid) const; ivec2 GetTileSize(int tileid) const;
ibox2 GetTilePixel(int tileid) const;
box2 GetTileTexel(int tileid) const;


void SetPalette(TileSet* palette); void SetPalette(TileSet* palette);
TileSet* GetPalette(); TileSet* GetPalette();


+ 6
- 4
src/utils.h View File

@@ -61,6 +61,12 @@ template< class T > inline int GetRandom(array<T> src)


// Gets the value for the given enum type. // Gets the value for the given enum type.
template<class T> inline T FindValue(const char* name) template<class T> inline T FindValue(const char* name)
{
auto str = String(name);
return FindValue<T>(str);
}

template<class T> inline T FindValue(String const& name)
{ {
String n = name; String n = name;
n.to_lower(); n.to_lower();
@@ -72,10 +78,6 @@ template<class T> inline T FindValue(const char* name)
} }
return T::Max; return T::Max;
} }
template<class T> inline T FindValue(String const& name)
{
return FindValue<T>(name.C());
}


} /* namespace lol */ } /* namespace lol */



Loading…
Cancel
Save