246 lines
7.7 KiB
C
246 lines
7.7 KiB
C
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h> /**< rand */
|
|
|
|
#include "sww/app.h"
|
|
#include "sww/fps_helper.h"
|
|
#include "sww/rate_helper.h"
|
|
#include "sww/renderer.h"
|
|
#include "sww/util.h"
|
|
#include "sww/window.h"
|
|
|
|
#define MAX_SCENE 10
|
|
|
|
#define TITLE "SWW Shapes"
|
|
|
|
typedef struct
|
|
{
|
|
int w;
|
|
int h;
|
|
int method;
|
|
swwRenderer* renderer;
|
|
} UserData;
|
|
|
|
void OnKey(swwWindow* o, swwKeycode key, int pressed)
|
|
{
|
|
if (pressed) {
|
|
if (key == swwKeycode_ESCAPE) {
|
|
swwApp_PostQuitEvent();
|
|
} else {
|
|
UserData* ud = swwWindow_GetUserData(o);
|
|
ud->method = (ud->method + 1) % MAX_SCENE;
|
|
}
|
|
}
|
|
}
|
|
|
|
void OnButton(swwWindow* o, swwButton btn, int pressed)
|
|
{
|
|
if (btn == swwButton_L && pressed) {
|
|
UserData* ud = swwWindow_GetUserData(o);
|
|
} else if (btn == swwButton_R && pressed) {
|
|
// Save to png file
|
|
UserData* ud = swwWindow_GetUserData(o);
|
|
uint32_t buf_size = swwUtil_PngBufferSize(ud->w, ud->h, 1);
|
|
uint8_t* buf = (uint8_t*)malloc(buf_size);
|
|
uint8_t* wbuf = swwRenderer_LockBuffer(ud->renderer);
|
|
FILE* fp = NULL;
|
|
swwUtil_SaveBufferToPngBuffer(buf, buf_size, wbuf, ud->w, ud->h, 1);
|
|
fp = fopen("output.png", "wb+");
|
|
fwrite(buf, 1, buf_size, fp);
|
|
fclose(fp);
|
|
free(buf);
|
|
}
|
|
}
|
|
|
|
void OnScroll(swwWindow* o, float offset)
|
|
{}
|
|
|
|
void HeartLine(swwWindow* o)
|
|
{
|
|
UserData* ud = swwWindow_GetUserData(o);
|
|
int i = 1;
|
|
int n = 1000;
|
|
float a = 10.f;
|
|
uint32_t red = Color_RGBA(255, 0, 0, 166);
|
|
|
|
int32_t hw = ud->w / 2;
|
|
int32_t hh = ud->h / 2;
|
|
|
|
for (; i < n; i++) {
|
|
float theta = i * 2.0 * M_PI / n;
|
|
float x = 16 * pow(sin(theta), 3);
|
|
float y = 13 * cos(theta) - 5 * cos(2 * theta) - 2 * cos(3 * theta) - cos(4 * theta);
|
|
int px = (int)(a * x + hw);
|
|
int py = (int)(-a * y + hh);
|
|
// swwWindow_DrawPixel(o, px, py, Color_Blend(swwWindow_GetPixel(o, px, py),
|
|
// red));
|
|
swwRenderer_DrawPixel(ud->renderer, (Point2i){px, py}, kRed);
|
|
}
|
|
}
|
|
|
|
void HideSphere(swwRenderer* o, int cx, int cy, float r, int alpha, int beta, int hide,
|
|
uint32_t color)
|
|
{
|
|
int i, j, k;
|
|
float x[4], y[4], z[4], x1[4], y1[4], z1[4], sx[4], sy[4];
|
|
double a1, a2, b1, b2, c, d, xn, yn, zn, vn;
|
|
c = alpha * M_PI / 180.0;
|
|
d = beta * M_PI / 180.0;
|
|
for (j = 0; j < 180; j = j + 5) {
|
|
a1 = j * M_PI / 180.0;
|
|
a2 = (j + 5) * M_PI / 180.0;
|
|
for (i = 0; i < 360; i = i + 5) {
|
|
b1 = i * M_PI / 180.0;
|
|
b2 = (i + 5) * M_PI / 180.0;
|
|
x[0] = r * sin(a1) * cos(b1);
|
|
y[0] = r * sin(a1) * sin(b1);
|
|
z[0] = r * cos(a1);
|
|
x[1] = r * sin(a2) * cos(b1);
|
|
y[1] = r * sin(a2) * sin(b1);
|
|
z[1] = r * cos(a2);
|
|
x[2] = r * sin(a2) * cos(b2);
|
|
y[2] = r * sin(a2) * sin(b2);
|
|
z[2] = r * cos(a2);
|
|
x[3] = r * sin(a1) * cos(b2);
|
|
y[3] = r * sin(a1) * sin(b2);
|
|
z[3] = r * cos(a1);
|
|
for (k = 0; k < 4; k++) {
|
|
x1[k] = x[k] * cos(c) - y[k] * sin(c);
|
|
y1[k] = x[k] * sin(c) * cos(d) + y[k] * cos(c) * sin(d) + z[k] * sin(d);
|
|
z1[k] = -x[k] * sin(c) * sin(d) - y[k] * cos(c) * sin(d) + z[k] * cos(d);
|
|
sx[k] = cx - x1[k];
|
|
sy[k] = cy - z1[k];
|
|
}
|
|
xn = (y1[2] - y1[0]) * (z1[3] - z1[1]) - (y1[3] - y1[1]) * (z1[2] - z1[0]);
|
|
yn = -(x1[2] - x1[0]) * (z1[3] - z1[1]) + (x1[3] - x1[1]) * (z1[2] - z1[0]);
|
|
zn = (x1[2] - x1[0]) * (y1[3] - y1[1]) - (x1[3] - x1[1]) * (y1[2] - y1[0]);
|
|
vn = sqrt(xn * xn + yn * yn + zn * zn);
|
|
xn = xn / vn;
|
|
yn = yn / vn;
|
|
zn = zn / vn;
|
|
if (!hide || yn >= 0.0) {
|
|
swwRenderer_DrawLine(o, (Point2i){sx[0], sy[0]}, (Point2i){sx[1], sy[1]}, color);
|
|
swwRenderer_DrawLine(o, (Point2i){sx[1], sy[1]}, (Point2i){sx[2], sy[2]}, color);
|
|
swwRenderer_DrawLine(o, (Point2i){sx[2], sy[2]}, (Point2i){sx[3], sy[3]}, color);
|
|
swwRenderer_DrawLine(o, (Point2i){sx[3], sy[3]}, (Point2i){sx[0], sy[0]}, color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int main()
|
|
{
|
|
int w = 512, h = 512;
|
|
int cw, ch;
|
|
swwRateHelper rh;
|
|
swwFpsHelper fps;
|
|
|
|
swwWindowCallback callback = {OnKey, OnButton, OnScroll};
|
|
swwApp_Initialize();
|
|
|
|
swwWindow* window = swwWindow_Create(TITLE, w, h);
|
|
UserData ud = {w, h, 0, NULL};
|
|
ud.renderer = swwRenderer_CreateAttachWindow(window, kSoftwareRenderer);
|
|
swwWindow_SetUserData(window, &ud);
|
|
|
|
swwWindow_SetCallback(window, &callback);
|
|
|
|
cw = w / 2;
|
|
ch = h / 2;
|
|
|
|
int x = 320, y = 240;
|
|
int dx = 2, dy = 2;
|
|
|
|
int radius = 100;
|
|
int alpha = 45;
|
|
int beta = 30;
|
|
uint32_t ball_c = kRed;
|
|
|
|
swwRenderer_EnablePerfMonitor(ud.renderer, 1);
|
|
swwFpsHelper_Construct(&fps, 1.f);
|
|
|
|
swwRateHelper_Construct(&rh, 30.f);
|
|
while (!swwApp_ShouldExit()) {
|
|
swwRenderer_ClearBlack(ud.renderer);
|
|
switch (ud.method) {
|
|
case 0: {
|
|
swwRenderer_DrawEllipse(ud.renderer, (Point2i){cw, ch}, 100, 200, kGreen, 0);
|
|
} break;
|
|
case 1: {
|
|
swwRenderer_DrawCircle(ud.renderer, (Point2i){cw, ch}, 100, kRed, 0);
|
|
} break;
|
|
case 2: {
|
|
swwRenderer_DrawEllipse(ud.renderer, (Point2i){cw, ch}, 100, 200,
|
|
kGreen + Color_Alphaf(0.5f), 1);
|
|
} break;
|
|
case 3: {
|
|
swwRenderer_DrawCircle(ud.renderer, (Point2i){cw, ch}, 100, kRed + Color_Alphaf(0.5f),
|
|
1);
|
|
|
|
swwRenderer_DrawCircle(ud.renderer, (Point2i){w - 1, h - 1}, 100,
|
|
kRed + Color_Alphaf(0.5f), 1);
|
|
} break;
|
|
case 4: {
|
|
HeartLine(window);
|
|
} break;
|
|
case 5: {
|
|
swwRenderer_DrawRectangleCenter(ud.renderer, (Point2i){120, 20}, (Sizei){200, 36},
|
|
kOrange + Color_Alpha(0x80), 1);
|
|
} break;
|
|
case 6: {
|
|
swwRenderer_DrawLine(ud.renderer, (Point2i){120, 20}, (Point2i){120, 200}, kViolet);
|
|
swwRenderer_DrawLine(ud.renderer, (Point2i){20, 120}, (Point2i){200, 120}, kOrange);
|
|
} break;
|
|
case 7: {
|
|
HideSphere(ud.renderer, x, y, radius, alpha, beta, 1, ball_c);
|
|
|
|
x += dx;
|
|
y += dy;
|
|
|
|
alpha = x;
|
|
beta = y;
|
|
|
|
if (x + radius >= ud.w || x - radius <= 0) {
|
|
dx = -dx;
|
|
ball_c = Color_RandomRGB;
|
|
}
|
|
|
|
if (y + radius >= ud.h || y - radius <= 0) {
|
|
dy = -dy;
|
|
ball_c = Color_RandomRGB;
|
|
}
|
|
} break;
|
|
case 8: {
|
|
const int n = 12;
|
|
for (float f = 0; f < 2 * M_PI; f += 2 * M_PI / n) {
|
|
for (float g = 0; g < 2 * M_PI; g += 2 * M_PI / n) {
|
|
Point2i begin = {(sinf(f) + 1) * w * 0.5, (cosf(f) + 1) * h * 0.5};
|
|
Point2i end = {(sinf(g) + 1) * w * 0.5, (cosf(g) + 1) * h * 0.5};
|
|
swwRenderer_DrawLine(ud.renderer, begin, end, kOrange);
|
|
}
|
|
}
|
|
} break;
|
|
case 9:
|
|
default: {
|
|
swwRenderer_DrawArc(ud.renderer, (Point2i){cw, ch}, 150, 30.f, 90.f,
|
|
Color_RGB(0x00, 0x00, 0xff), 0);
|
|
} break;
|
|
}
|
|
|
|
if (swwFpsHelper_Update(&fps, ud.renderer)) {
|
|
swwFpsHelper_SetTitleWithFps(&fps, window, TITLE);
|
|
}
|
|
|
|
swwRenderer_Present(ud.renderer);
|
|
|
|
swwApp_PollEvent();
|
|
swwRateHelper_Sleep(&rh);
|
|
}
|
|
|
|
swwRenderer_Destroy(ud.renderer);
|
|
swwWindow_Destroy(window);
|
|
swwApp_Cleanup();
|
|
|
|
return 0;
|
|
}
|