stuff
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
#ifndef TEXTURE_PAINTER_CLASS
|
||||
#define TEXTURE_PAINTER_CLASS
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "texture.h"
|
||||
|
||||
// The brush behind the texture drawer. Edits a Texture's pixels and uploads them.
|
||||
class TexturePainter {
|
||||
public:
|
||||
glm::vec3 color = glm::vec3(0.0f);
|
||||
int brushSize = 8; // radius in pixels of a 256 wide texture, so it looks the same on any size
|
||||
|
||||
// uv runs 0-1 from the top left of the image. Joins up with the last call until EndStroke.
|
||||
void Stroke(Texture& texture, const glm::vec2& uv) {
|
||||
const glm::vec2 point(uv.x * texture.width, (1.0f - uv.y) * texture.height);
|
||||
const float radius = glm::max(1.0f, brushSize * texture.width / 256.0f);
|
||||
|
||||
if (!stroking) {
|
||||
Stamp(texture, point, radius);
|
||||
}
|
||||
else {
|
||||
// Fill the gap, the mouse can cross a lot of pixels in one frame
|
||||
const int steps = (int)std::ceil(glm::length(point - lastPoint) / (radius * 0.5f));
|
||||
for (int i = 1; i <= steps; i++)
|
||||
Stamp(texture, glm::mix(lastPoint, point, (float)i / (float)steps), radius);
|
||||
}
|
||||
|
||||
stroking = true;
|
||||
lastPoint = point;
|
||||
texture.Upload();
|
||||
}
|
||||
|
||||
void EndStroke() {
|
||||
stroking = false;
|
||||
}
|
||||
|
||||
void Clear(Texture& texture) {
|
||||
texture.pixels.assign(texture.pixels.size(), 255);
|
||||
texture.Upload();
|
||||
}
|
||||
|
||||
private:
|
||||
bool stroking = false;
|
||||
glm::vec2 lastPoint = glm::vec2(0.0f);
|
||||
|
||||
void Stamp(Texture& texture, const glm::vec2& center, float radius) {
|
||||
const int minX = glm::max((int)(center.x - radius), 0);
|
||||
const int maxX = glm::min((int)(center.x + radius), texture.width - 1);
|
||||
const int minY = glm::max((int)(center.y - radius), 0);
|
||||
const int maxY = glm::min((int)(center.y + radius), texture.height - 1);
|
||||
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
const glm::vec2 offset = glm::vec2(x + 0.5f, y + 0.5f) - center;
|
||||
if (glm::dot(offset, offset) > radius * radius)
|
||||
continue;
|
||||
|
||||
unsigned char* pixel = &texture.pixels[((size_t)y * texture.width + x) * 4];
|
||||
pixel[0] = (unsigned char)(color.r * 255.0f);
|
||||
pixel[1] = (unsigned char)(color.g * 255.0f);
|
||||
pixel[2] = (unsigned char)(color.b * 255.0f);
|
||||
pixel[3] = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user