263 lines
14 KiB
C++
263 lines
14 KiB
C++
// these were once in raylib but were removed afterwards :(
|
|
#include "rlremoved.h"
|
|
#include <rlgl.h>
|
|
#include <raylib.h>
|
|
|
|
void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float length, Color color)
|
|
{
|
|
float x = position.x;
|
|
float y = position.y;
|
|
float z = position.z;
|
|
|
|
// Set desired texture to be enabled while drawing following vertex data
|
|
rlSetTexture(texture.id);
|
|
|
|
// Vertex data transformation can be defined with the commented lines,
|
|
// but in this example we calculate the transformed vertex data directly when calling rlVertex3f()
|
|
//rlPushMatrix();
|
|
// NOTE: Transformation is applied in inverse order (scale -> rotate -> translate)
|
|
//rlTranslatef(2.0f, 0.0f, 0.0f);
|
|
//rlRotatef(45, 0, 1, 0);
|
|
//rlScalef(2.0f, 2.0f, 2.0f);
|
|
|
|
rlBegin(RL_QUADS);
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
// Front Face
|
|
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
|
|
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - width / 2, y - height / 2, z + length / 2); // Bottom Left Of The Texture and Quad
|
|
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + width / 2, y - height / 2, z + length / 2); // Bottom Right Of The Texture and Quad
|
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + width / 2, y + height / 2, z + length / 2); // Top Right Of The Texture and Quad
|
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - width / 2, y + height / 2, z + length / 2); // Top Left Of The Texture and Quad
|
|
// Back Face
|
|
rlNormal3f(0.0f, 0.0f, -1.0f); // Normal Pointing Away From Viewer
|
|
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - width / 2, y - height / 2, z - length / 2); // Bottom Right Of The Texture and Quad
|
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - width / 2, y + height / 2, z - length / 2); // Top Right Of The Texture and Quad
|
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + width / 2, y + height / 2, z - length / 2); // Top Left Of The Texture and Quad
|
|
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + width / 2, y - height / 2, z - length / 2); // Bottom Left Of The Texture and Quad
|
|
// Top Face
|
|
rlNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
|
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - width / 2, y + height / 2, z - length / 2); // Top Left Of The Texture and Quad
|
|
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - width / 2, y + height / 2, z + length / 2); // Bottom Left Of The Texture and Quad
|
|
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + width / 2, y + height / 2, z + length / 2); // Bottom Right Of The Texture and Quad
|
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + width / 2, y + height / 2, z - length / 2); // Top Right Of The Texture and Quad
|
|
// Bottom Face
|
|
rlNormal3f(0.0f, -1.0f, 0.0f); // Normal Pointing Down
|
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - width / 2, y - height / 2, z - length / 2); // Top Right Of The Texture and Quad
|
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + width / 2, y - height / 2, z - length / 2); // Top Left Of The Texture and Quad
|
|
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + width / 2, y - height / 2, z + length / 2); // Bottom Left Of The Texture and Quad
|
|
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - width / 2, y - height / 2, z + length / 2); // Bottom Right Of The Texture and Quad
|
|
// Right face
|
|
rlNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right
|
|
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x + width / 2, y - height / 2, z - length / 2); // Bottom Right Of The Texture and Quad
|
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x + width / 2, y + height / 2, z - length / 2); // Top Right Of The Texture and Quad
|
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x + width / 2, y + height / 2, z + length / 2); // Top Left Of The Texture and Quad
|
|
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x + width / 2, y - height / 2, z + length / 2); // Bottom Left Of The Texture and Quad
|
|
// Left Face
|
|
rlNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left
|
|
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x - width / 2, y - height / 2, z - length / 2); // Bottom Left Of The Texture and Quad
|
|
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x - width / 2, y - height / 2, z + length / 2); // Bottom Right Of The Texture and Quad
|
|
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x - width / 2, y + height / 2, z + length / 2); // Top Right Of The Texture and Quad
|
|
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x - width / 2, y + height / 2, z - length / 2); // Top Left Of The Texture and Quad
|
|
rlEnd();
|
|
//rlPopMatrix();
|
|
|
|
rlSetTexture(0);
|
|
}
|
|
|
|
// Draw cube with texture piece applied to all faces
|
|
void DrawCubeTextureRec(Texture2D texture, Rectangle source, Vector3 position, float width, float height, float length, Color color)
|
|
{
|
|
float x = position.x;
|
|
float y = position.y;
|
|
float z = position.z;
|
|
float texWidth = (float)texture.width;
|
|
float texHeight = (float)texture.height;
|
|
|
|
// Set desired texture to be enabled while drawing following vertex data
|
|
rlSetTexture(texture.id);
|
|
|
|
// We calculate the normalized texture coordinates for the desired texture-source-rectangle
|
|
// It means converting from (tex.width, tex.height) coordinates to [0.0f, 1.0f] equivalent
|
|
rlBegin(RL_QUADS);
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
// Front face
|
|
rlNormal3f(0.0f, 0.0f, 1.0f);
|
|
rlTexCoord2f(source.x / texWidth, (source.y + source.height) / texHeight);
|
|
rlVertex3f(x - width / 2, y - height / 2, z + length / 2);
|
|
rlTexCoord2f((source.x + source.width) / texWidth, (source.y + source.height) / texHeight);
|
|
rlVertex3f(x + width / 2, y - height / 2, z + length / 2);
|
|
rlTexCoord2f((source.x + source.width) / texWidth, source.y / texHeight);
|
|
rlVertex3f(x + width / 2, y + height / 2, z + length / 2);
|
|
rlTexCoord2f(source.x / texWidth, source.y / texHeight);
|
|
rlVertex3f(x - width / 2, y + height / 2, z + length / 2);
|
|
|
|
// Back face
|
|
rlNormal3f(0.0f, 0.0f, -1.0f);
|
|
rlTexCoord2f((source.x + source.width) / texWidth, (source.y + source.height) / texHeight);
|
|
rlVertex3f(x - width / 2, y - height / 2, z - length / 2);
|
|
rlTexCoord2f((source.x + source.width) / texWidth, source.y / texHeight);
|
|
rlVertex3f(x - width / 2, y + height / 2, z - length / 2);
|
|
rlTexCoord2f(source.x / texWidth, source.y / texHeight);
|
|
rlVertex3f(x + width / 2, y + height / 2, z - length / 2);
|
|
rlTexCoord2f(source.x / texWidth, (source.y + source.height) / texHeight);
|
|
rlVertex3f(x + width / 2, y - height / 2, z - length / 2);
|
|
|
|
// Top face
|
|
rlNormal3f(0.0f, 1.0f, 0.0f);
|
|
rlTexCoord2f(source.x / texWidth, source.y / texHeight);
|
|
rlVertex3f(x - width / 2, y + height / 2, z - length / 2);
|
|
rlTexCoord2f(source.x / texWidth, (source.y + source.height) / texHeight);
|
|
rlVertex3f(x - width / 2, y + height / 2, z + length / 2);
|
|
rlTexCoord2f((source.x + source.width) / texWidth, (source.y + source.height) / texHeight);
|
|
rlVertex3f(x + width / 2, y + height / 2, z + length / 2);
|
|
rlTexCoord2f((source.x + source.width) / texWidth, source.y / texHeight);
|
|
rlVertex3f(x + width / 2, y + height / 2, z - length / 2);
|
|
|
|
// Bottom face
|
|
rlNormal3f(0.0f, -1.0f, 0.0f);
|
|
rlTexCoord2f((source.x + source.width) / texWidth, source.y / texHeight);
|
|
rlVertex3f(x - width / 2, y - height / 2, z - length / 2);
|
|
rlTexCoord2f(source.x / texWidth, source.y / texHeight);
|
|
rlVertex3f(x + width / 2, y - height / 2, z - length / 2);
|
|
rlTexCoord2f(source.x / texWidth, (source.y + source.height) / texHeight);
|
|
rlVertex3f(x + width / 2, y - height / 2, z + length / 2);
|
|
rlTexCoord2f((source.x + source.width) / texWidth, (source.y + source.height) / texHeight);
|
|
rlVertex3f(x - width / 2, y - height / 2, z + length / 2);
|
|
|
|
// Right face
|
|
rlNormal3f(1.0f, 0.0f, 0.0f);
|
|
rlTexCoord2f((source.x + source.width) / texWidth, (source.y + source.height) / texHeight);
|
|
rlVertex3f(x + width / 2, y - height / 2, z - length / 2);
|
|
rlTexCoord2f((source.x + source.width) / texWidth, source.y / texHeight);
|
|
rlVertex3f(x + width / 2, y + height / 2, z - length / 2);
|
|
rlTexCoord2f(source.x / texWidth, source.y / texHeight);
|
|
rlVertex3f(x + width / 2, y + height / 2, z + length / 2);
|
|
rlTexCoord2f(source.x / texWidth, (source.y + source.height) / texHeight);
|
|
rlVertex3f(x + width / 2, y - height / 2, z + length / 2);
|
|
|
|
// Left face
|
|
rlNormal3f(-1.0f, 0.0f, 0.0f);
|
|
rlTexCoord2f(source.x / texWidth, (source.y + source.height) / texHeight);
|
|
rlVertex3f(x - width / 2, y - height / 2, z - length / 2);
|
|
rlTexCoord2f((source.x + source.width) / texWidth, (source.y + source.height) / texHeight);
|
|
rlVertex3f(x - width / 2, y - height / 2, z + length / 2);
|
|
rlTexCoord2f((source.x + source.width) / texWidth, source.y / texHeight);
|
|
rlVertex3f(x - width / 2, y + height / 2, z + length / 2);
|
|
rlTexCoord2f(source.x / texWidth, source.y / texHeight);
|
|
rlVertex3f(x - width / 2, y + height / 2, z - length / 2);
|
|
|
|
rlEnd();
|
|
|
|
rlSetTexture(0);
|
|
}
|
|
|
|
void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontSize, bool backface, Color tint)
|
|
{
|
|
// Character index position in sprite font
|
|
// NOTE: In case a codepoint is not available in the font, index returned points to '?'
|
|
int index = GetGlyphIndex(font, codepoint);
|
|
float scale = fontSize / (float)font.baseSize;
|
|
|
|
// Character destination rectangle on screen
|
|
// NOTE: We consider charsPadding on drawing
|
|
position.x += (float)(font.glyphs[index].offsetX - font.glyphPadding) / (float)font.baseSize * scale;
|
|
position.z += (float)(font.glyphs[index].offsetY - font.glyphPadding) / (float)font.baseSize * scale;
|
|
|
|
// Character source rectangle from font texture atlas
|
|
// NOTE: We consider chars padding when drawing, it could be required for outline/glow shader effects
|
|
Rectangle srcRec = { font.recs[index].x - (float)font.glyphPadding, font.recs[index].y - (float)font.glyphPadding,
|
|
font.recs[index].width + 2.0f * font.glyphPadding, font.recs[index].height + 2.0f * font.glyphPadding };
|
|
|
|
float width = (float)(font.recs[index].width + 2.0f * font.glyphPadding) / (float)font.baseSize * scale;
|
|
float height = (float)(font.recs[index].height + 2.0f * font.glyphPadding) / (float)font.baseSize * scale;
|
|
|
|
if (font.texture.id > 0)
|
|
{
|
|
const float x = 0.0f;
|
|
const float y = 0.0f;
|
|
const float z = 0.0f;
|
|
|
|
// normalized texture coordinates of the glyph inside the font texture (0.0f -> 1.0f)
|
|
const float tx = srcRec.x / font.texture.width;
|
|
const float ty = srcRec.y / font.texture.height;
|
|
const float tw = (srcRec.x + srcRec.width) / font.texture.width;
|
|
const float th = (srcRec.y + srcRec.height) / font.texture.height;
|
|
|
|
// if (SHOW_LETTER_BOUNDRY) DrawCubeWiresV((Vector3) { position.x + width / 2, position.y, position.z + height / 2 }, (Vector3) { width, LETTER_BOUNDRY_SIZE, height }, LETTER_BOUNDRY_COLOR);
|
|
|
|
rlCheckRenderBatchLimit(4 + 4 * backface);
|
|
rlSetTexture(font.texture.id);
|
|
|
|
rlPushMatrix();
|
|
rlTranslatef(position.x, position.y, position.z);
|
|
|
|
rlBegin(RL_QUADS);
|
|
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
|
|
|
// Front Face
|
|
rlNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
|
|
rlTexCoord2f(tx, ty); rlVertex3f(x, y, z); // Top Left Of The Texture and Quad
|
|
rlTexCoord2f(tx, th); rlVertex3f(x, y, z + height); // Bottom Left Of The Texture and Quad
|
|
rlTexCoord2f(tw, th); rlVertex3f(x + width, y, z + height); // Bottom Right Of The Texture and Quad
|
|
rlTexCoord2f(tw, ty); rlVertex3f(x + width, y, z); // Top Right Of The Texture and Quad
|
|
|
|
if (backface)
|
|
{
|
|
// Back Face
|
|
rlNormal3f(0.0f, -1.0f, 0.0f); // Normal Pointing Down
|
|
rlTexCoord2f(tx, ty); rlVertex3f(x, y, z); // Top Right Of The Texture and Quad
|
|
rlTexCoord2f(tw, ty); rlVertex3f(x + width, y, z); // Top Left Of The Texture and Quad
|
|
rlTexCoord2f(tw, th); rlVertex3f(x + width, y, z + height); // Bottom Left Of The Texture and Quad
|
|
rlTexCoord2f(tx, th); rlVertex3f(x, y, z + height); // Bottom Right Of The Texture and Quad
|
|
}
|
|
rlEnd();
|
|
rlPopMatrix();
|
|
|
|
rlSetTexture(0);
|
|
}
|
|
}
|
|
|
|
// Draw a 2D text in 3D space
|
|
void DrawText3D(Font font, const char* text, Vector3 position, float fontSize, float fontSpacing, float lineSpacing, bool backface, Color tint)
|
|
{
|
|
int length = TextLength(text); // Total length in bytes of the text, scanned by codepoints in loop
|
|
|
|
float textOffsetY = 0.0f; // Offset between lines (on line break '\n')
|
|
float textOffsetX = 0.0f; // Offset X to next character to draw
|
|
|
|
float scale = fontSize / (float)font.baseSize;
|
|
|
|
for (int i = 0; i < length;)
|
|
{
|
|
// Get next codepoint from byte string and glyph index in font
|
|
int codepointByteCount = 0;
|
|
int codepoint = GetCodepoint(&text[i], &codepointByteCount);
|
|
int index = GetGlyphIndex(font, codepoint);
|
|
|
|
// NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f)
|
|
// but we need to draw all of the bad bytes using the '?' symbol moving one byte
|
|
if (codepoint == 0x3f) codepointByteCount = 1;
|
|
|
|
if (codepoint == '\n')
|
|
{
|
|
// NOTE: Fixed line spacing of 1.5 line-height
|
|
// TODO: Support custom line spacing defined by user
|
|
textOffsetY += scale + lineSpacing / (float)font.baseSize * scale;
|
|
textOffsetX = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
if ((codepoint != ' ') && (codepoint != '\t'))
|
|
{
|
|
DrawTextCodepoint3D(font, codepoint, { position.x + textOffsetX, position.y, position.z + textOffsetY }, fontSize, backface, tint);
|
|
}
|
|
|
|
if (font.glyphs[index].advanceX == 0) textOffsetX += (float)(font.recs[index].width + fontSpacing) / (float)font.baseSize * scale;
|
|
else textOffsetX += (float)(font.glyphs[index].advanceX + fontSpacing) / (float)font.baseSize * scale;
|
|
}
|
|
|
|
i += codepointByteCount; // Move text bytes counter to next codepoint
|
|
}
|
|
}
|