696 lines
19 KiB
C++
696 lines
19 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <iostream>
|
|
|
|
#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
|
|
#include <SDL3/SDL.h>
|
|
#include <SDL3/SDL_main.h>
|
|
#include <SDL3/SDL_opengl.h>
|
|
|
|
#include "math/dvc_vector2.h"
|
|
#include "math/dvc_vector3.h"
|
|
|
|
#include "dvr_triangle.h"
|
|
#include "dvr_canvas.h"
|
|
#include "rasterizer/dvc_rasterizer_triangle.h"
|
|
|
|
using namespace davinci;
|
|
|
|
enum MouseAction
|
|
{
|
|
MT_NULL,
|
|
MT_FIRST_LINE,
|
|
MT_TRIANGLE,
|
|
|
|
MT_PAN,
|
|
};
|
|
|
|
const float MIN_SCALE = 4.f;
|
|
const float MAX_SCALE = 120.f;
|
|
const float TRIANGLE_BORDER_WIDTH = 1.5f;
|
|
const float ACTION_WIDTH = 1.f;
|
|
const fVector3 GRID_BORDER_COLOR = fVector3(0.f, 0.f, 0.f);
|
|
const fVector3 GRID_CROSS_COLOR = fVector3(0.1f, 0.1f, 0.1f);
|
|
const fVector3 TRIANGLE_BORDER_COLOR = fVector3(0.f, 0.f, 0.f);
|
|
const fVector3 ACTION_COLOR = fVector3(1.f, 0.f, 0.f);
|
|
const int32_t CANVAS_WIDTH = 512;
|
|
const int32_t CANVAS_HEIGHT = 256;
|
|
|
|
int32_t g_viewWidth = 2048;
|
|
int32_t g_viewHeight = 1440;
|
|
float32_t g_scale = MAX_SCALE/2.0f;
|
|
int32_t g_lbCorner_x = 20;
|
|
int32_t g_lbCorner_y = 20;
|
|
int32_t g_nDrawGridLevel = 0; //0:all 1:fine+coarse+tile 2:coarse+tile 3: tile
|
|
int32_t g_screenMousePosX = 0, g_screenMousePosY = 0;
|
|
float32_t g_mousePosX, g_mousePosY;
|
|
bool g_bSnapMode = true;
|
|
float g_fSnapSize = 0.25f;
|
|
MouseAction g_currentAction = MT_NULL;
|
|
bool g_bDrawExtension = false;
|
|
|
|
int32_t g_nStartPanX, g_nStartPanY;
|
|
int32_t g_nPanX, g_nPanY;
|
|
|
|
Triangle g_currentTriangle(INT_MAX, ACTION_COLOR);
|
|
TriangleArray g_allTriangles;
|
|
Canvas g_canvas;
|
|
AntiAliasingTech g_aaTech = AntiAliasingTech::AA_None;
|
|
|
|
SDL_Window* g_window = NULL;
|
|
SDL_Renderer* g_renderer = NULL;
|
|
|
|
#define trans_w2s_x(x) ((float32_t)(x) * g_scale + g_lbCorner_x + g_nPanX)
|
|
#define trans_w2s_y(y) ((float32_t)g_viewHeight - ((float32_t)(y) * g_scale + g_lbCorner_y + g_nPanY))
|
|
|
|
#define trans_s2w_x(x) ((float32_t)(x - g_lbCorner_x - g_nPanX) / g_scale)
|
|
#define trans_s2w_y(y) ((float32_t)(g_viewHeight - y - g_lbCorner_y - g_nPanY) / g_scale)
|
|
|
|
void _onFramebufferSize(int32_t w, int32_t h)
|
|
{
|
|
g_viewWidth = w;
|
|
g_viewHeight = h > 0 ? h : 1;
|
|
|
|
if (g_scale < 10.f) g_nDrawGridLevel = 3;
|
|
else if (g_scale < 20.f) g_nDrawGridLevel = 2;
|
|
else if (g_scale < 50.f) g_nDrawGridLevel = 1;
|
|
else g_nDrawGridLevel = 0;
|
|
}
|
|
|
|
static void _drawGrid(void)
|
|
{
|
|
int32_t horLength = (int32_t)floorf(g_viewWidth / g_scale);
|
|
int32_t verLength = (int32_t)floorf(g_viewHeight / g_scale);
|
|
|
|
// draw canvas background
|
|
SDL_FRect rect;
|
|
rect.x = trans_w2s_x(0);
|
|
rect.y = trans_w2s_y(0);
|
|
rect.w = g_canvas.width() * g_scale;
|
|
rect.h = -g_canvas.height() * g_scale;
|
|
SDL_SetRenderDrawColorFloat(g_renderer, 255, 255, 255, SDL_ALPHA_OPAQUE_FLOAT);
|
|
SDL_RenderFillRect(g_renderer, &rect);
|
|
|
|
fVector3 lineColor[] = { fVector3(0.f, 0.f, 0.f), fVector3(0.5f, 0.5f, 0.5f), fVector3(0.7f,0.7f,0.7f), fVector3(0.9f, 0.9f,0.9f) };
|
|
|
|
// Horizontal lines
|
|
for (int32_t i = (int32_t)trans_s2w_y(0); ; i--)
|
|
{
|
|
if (i > g_canvas.height()) continue;
|
|
if (i < 0) break;
|
|
|
|
float32_t screenY = trans_w2s_y(i);
|
|
if (screenY < 0) continue;
|
|
if (screenY > g_viewHeight) break;
|
|
|
|
int32_t level = 3;
|
|
|
|
if (i % 64 == 0)level = 0;
|
|
else if (i % 16 == 0) level = 1;
|
|
else if (i % 4 == 0) level = 2;
|
|
if (level > 3 - g_nDrawGridLevel) continue;
|
|
|
|
SDL_SetRenderDrawColorFloat(g_renderer, lineColor[level].x, lineColor[level].y, lineColor[level].z, SDL_ALPHA_OPAQUE_FLOAT);
|
|
SDL_RenderLine(g_renderer, trans_w2s_x(0), screenY, trans_w2s_x(g_canvas.width()), screenY);
|
|
}
|
|
|
|
// Vertical lines
|
|
for (int32_t j = (int32_t)trans_s2w_x(0); ; j++)
|
|
{
|
|
if (j < 0) continue;
|
|
if (j > g_canvas.width()) break;
|
|
|
|
float32_t screenX = trans_w2s_x(j);
|
|
if (screenX < 0) continue;
|
|
if (screenX > g_viewWidth) break;
|
|
|
|
int32_t level = 3;
|
|
|
|
if (j % 64 == 0)level = 0;
|
|
else if (j % 16 == 0) level = 1;
|
|
else if (j % 4 == 0) level = 2;
|
|
if (level > 3 - g_nDrawGridLevel) continue;
|
|
|
|
SDL_SetRenderDrawColorFloat(g_renderer, lineColor[level].x, lineColor[level].y, lineColor[level].z, SDL_ALPHA_OPAQUE_FLOAT);
|
|
SDL_RenderLine(g_renderer, screenX, trans_w2s_y(0), screenX, trans_w2s_y(g_canvas.height()));
|
|
}
|
|
}
|
|
|
|
void _drawTriangleBorder(const Triangle& triangle, const fVector3& color, float lineWidth)
|
|
{
|
|
SDL_SetRenderDrawColorFloat(g_renderer, color[0], color[1], color[2], SDL_ALPHA_OPAQUE_FLOAT);
|
|
|
|
SDL_FPoint points[4] = {
|
|
{trans_w2s_x(triangle.m_p0.x), trans_w2s_y(triangle.m_p0.y)},
|
|
{trans_w2s_x(triangle.m_p1.x), trans_w2s_y(triangle.m_p1.y)},
|
|
{trans_w2s_x(triangle.m_p2.x), trans_w2s_y(triangle.m_p2.y)},
|
|
{trans_w2s_x(triangle.m_p0.x), trans_w2s_y(triangle.m_p0.y)}
|
|
};
|
|
SDL_RenderLines(g_renderer, points, 4);
|
|
}
|
|
|
|
void _drawCanvasPixel()
|
|
{
|
|
SDL_SetRenderDrawBlendMode(g_renderer, SDL_BLENDMODE_BLEND);
|
|
|
|
for (int32_t y = 0; y < g_canvas.height(); y++)
|
|
{
|
|
for (int32_t x = 0; x < g_canvas.width(); x++)
|
|
{
|
|
const Canvas::Pixel& pixel = g_canvas.pixel(x, y);
|
|
if (pixel.fragementID < 0) continue;
|
|
|
|
SDL_FRect rect;
|
|
rect.x = trans_w2s_x(x);
|
|
rect.y = trans_w2s_y(y);
|
|
rect.w = g_scale;
|
|
rect.h = -g_scale;
|
|
SDL_SetRenderDrawColorFloat(g_renderer, pixel.color.x, pixel.color.y, pixel.color.z, pixel.alpha);
|
|
SDL_RenderFillRect(g_renderer, &rect);
|
|
}
|
|
}
|
|
}
|
|
|
|
void _drawTriangles(void)
|
|
{
|
|
_drawCanvasPixel();
|
|
|
|
for (const auto& triangle : g_allTriangles)
|
|
{
|
|
_drawTriangleBorder(triangle, TRIANGLE_BORDER_COLOR, TRIANGLE_BORDER_WIDTH);
|
|
}
|
|
}
|
|
|
|
void _drawSegmentInAABB(const fVector2& p0, const fVector2& p1, float xMin, float xMax, float yMin, float yMax)
|
|
{
|
|
float32_t dx = p1.x - p0.x;
|
|
float32_t dy = p1.y - p0.y;
|
|
if (std::abs(dx) > std::abs(dy))
|
|
{
|
|
float _ymin = (xMin - p0.x) * dy / dx + p0.y;
|
|
float _ymax = (xMax - p0.x) * dy / dx + p0.y;
|
|
|
|
if (dx > 0) {
|
|
SDL_RenderLine(g_renderer, trans_w2s_x(xMin), trans_w2s_y(_ymin), trans_w2s_x(p0.x), trans_w2s_y(p0.y) );
|
|
SDL_RenderLine(g_renderer, trans_w2s_x(p1.x), trans_w2s_y(p1.y), trans_w2s_x(xMax), trans_w2s_y(_ymax) );
|
|
}
|
|
else {
|
|
SDL_RenderLine(g_renderer, trans_w2s_x(xMin), trans_w2s_y(_ymin), trans_w2s_x(p1.x), trans_w2s_y(p1.y));
|
|
SDL_RenderLine(g_renderer, trans_w2s_x(p0.x), trans_w2s_y(p0.y), trans_w2s_x(xMax), trans_w2s_y(_ymax));
|
|
}
|
|
}
|
|
else {
|
|
float _xmin = (yMin - p0.y) * dx / dy + p0.x;
|
|
float _xmax = (yMax - p0.y) * dx / dy + p0.x;
|
|
|
|
if (dy > 0) {
|
|
SDL_RenderLine(g_renderer, trans_w2s_x(_xmin), trans_w2s_y(yMin), trans_w2s_x(p0.x), trans_w2s_y(p0.y));
|
|
SDL_RenderLine(g_renderer, trans_w2s_x(p1.x), trans_w2s_y(p1.y), trans_w2s_x(_xmax), trans_w2s_y(yMax));
|
|
}
|
|
else {
|
|
SDL_RenderLine(g_renderer, trans_w2s_x(_xmin), trans_w2s_y(yMin), trans_w2s_x(p1.x), trans_w2s_y(p1.y));
|
|
SDL_RenderLine(g_renderer, trans_w2s_x(p0.x), trans_w2s_y(p0.y), trans_w2s_x(_xmax), trans_w2s_y(yMax));
|
|
}
|
|
}
|
|
}
|
|
|
|
void _drawAction(void)
|
|
{
|
|
if (g_bDrawExtension) {
|
|
SDL_SetRenderDrawColorFloat(g_renderer, ACTION_COLOR.x/2.f, ACTION_COLOR.y/2.f, ACTION_COLOR.z/2.f, SDL_ALPHA_OPAQUE_FLOAT);
|
|
|
|
_drawSegmentInAABB(g_currentTriangle.m_p0.xy(), g_currentTriangle.m_p1.xy(),
|
|
0, (float)g_canvas.width(), 0, (float)g_canvas.height());
|
|
_drawSegmentInAABB(g_currentTriangle.m_p1.xy(), g_currentTriangle.m_p2.xy(),
|
|
0, (float)g_canvas.width(), 0, (float)g_canvas.height());
|
|
_drawSegmentInAABB(g_currentTriangle.m_p2.xy(), g_currentTriangle.m_p0.xy(),
|
|
0, (float)g_canvas.width(), 0, (float)g_canvas.height());
|
|
}
|
|
|
|
SDL_SetRenderDrawColorFloat(g_renderer, ACTION_COLOR.x, ACTION_COLOR.y, ACTION_COLOR.z, SDL_ALPHA_OPAQUE_FLOAT);
|
|
switch (g_currentAction)
|
|
{
|
|
case MT_FIRST_LINE:
|
|
{
|
|
SDL_RenderLine(g_renderer,
|
|
trans_w2s_x(g_currentTriangle.m_p0.x), trans_w2s_y(g_currentTriangle.m_p0.y),
|
|
trans_w2s_x(g_currentTriangle.m_p1.x), trans_w2s_y(g_currentTriangle.m_p1.y)
|
|
);
|
|
}
|
|
break;
|
|
|
|
case MT_TRIANGLE:
|
|
{
|
|
_drawTriangleBorder(g_currentTriangle, ACTION_COLOR, ACTION_WIDTH);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void _drawPixelSample()
|
|
{
|
|
const float crossLength = 0.2f;
|
|
|
|
//sample cross
|
|
if (g_nDrawGridLevel < 3)
|
|
{
|
|
SDL_SetRenderDrawColorFloat(g_renderer, GRID_CROSS_COLOR.x, GRID_CROSS_COLOR.y, GRID_CROSS_COLOR.z, SDL_ALPHA_OPAQUE_FLOAT);
|
|
|
|
for (int32_t i = 0; i < g_canvas.height(); i++)
|
|
{
|
|
for (int32_t j = 0; j < g_canvas.width(); j++)
|
|
{
|
|
const Canvas::Pixel& pixel = g_canvas.pixel(j, i);
|
|
if (pixel.fragementID < 0) continue;
|
|
|
|
if (g_aaTech == AntiAliasingTech::AA_None)
|
|
{
|
|
SDL_RenderLine(g_renderer,
|
|
trans_w2s_x(j + 0.5f - crossLength), trans_w2s_y(i + 0.5f - crossLength),
|
|
trans_w2s_x(j + 0.5f + crossLength), trans_w2s_y(i + 0.5f + crossLength)
|
|
);
|
|
|
|
SDL_RenderLine(g_renderer,
|
|
trans_w2s_x(j + 0.5f - crossLength), trans_w2s_y(i + 0.5f + crossLength),
|
|
trans_w2s_x(j + 0.5f + crossLength), trans_w2s_y(i + 0.5f - crossLength)
|
|
);
|
|
}
|
|
else if (g_aaTech == AntiAliasingTech::AA_MSAA_2X2)
|
|
{
|
|
for (int32_t ii = 0; ii < 2; ii++)
|
|
{
|
|
for (int32_t jj = 0; jj < 2; jj++)
|
|
{
|
|
int32_t maskOffset = ii * 2 + jj;
|
|
if (((pixel.mask >> maskOffset) & 1) == 0U) continue;
|
|
|
|
SDL_RenderLine(g_renderer,
|
|
trans_w2s_x(j + 0.25f + jj * 0.5f - crossLength / 2), trans_w2s_y(i + 0.25f + ii * 0.5f - crossLength / 2),
|
|
trans_w2s_x(j + 0.25f + jj * 0.5f + crossLength / 2), trans_w2s_y(i + 0.25f + ii * 0.5f + crossLength / 2)
|
|
);
|
|
|
|
SDL_RenderLine(g_renderer,
|
|
trans_w2s_x(j + 0.25f + jj * 0.5f - crossLength / 2), trans_w2s_y(i + 0.25f + ii * 0.5f + crossLength / 2),
|
|
trans_w2s_x(j + 0.25f + jj * 0.5f + crossLength / 2), trans_w2s_y(i + 0.25f + ii * 0.5f - crossLength / 2)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
else if (g_aaTech == AntiAliasingTech::AA_MSAA_4X4)
|
|
{
|
|
for (int32_t ii = 0; ii < 4; ii++)
|
|
{
|
|
for (int32_t jj = 0; jj < 4; jj++)
|
|
{
|
|
int32_t maskOffset = ii * 4 + jj;
|
|
if (((pixel.mask >> maskOffset) & 1) == 0U) continue;
|
|
|
|
SDL_RenderLine(g_renderer,
|
|
trans_w2s_x(j + 0.125f + jj * 0.25f - crossLength/4), trans_w2s_y(i + 0.125f + ii * 0.25f - crossLength/4),
|
|
trans_w2s_x(j + 0.125f + jj * 0.25f + crossLength/4), trans_w2s_y(i + 0.125f + ii * 0.25f + crossLength/4)
|
|
);
|
|
|
|
SDL_RenderLine(g_renderer,
|
|
trans_w2s_x(j + 0.125f + jj * 0.25f - crossLength/4), trans_w2s_y(i + 0.125f + ii * 0.25f + crossLength/4),
|
|
trans_w2s_x(j + 0.125f + jj * 0.25f + crossLength/4), trans_w2s_y(i + 0.125f + ii * 0.25f - crossLength/4)
|
|
);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//for (int32_t i = (int32_t)trans_s2w_y(0); ; i--)
|
|
//{
|
|
// if (i > g_canvas.height()) continue;
|
|
// if (i < 0) break;
|
|
|
|
//}
|
|
|
|
//float crossLength = 0.2f;
|
|
//for (int i = 0; i < verLength; i++)
|
|
//{
|
|
// for (int j = 0; j < horLength; j++)
|
|
// {
|
|
// SDL_RenderLine(g_renderer,
|
|
// trans_w2s_x(j + 0.5f - crossLength), trans_w2s_y(i + 0.5f - crossLength),
|
|
// trans_w2s_x(j + 0.5f + crossLength), trans_w2s_y(i + 0.5f + crossLength)
|
|
// );
|
|
|
|
// SDL_RenderLine(g_renderer,
|
|
// trans_w2s_x(j + 0.5f - crossLength), trans_w2s_y(i + 0.5f + crossLength),
|
|
// trans_w2s_x(j + 0.5f + crossLength), trans_w2s_y(i + 0.5f - crossLength)
|
|
// );
|
|
// }
|
|
//}
|
|
}
|
|
}
|
|
|
|
void _drawMouseCursor(void)
|
|
{
|
|
if (g_bSnapMode && g_currentAction!=MT_PAN)
|
|
{
|
|
SDL_SetRenderDrawColorFloat(g_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE_FLOAT);
|
|
|
|
const float32_t CursorLength = 10.f / g_scale;
|
|
|
|
SDL_RenderLine(g_renderer,
|
|
trans_w2s_x(g_mousePosX - CursorLength), trans_w2s_y(g_mousePosY),
|
|
trans_w2s_x(g_mousePosX + CursorLength), trans_w2s_y(g_mousePosY)
|
|
);
|
|
|
|
SDL_RenderLine(g_renderer,
|
|
trans_w2s_x(g_mousePosX), trans_w2s_y(g_mousePosY - CursorLength),
|
|
trans_w2s_x(g_mousePosX), trans_w2s_y(g_mousePosY + CursorLength)
|
|
);
|
|
}
|
|
}
|
|
|
|
void _drawDebugText()
|
|
{
|
|
const float32_t TextHeight = (float32_t)SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE*1.5;
|
|
|
|
SDL_SetRenderDrawColorFloat(g_renderer, 0, 0, 0, SDL_ALPHA_OPAQUE_FLOAT);
|
|
|
|
SDL_SetRenderScale(g_renderer, 1.5f, 1.5f);
|
|
SDL_RenderDebugText(g_renderer, 20, 20, "Press 'S' to turn on/off snap mode.");
|
|
SDL_RenderDebugText(g_renderer, 20, 20 + TextHeight, "Click 'LeftMouseButton' to draw new triangle.");
|
|
|
|
SDL_SetRenderScale(g_renderer, 1.0f, 1.0f);
|
|
}
|
|
|
|
inline float _snapPosition(float pos)
|
|
{
|
|
if (g_fSnapSize < 1) {
|
|
int invSize = (int)(1.f / g_fSnapSize);
|
|
|
|
float x_f = floorf(((pos - floorf(pos)) * invSize + 0.5f)) / (float)invSize;
|
|
return floorf(pos) + x_f;
|
|
}
|
|
else {
|
|
return floorf(pos - floorf(pos / g_fSnapSize) + 0.5f) * g_fSnapSize;
|
|
}
|
|
}
|
|
|
|
void _onMouseMove(float32_t x, float32_t y)
|
|
{
|
|
g_screenMousePosX = (int32_t)x;
|
|
g_screenMousePosY = (int32_t)y;
|
|
g_mousePosX = trans_s2w_x(x);
|
|
g_mousePosY = trans_s2w_y(y);
|
|
|
|
if (g_bSnapMode && g_currentAction != MT_PAN)
|
|
{
|
|
g_mousePosX = _snapPosition(g_mousePosX);
|
|
g_mousePosY = _snapPosition(g_mousePosY);
|
|
}
|
|
|
|
switch (g_currentAction)
|
|
{
|
|
case MT_FIRST_LINE:
|
|
{
|
|
g_currentTriangle.m_p1 = fVector3(g_mousePosX, g_mousePosY, 0);
|
|
}
|
|
break;
|
|
|
|
case MT_TRIANGLE:
|
|
{
|
|
g_currentTriangle.m_p2 = fVector3(g_mousePosX, g_mousePosY, 0);
|
|
g_currentTriangle.build(g_canvas.width(), g_canvas.height(), g_aaTech);
|
|
|
|
g_canvas.update(g_aaTech, g_allTriangles, &g_currentTriangle);
|
|
}
|
|
break;
|
|
|
|
case MT_PAN:
|
|
{
|
|
g_nPanX = g_screenMousePosX - g_nStartPanX;
|
|
g_nPanY = -(g_screenMousePosY - g_nStartPanY);
|
|
}
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
void _onMouseWheel(float32_t x, float32_t y)
|
|
{
|
|
g_scale += (float)y * g_scale * 0.05f;
|
|
if (g_scale < MIN_SCALE) g_scale = MIN_SCALE;
|
|
if (g_scale > MAX_SCALE) g_scale = MAX_SCALE;
|
|
|
|
_onFramebufferSize(g_viewWidth, g_viewHeight);
|
|
}
|
|
|
|
void _onKeyDown(SDL_Keycode key)
|
|
{
|
|
if (SDLK_S == key)
|
|
{
|
|
g_bSnapMode = !g_bSnapMode;
|
|
}
|
|
else if (SDLK_A == key)
|
|
{
|
|
if (g_currentAction == MT_NULL)
|
|
{
|
|
if (g_aaTech == AntiAliasingTech::AA_None)
|
|
{
|
|
g_aaTech = AntiAliasingTech::AA_MSAA_2X2;
|
|
}
|
|
else if (g_aaTech == AntiAliasingTech::AA_MSAA_2X2)
|
|
{
|
|
g_aaTech = AntiAliasingTech::AA_MSAA_4X4;
|
|
}
|
|
else if (g_aaTech == AntiAliasingTech::AA_MSAA_4X4)
|
|
{
|
|
g_aaTech = AntiAliasingTech::AA_None;
|
|
}
|
|
for (auto& triangle : g_allTriangles)
|
|
{
|
|
triangle.build(g_canvas.width(), g_canvas.height(), g_aaTech);
|
|
}
|
|
g_canvas.update(g_aaTech, g_allTriangles);
|
|
}
|
|
}
|
|
else if (SDLK_ESCAPE == key)
|
|
{
|
|
g_currentAction = MT_NULL;
|
|
g_bDrawExtension = false;
|
|
}
|
|
}
|
|
|
|
void _onMouseDown(Uint8 button)
|
|
{
|
|
if (button == SDL_BUTTON_MIDDLE)
|
|
{
|
|
if (g_currentAction == MT_NULL)
|
|
{
|
|
g_currentAction = MT_PAN;
|
|
|
|
g_nStartPanX = g_screenMousePosX;
|
|
g_nStartPanY = g_screenMousePosY;
|
|
g_nPanX = g_nPanY = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void _onMouseUp(Uint8 button)
|
|
{
|
|
if (button == SDL_BUTTON_LEFT)
|
|
{
|
|
switch (g_currentAction)
|
|
{
|
|
case MT_NULL:
|
|
{
|
|
g_currentTriangle.m_p0 = g_currentTriangle.m_p1 = fVector3(g_mousePosX, g_mousePosY, 0);
|
|
g_currentAction = MT_FIRST_LINE;
|
|
g_bDrawExtension = false;
|
|
}
|
|
break;
|
|
|
|
case MT_FIRST_LINE:
|
|
{
|
|
g_currentTriangle.m_p1 = g_currentTriangle.m_p2 = fVector3(g_mousePosX, g_mousePosY, 0);
|
|
g_currentAction = MT_TRIANGLE;
|
|
g_bDrawExtension = true;
|
|
}
|
|
break;
|
|
|
|
case MT_TRIANGLE:
|
|
{
|
|
g_currentTriangle.m_p2 = fVector3(g_mousePosX, g_mousePosY, 0);
|
|
g_currentAction = MT_NULL;
|
|
|
|
//build triangle
|
|
Triangle newTriangle(Triangle::nextID(), Triangle::randomColor());
|
|
newTriangle.m_p0 = g_currentTriangle.m_p0;
|
|
newTriangle.m_p1 = g_currentTriangle.m_p1;
|
|
newTriangle.m_p2 = g_currentTriangle.m_p2;
|
|
newTriangle.build(g_canvas.width(), g_canvas.height(), g_aaTech);
|
|
g_allTriangles.push_back(std::move(newTriangle));
|
|
g_canvas.update(g_aaTech, g_allTriangles);
|
|
g_bDrawExtension = true;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (button== SDL_BUTTON_RIGHT)
|
|
{
|
|
g_currentAction = MT_NULL;
|
|
g_bDrawExtension = false;
|
|
g_canvas.update(g_aaTech, g_allTriangles);
|
|
}
|
|
else if (button == SDL_BUTTON_MIDDLE)
|
|
{
|
|
if (g_currentAction == MT_PAN)
|
|
{
|
|
g_currentAction = MT_NULL;
|
|
g_lbCorner_x += g_nPanX;
|
|
g_lbCorner_y += g_nPanY;
|
|
g_nPanX = g_nPanY = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void _buildDemoTriangles(void)
|
|
{
|
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/cc627092(v=vs.85).aspx
|
|
|
|
float32_t triangleData[] = {
|
|
1, 2,7, 4,5, 2,
|
|
5, 2,7, 4,8, 1,
|
|
8, 1,7, 4,9.5f, 2.5f,
|
|
1, 7,6, 6,2, 4,
|
|
5.25f, 6.75f, 6.25f, 7.75,6.25f, 6.75f,
|
|
6.5f, 5.5f,7.5f, 7.5f,7.5f, 6.5f,
|
|
11.5f, 1.5f,11.5f, 3.5f, 12.5f, 2.5f,
|
|
13.5f, 0.5f,13.5f, 2.5f, 15.5f, 2.5f,
|
|
13.5f, 0.5f,15.5f, 2.5f, 15.5f, 0.5f,
|
|
13.5f, 6.5f,14.5f, 5.5f, 14.5f, 3.5f,
|
|
13.5f, 6.5f,15, 8, 14.5f, 5.5f,
|
|
9.5f, 0.5f, 10.5f, 0.5f,9.5f, -1.5f,
|
|
7.6f, 5.5f,9.75f, 7.25f, 11.6f, 5.5f,
|
|
7.6f, 5.5f, 11.6f, 5.5f, 9.5f, 2.6f,
|
|
};
|
|
|
|
size_t triangleCounts = sizeof(triangleData) / (6 * sizeof(float));
|
|
for (size_t i = 0; i < triangleCounts; i++) {
|
|
|
|
fVector3 p0(triangleData[i * 6 + 0], triangleData[i * 6 + 1], 0.f);
|
|
fVector3 p1(triangleData[i * 6 + 2], triangleData[i * 6 + 3], 0.f);
|
|
fVector3 p2(triangleData[i * 6 + 4], triangleData[i * 6 + 5], 0.f);
|
|
|
|
Triangle triangle(Triangle::nextID(), Triangle::randomColor());
|
|
triangle.m_p0 = p0;
|
|
triangle.m_p1 = p1;
|
|
triangle.m_p2 = p2;
|
|
triangle.build(g_canvas.width(), g_canvas.height(), g_aaTech);
|
|
g_allTriangles.emplace_back(triangle);
|
|
}
|
|
}
|
|
|
|
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[])
|
|
{
|
|
// Setup SDL
|
|
SDL_SetAppMetadata("Davinci Rasterization Test Program", "1.0", "com.thecodeway.davinci");
|
|
|
|
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
|
|
{
|
|
printf("Error: SDL_Init(): %s\n", SDL_GetError());
|
|
return SDL_APP_FAILURE;
|
|
}
|
|
|
|
if (!SDL_CreateWindowAndRenderer("Davinci Rasterization Test Program", g_viewWidth, g_viewHeight, SDL_WINDOW_RESIZABLE, &g_window, &g_renderer))
|
|
{
|
|
SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
|
|
return SDL_APP_FAILURE;
|
|
}
|
|
|
|
g_canvas.reset(CANVAS_WIDTH, CANVAS_HEIGHT);
|
|
|
|
_onFramebufferSize(g_viewWidth, g_viewHeight);
|
|
_buildDemoTriangles();
|
|
|
|
g_canvas.update(g_aaTech, g_allTriangles);
|
|
|
|
return SDL_APP_CONTINUE; /* carry on with the program! */
|
|
}
|
|
|
|
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
|
|
SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
|
|
{
|
|
switch (event->type)
|
|
{
|
|
case SDL_EVENT_QUIT:
|
|
return SDL_APP_SUCCESS;
|
|
break;
|
|
|
|
case SDL_EVENT_WINDOW_RESIZED:
|
|
{
|
|
_onFramebufferSize(event->window.data1, event->window.data2);
|
|
}
|
|
break;
|
|
|
|
case SDL_EVENT_MOUSE_MOTION:
|
|
{
|
|
_onMouseMove(event->motion.x, event->motion.y);
|
|
}
|
|
break;
|
|
|
|
case SDL_EVENT_MOUSE_WHEEL:
|
|
{
|
|
_onMouseWheel(event->wheel.x, event->wheel.y);
|
|
}
|
|
break;
|
|
|
|
case SDL_EVENT_KEY_DOWN:
|
|
{
|
|
_onKeyDown(event->key.key);
|
|
}
|
|
break;
|
|
|
|
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
|
{
|
|
_onMouseDown(event->button.button);
|
|
}
|
|
break;
|
|
case SDL_EVENT_MOUSE_BUTTON_UP:
|
|
{
|
|
_onMouseUp(event->button.button);
|
|
}
|
|
break;
|
|
}
|
|
return SDL_APP_CONTINUE;
|
|
}
|
|
|
|
SDL_AppResult SDL_AppIterate(void* appstate)
|
|
{
|
|
SDL_FRect rect;
|
|
|
|
SDL_SetRenderDrawColor(g_renderer, 0, 99, 177, SDL_ALPHA_OPAQUE);
|
|
SDL_RenderClear(g_renderer);
|
|
|
|
_drawGrid();
|
|
_drawTriangles();
|
|
_drawAction();
|
|
_drawPixelSample();
|
|
_drawMouseCursor();
|
|
_drawDebugText();
|
|
|
|
SDL_RenderPresent(g_renderer); /* put it all on the screen! */
|
|
return SDL_APP_CONTINUE;
|
|
}
|
|
|
|
/* This function runs once at shutdown. */
|
|
void SDL_AppQuit(void* appstate, SDL_AppResult result)
|
|
{
|
|
}
|