Implements drawing textures with transformation.
This commit is contained in:
parent
5f59ba420a
commit
b6c35e84a9
2
Font.h
2
Font.h
@ -54,7 +54,7 @@ namespace gj {
|
|||||||
|
|
||||||
for (int y = 0; y < h; ++y) {
|
for (int y = 0; y < h; ++y) {
|
||||||
for (int x = 0; x < w; ++x) {
|
for (int x = 0; x < w; ++x) {
|
||||||
*dst = *src*1./UINT8_MAX;
|
*dst = static_cast<float>(*src*1./UINT8_MAX);
|
||||||
++dst, ++src;
|
++dst, ++src;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
Game.h
28
Game.h
@ -1,10 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "iDrawable.h"
|
#include "iDrawable.h"
|
||||||
#include "iWritable.h"
|
#include "iWritable.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
|
||||||
namespace gj {
|
namespace gj {
|
||||||
@ -19,25 +21,45 @@ class Game : public iDrawable, public iWritable {
|
|||||||
Game& operator=(Game&&) = delete;
|
Game& operator=(Game&&) = delete;
|
||||||
Game& operator=(const Game&) = delete;
|
Game& operator=(const Game&) = delete;
|
||||||
|
|
||||||
Game(uint32_t w, uint32_t h) : w_(w), h_(h), logger_(h) {
|
Game(iAllocator* alloc, uint32_t w, uint32_t h) :
|
||||||
logger_.Print(L"こんにちは");
|
alloc_(alloc), w_(w), h_(h), logger_(h), test_(Colorbuffer(alloc, 1, 1)) {
|
||||||
|
Colorbuffer temp(alloc_, 5, 5);
|
||||||
|
float* ptr = temp.ptr();
|
||||||
|
for (size_t i = 0; i < 25; ++i) ptr[i] = i%2*.3+.7;
|
||||||
|
test_ = Texture(std::move(temp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update() {
|
void Update() {
|
||||||
static int i = 0;
|
static int i = 0;
|
||||||
++i;
|
++i;
|
||||||
logger_.Print(L"すべての人類は死滅する: "+std::to_wstring(i));
|
if (i%100 == 0) logger_.Print(L"すべての人類は死滅する: "+std::to_wstring(i));
|
||||||
|
|
||||||
|
double t = i%200/200.;
|
||||||
|
t = 1 - t;
|
||||||
|
|
||||||
|
mat3 m = mat3{ {.2, 0, 0},{0, .2, 0},{0, 0, 1} };
|
||||||
|
|
||||||
|
const double s = sin(3.14*2*t*t*t), c = cos(3.14*2*t*t*t);
|
||||||
|
m = ::linalg::mul(mat3{{c, -s, 0,}, {s, c, 0}, {0, 0, 1}}, m);
|
||||||
|
m = ::linalg::mul(mat3{{ 1, 0, 0,}, {0, 1, 0}, {(1 - t * t * t * 2) * .6, 0, 1}}, m);
|
||||||
|
m = ::linalg::mul(mat3{ {1, 0, 0},{0, 16/9., 0},{0, 0, 1} }, m);
|
||||||
|
test_.SetMatrix(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw(Colorbuffer& fb) const override {
|
void Draw(Colorbuffer& fb) const override {
|
||||||
|
test_.Draw(fb);
|
||||||
}
|
}
|
||||||
void Write(Textbuffer& fb) const override {
|
void Write(Textbuffer& fb) const override {
|
||||||
logger_.Write(fb);
|
logger_.Write(fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
iAllocator* alloc_;
|
||||||
|
|
||||||
uint32_t w_, h_;
|
uint32_t w_, h_;
|
||||||
Logger logger_;
|
Logger logger_;
|
||||||
|
|
||||||
|
Texture test_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -158,6 +158,7 @@
|
|||||||
<ClInclude Include="LinearAllocator.h" />
|
<ClInclude Include="LinearAllocator.h" />
|
||||||
<ClInclude Include="StackAllocator.h" />
|
<ClInclude Include="StackAllocator.h" />
|
||||||
<ClInclude Include="Text.h" />
|
<ClInclude Include="Text.h" />
|
||||||
|
<ClInclude Include="Texture.h" />
|
||||||
<ClInclude Include="thirdparty\linalg.h" />
|
<ClInclude Include="thirdparty\linalg.h" />
|
||||||
<ClInclude Include="thirdparty\stb_truetype.h" />
|
<ClInclude Include="thirdparty\stb_truetype.h" />
|
||||||
<ClInclude Include="Win32Console.h" />
|
<ClInclude Include="Win32Console.h" />
|
||||||
|
@ -77,5 +77,8 @@
|
|||||||
<ClInclude Include="iWritable.h">
|
<ClInclude Include="iWritable.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Texture.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
2
Logger.h
2
Logger.h
@ -34,7 +34,7 @@ class Logger : public iWritable, public iLogger {
|
|||||||
lines_.erase(lines_.begin());
|
lines_.erase(lines_.begin());
|
||||||
--n;
|
--n;
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
lines_[i].SetPosition(0, i);
|
lines_[i].SetPosition(0, static_cast<int32_t>(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
117
Texture.h
Normal file
117
Texture.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "thirdparty/linalg.h"
|
||||||
|
|
||||||
|
#include "iDrawable.h"
|
||||||
|
#include "Rasterbuffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace gj {
|
||||||
|
|
||||||
|
|
||||||
|
class Texture : public DrawableBase {
|
||||||
|
public:
|
||||||
|
Texture() = delete;
|
||||||
|
Texture(Texture&&) = default;
|
||||||
|
Texture(const Texture&) = default;
|
||||||
|
|
||||||
|
Texture& operator=(Texture&&) = default;
|
||||||
|
Texture& operator=(const Texture&) = default;
|
||||||
|
|
||||||
|
Texture(Colorbuffer&& src) : src_(std::move(src)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Draw(Colorbuffer& fb) const override {
|
||||||
|
const int32_t w = static_cast<int32_t>(fb.width());
|
||||||
|
const int32_t h = static_cast<int32_t>(fb.height());
|
||||||
|
|
||||||
|
const int32_t srcw = static_cast<int32_t>(src_.width());
|
||||||
|
const int32_t srch = static_cast<int32_t>(src_.height());
|
||||||
|
|
||||||
|
vec3 p[4] = {
|
||||||
|
{ -1, 1, 1 },
|
||||||
|
{ -1, -1, 1 },
|
||||||
|
{ 1, -1, 1 },
|
||||||
|
{ 1, 1, 1 },
|
||||||
|
};
|
||||||
|
for (size_t i = 0; i < 4; ++i) {
|
||||||
|
p[i] = ::linalg::mul(mat_, p[i]);
|
||||||
|
}
|
||||||
|
const double pl = std::min({p[0].x, p[1].x, p[2].x, p[3].x})-.1;
|
||||||
|
const double pr = std::max({p[0].x, p[1].x, p[2].x, p[3].x})+.1;
|
||||||
|
const double pu = std::max({p[0].y, p[1].y, p[2].y, p[3].y})+.1;
|
||||||
|
const double pb = std::min({p[0].y, p[1].y, p[2].y, p[3].y})-.1;
|
||||||
|
const double pw = pr - pl;
|
||||||
|
const double ph = pu - pb;
|
||||||
|
|
||||||
|
const int32_t pli = static_cast<int32_t>((pl + 1) / 2 * w);
|
||||||
|
const int32_t pri = static_cast<int32_t>((pr + 1) / 2 * w);
|
||||||
|
const int32_t pui = static_cast<int32_t>((pu + 1) / 2 * h);
|
||||||
|
const int32_t pbi = static_cast<int32_t>((pb + 1) / 2 * h);
|
||||||
|
const int32_t pwi = pri - pli;
|
||||||
|
const int32_t phi = pui - pbi;
|
||||||
|
|
||||||
|
vec3 q[4] = {
|
||||||
|
{ pl, pu, 1 },
|
||||||
|
{ pl, pb, 1 },
|
||||||
|
{ pr, pb, 1 },
|
||||||
|
{ pr, pu, 1 },
|
||||||
|
};
|
||||||
|
for (size_t i = 0; i < 4; ++i) {
|
||||||
|
q[i] = ::linalg::mul(invmat_, q[i]);
|
||||||
|
}
|
||||||
|
const double ql = std::min({q[0].x, q[1].x, q[2].x, q[3].x});
|
||||||
|
const double qr = std::max({q[0].x, q[1].x, q[2].x, q[3].x});
|
||||||
|
const double qu = std::max({q[0].y, q[1].y, q[2].y, q[3].y});
|
||||||
|
const double qb = std::min({q[0].y, q[1].y, q[2].y, q[3].y});
|
||||||
|
|
||||||
|
const double qldx = q[0].x - q[1].x;
|
||||||
|
const double qrdx = q[3].x - q[2].x;
|
||||||
|
const double qldy = q[0].y - q[1].y;
|
||||||
|
const double qrdy = q[3].y - q[2].y;
|
||||||
|
|
||||||
|
const float* src = src_.ptr();
|
||||||
|
float* dst = fb.ptr();
|
||||||
|
for (int32_t y = 0; y <= phi; ++y) {
|
||||||
|
const double yfr = y*1. / phi;
|
||||||
|
|
||||||
|
const double lxf = qldx * yfr + q[1].x;
|
||||||
|
const double rxf = qrdx * yfr + q[2].x;
|
||||||
|
const double ax = (rxf - lxf) / pwi;
|
||||||
|
|
||||||
|
const double lyf = qldy * yfr + q[1].y;
|
||||||
|
const double ryf = qrdy * yfr + q[2].y;
|
||||||
|
const double ay = (ryf - lyf) / pwi;
|
||||||
|
|
||||||
|
for (int32_t x = 0; x <= pwi; ++x) {
|
||||||
|
const double xf = lxf + ax*x;
|
||||||
|
const double yf = lyf + ay*x;
|
||||||
|
if (std::abs(xf) > 1 || std::abs(yf) > 1) continue;
|
||||||
|
|
||||||
|
int32_t srcx = static_cast<int32_t>((xf+1)/2 * srcw);
|
||||||
|
int32_t srcy = srch - 1 - static_cast<int32_t>((yf+1)/2 * srch);
|
||||||
|
if (srcx >= srcw) srcx = srcw - 1;
|
||||||
|
if (srcy >= srch) srcy = srch - 1;
|
||||||
|
|
||||||
|
const int32_t dstx = pli + x;
|
||||||
|
const int32_t dsty = (h-pui) + y;
|
||||||
|
if (dstx < 0 || w <= dstx) continue;
|
||||||
|
if (dsty < 0 || h <= dsty) continue;
|
||||||
|
|
||||||
|
dst[dstx + w*dsty] = src[srcx + srcw*srcy];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSource(Colorbuffer&& src) {
|
||||||
|
src_ = std::move(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Colorbuffer src_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -53,7 +53,7 @@ class Win32Console : public iConsole {
|
|||||||
SetConsoleScreenBufferInfoEx(screen_, &size);
|
SetConsoleScreenBufferInfoEx(screen_, &size);
|
||||||
|
|
||||||
ShowWindow(win_, FALSE);
|
ShowWindow(win_, FALSE);
|
||||||
SetWindowLong(win_, GWL_STYLE, GetWindowLong(win_, GWL_STYLE) & ~WS_SIZEBOX);
|
SetWindowLong(win_, GWL_STYLE, GetWindowLong(win_, GWL_STYLE) & ~(WS_SIZEBOX | WS_MAXIMIZEBOX));
|
||||||
}
|
}
|
||||||
~Win32Console() {
|
~Win32Console() {
|
||||||
alive_.store(false);
|
alive_.store(false);
|
||||||
|
@ -34,11 +34,11 @@ public:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
using UniquePtr = std::unique_ptr<T, Deleter<T>>;
|
using UniquePtr = std::unique_ptr<T, Deleter<T>>;
|
||||||
|
|
||||||
iAllocator(iAllocator&&) = delete;
|
iAllocator(iAllocator&&) = default;
|
||||||
iAllocator(const iAllocator&) = delete;
|
iAllocator(const iAllocator&) = default;
|
||||||
|
|
||||||
iAllocator& operator=(iAllocator&&) = delete;
|
iAllocator& operator=(iAllocator&&) = default;
|
||||||
iAllocator& operator=(const iAllocator&) = delete;
|
iAllocator& operator=(const iAllocator&) = default;
|
||||||
|
|
||||||
iAllocator() = default;
|
iAllocator() = default;
|
||||||
|
|
||||||
|
14
iDrawable.h
14
iDrawable.h
@ -8,8 +8,8 @@
|
|||||||
namespace gj {
|
namespace gj {
|
||||||
|
|
||||||
|
|
||||||
using mat4 = ::linalg::mat<double, 4, 4>;
|
using mat3 = ::linalg::mat<double, 3, 3>;
|
||||||
using vec4 = ::linalg::vec<double, 4>;
|
using vec3 = ::linalg::vec<double, 3>;
|
||||||
|
|
||||||
class iDrawable {
|
class iDrawable {
|
||||||
public:
|
public:
|
||||||
@ -36,15 +36,17 @@ class DrawableBase : public iDrawable {
|
|||||||
DrawableBase& operator=(DrawableBase&&) = default;
|
DrawableBase& operator=(DrawableBase&&) = default;
|
||||||
DrawableBase& operator=(const DrawableBase&) = default;
|
DrawableBase& operator=(const DrawableBase&) = default;
|
||||||
|
|
||||||
void setMatrix(const mat4& m) {
|
void SetMatrix(const mat3& m) {
|
||||||
setMatrix(mat4(m));
|
SetMatrix(mat3(m));
|
||||||
}
|
}
|
||||||
void setMatrix(mat4&& m) {
|
void SetMatrix(mat3&& m) {
|
||||||
mat_ = std::move(m);
|
mat_ = std::move(m);
|
||||||
|
invmat_ = ::linalg::inverse(mat_);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mat4 mat_ = ::linalg::identity;
|
mat3 mat_ = ::linalg::identity;
|
||||||
|
mat3 invmat_ = ::linalg::identity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
5
main.cc
5
main.cc
@ -24,8 +24,7 @@ int main() {
|
|||||||
gj::Win32Console console(&alloc, kWidth, kHeight);
|
gj::Win32Console console(&alloc, kWidth, kHeight);
|
||||||
console.Show();
|
console.Show();
|
||||||
|
|
||||||
gj::Game game(kWidth, kHeight);
|
gj::Game game(&alloc, kWidth, kHeight);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
game.Update();
|
game.Update();
|
||||||
{
|
{
|
||||||
@ -40,6 +39,6 @@ int main() {
|
|||||||
game.Write(fb);
|
game.Write(fb);
|
||||||
console.SwapTextbuffer();
|
console.SwapTextbuffer();
|
||||||
}
|
}
|
||||||
Sleep(100);
|
Sleep(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user