122 lines
3.9 KiB
C
122 lines
3.9 KiB
C
#include "twn_draw_c.h"
|
|
#include "twn_draw.h"
|
|
#include "twn_engine_context_c.h"
|
|
#include "twn_util.h"
|
|
|
|
#include <stb_ds.h>
|
|
|
|
/* TODO: Support thickness */
|
|
void draw_line(Vec2 start,
|
|
Vec2 finish,
|
|
float thickness,
|
|
Color color)
|
|
{
|
|
if (fabsf(1.0f - thickness) >= 0.00001f)
|
|
log_warn("Thickness isn't yet implemented for line drawing (got %f)", (double)thickness);
|
|
|
|
if (thickness < 1.0f) {
|
|
log_warn("Invalid thickness given.");
|
|
return;
|
|
}
|
|
|
|
struct LineVertex const v0 = { .position = (Vec3){start.x, start.y, 0}, .color = color };
|
|
struct LineVertex const v1 = { .position = (Vec3){finish.x, finish.y, 0}, .color = color };
|
|
|
|
/* combine with existing position if it's compatible */
|
|
if (arrlenu(ctx.render_queue_2d) != 0) {
|
|
Primitive2D *const primitive = &ctx.render_queue_2d[arrlenu(ctx.render_queue_2d) - 1];
|
|
if (primitive->type == PRIMITIVE_2D_LINES && fabsf(primitive->line.thickness - thickness) < 0.00001f &&
|
|
primitive->line.color.a == color.a && primitive->line.color.b == color.b &&
|
|
primitive->line.color.r == color.r && primitive->line.color.g == color.g) {
|
|
|
|
arrput(primitive->line.vertices, v0);
|
|
arrput(primitive->line.vertices, v1);
|
|
return;
|
|
}
|
|
}
|
|
|
|
LinePrimitive line = {
|
|
.thickness = thickness,
|
|
.color = color,
|
|
};
|
|
|
|
Primitive2D primitive = {
|
|
.type = PRIMITIVE_2D_LINES,
|
|
.line = line,
|
|
};
|
|
|
|
arrput(primitive.line.vertices, v0);
|
|
arrput(primitive.line.vertices, v1);
|
|
arrput(ctx.render_queue_2d, primitive);
|
|
}
|
|
|
|
|
|
void draw_line_3d(Vec3 start,
|
|
Vec3 finish,
|
|
float thickness,
|
|
Color color)
|
|
{
|
|
if (fabsf(1.0f - thickness) >= 0.00001f)
|
|
log_warn("Thickness isn't yet implemented for line drawing (got %f)", (double)thickness);
|
|
|
|
if (thickness < 1.0f) {
|
|
log_warn("Invalid thickness given.");
|
|
return;
|
|
}
|
|
|
|
struct LineVertex const v0 = { .position = start, .color = color };
|
|
struct LineVertex const v1 = { .position = finish, .color = color };
|
|
|
|
/* 3d case, unordered depth based draw */
|
|
struct LineBatchItemKey const key = { .color = color, .thickness = (uint8_t)(floorf(thickness)) };
|
|
struct LineBatchItem *batch_p = hmgetp_null(ctx.line_batches, key);
|
|
if (!batch_p) {
|
|
hmput(ctx.line_batches, key, ((struct LinePrimitive){.thickness = thickness, .color = color}));
|
|
batch_p = &ctx.line_batches[hmlenu(ctx.line_batches) - 1];
|
|
}
|
|
arrput(batch_p->value.vertices, v0);
|
|
arrput(batch_p->value.vertices, v1);
|
|
return;
|
|
}
|
|
|
|
|
|
void render_lines(LinePrimitive const *line, bool is_3d) {
|
|
DeferredCommandDraw command = {0};
|
|
|
|
VertexBuffer buffer = get_scratch_vertex_array();
|
|
specify_vertex_buffer(buffer, line->vertices, arrlenu(line->vertices) * sizeof (*line->vertices));
|
|
|
|
command.vertices = (AttributeArrayPointer) {
|
|
.arity = 3,
|
|
.type = TWN_FLOAT,
|
|
.stride = sizeof (struct LineVertex),
|
|
.offset = offsetof (struct LineVertex, position),
|
|
.buffer = buffer
|
|
};
|
|
|
|
command.colors = (AttributeArrayPointer) {
|
|
.arity = 4,
|
|
.type = TWN_UNSIGNED_BYTE,
|
|
.stride = sizeof (struct LineVertex),
|
|
.offset = offsetof (struct LineVertex, color),
|
|
.buffer = buffer
|
|
};
|
|
|
|
command.primitive_count = (uint32_t)arrlenu(line->vertices);
|
|
|
|
command.geometry_mode = DEFERRED_COMMAND_DRAW_GEOMETRY_MODE_LINES;
|
|
command.pipeline = is_3d ? PIPELINE_SPACE : PIPELINE_2D;
|
|
|
|
command.texture_mode = line->color.a == 255 ? TEXTURE_MODE_OPAQUE : TEXTURE_MODE_GHOSTLY;
|
|
|
|
command.depth_range_high = depth_range_high;
|
|
command.depth_range_low = depth_range_low;
|
|
|
|
DeferredCommand final_command = {
|
|
.type = DEFERRED_COMMAND_TYPE_DRAW,
|
|
.draw = command
|
|
};
|
|
|
|
arrpush(deferred_commands, final_command);
|
|
}
|