#include "raylib.h" #include "math.h" #include "raymath.h" #include #include #include "common.hpp" #include #include const char* Pathify(const char* src) { static std::string s; s = std::string(PATH_APPEND) + src; return s.c_str(); } const char* PathifyUser(const char* src) { static std::string s; s = std::string(PATH_APPEND_USER) + src; return s.c_str(); } #ifndef SERVER void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float length, Color color, int offsetX, int offsetY, int sizeX, int sizeY) { float x = position.x; float y = position.y; float z = position.z; float sidesModX = length / width; float topBottomModY = height / width; UVCorners front = GetUVTexFlipX(texture.width, texture.height, offsetX, offsetY, sizeX, sizeY * topBottomModY); UVCorners back = GetUVTexFlipX(texture.width, texture.height, offsetX+sizeX+sizeX*sidesModX, offsetY, sizeX, sizeY * topBottomModY); UVCorners top = GetUVTexFlipX(texture.width, texture.height, offsetX, offsetY-sizeY, sizeX, sizeY); UVCorners bottom = GetUVTexFlipX(texture.width, texture.height, offsetX+sizeX, offsetY-sizeY, sizeX, sizeY); UVCorners left = GetUVTexFlipX(texture.width, texture.height, offsetX-sizeX * sidesModX, offsetY, sizeX * sidesModX, sizeY * topBottomModY); UVCorners right = GetUVTexFlipX(texture.width, texture.height, offsetX+sizeX * sidesModX, offsetY, sizeX * sidesModX, sizeY * topBottomModY); // 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(front.corner0.x, front.corner0.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(front.corner1.x, front.corner1.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(front.corner2.x, front.corner2.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad rlTexCoord2f(front.corner3.x, front.corner3.y); 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(back.corner1.x, back.corner1.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(back.corner2.x, back.corner2.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad rlTexCoord2f(back.corner3.x, back.corner3.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad rlTexCoord2f(back.corner0.x, back.corner0.y); 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(top.corner3.x, top.corner3.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad rlTexCoord2f(top.corner0.x, top.corner0.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(top.corner1.x, top.corner1.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(top.corner2.x, top.corner2.y); 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(bottom.corner2.x, bottom.corner2.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Right Of The Texture and Quad rlTexCoord2f(bottom.corner3.x, bottom.corner3.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Top Left Of The Texture and Quad rlTexCoord2f(bottom.corner0.x, bottom.corner0.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(bottom.corner1.x, bottom.corner1.y); 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(right.corner1.x, right.corner1.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(right.corner2.x, right.corner2.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad rlTexCoord2f(right.corner3.x, right.corner3.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad rlTexCoord2f(right.corner0.x, right.corner0.y); 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(left.corner0.x, left.corner0.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(left.corner1.x, left.corner1.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(left.corner2.x, left.corner2.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad rlTexCoord2f(left.corner3.x, left.corner3.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad rlEnd(); //rlPopMatrix(); rlSetTexture(0); } void DrawCubeBlock(Texture2D texture, Vector3 position, float width, float height, float length, BlockDef def) { float x = position.x; float y = position.y; float z = position.z; float sidesModX = length / width; float topBottomModY = height / width; UVCorners front = GetUVTex(def.textureSide); UVCorners back = GetUVTex(def.textureSide); UVCorners top = GetUVTex(def.textureTop); UVCorners bottom = GetUVTex(def.textureBottom); UVCorners left = GetUVTex(def.textureSide); UVCorners right = GetUVTex(def.textureSide); rlSetTexture(texture.id); rlBegin(RL_QUADS); rlColor4ub(255, 255, 255, 255); // Front Face rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer rlTexCoord2f(front.corner0.x, front.corner0.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(front.corner1.x, front.corner1.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(front.corner2.x, front.corner2.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad rlTexCoord2f(front.corner3.x, front.corner3.y); 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(back.corner1.x, back.corner1.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(back.corner2.x, back.corner2.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad rlTexCoord2f(back.corner3.x, back.corner3.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad rlTexCoord2f(back.corner0.x, back.corner0.y); 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(top.corner3.x, top.corner3.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad rlTexCoord2f(top.corner0.x, top.corner0.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(top.corner1.x, top.corner1.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(top.corner2.x, top.corner2.y); 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(bottom.corner2.x, bottom.corner2.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Top Right Of The Texture and Quad rlTexCoord2f(bottom.corner3.x, bottom.corner3.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Top Left Of The Texture and Quad rlTexCoord2f(bottom.corner0.x, bottom.corner0.y); rlVertex3f(x + width/2, y - height/2, z + length/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(bottom.corner1.x, bottom.corner1.y); 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(right.corner1.x, right.corner1.y); rlVertex3f(x + width/2, y - height/2, z - length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(right.corner2.x, right.corner2.y); rlVertex3f(x + width/2, y + height/2, z - length/2); // Top Right Of The Texture and Quad rlTexCoord2f(right.corner3.x, right.corner3.y); rlVertex3f(x + width/2, y + height/2, z + length/2); // Top Left Of The Texture and Quad rlTexCoord2f(right.corner0.x, right.corner0.y); 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(left.corner0.x, left.corner0.y); rlVertex3f(x - width/2, y - height/2, z - length/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(left.corner1.x, left.corner1.y); rlVertex3f(x - width/2, y - height/2, z + length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(left.corner2.x, left.corner2.y); rlVertex3f(x - width/2, y + height/2, z + length/2); // Top Right Of The Texture and Quad rlTexCoord2f(left.corner3.x, left.corner3.y); rlVertex3f(x - width/2, y + height/2, z - length/2); // Top Left Of The Texture and Quad rlEnd(); rlSetTexture(0); } #endif #ifndef SERVER 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)*scale; position.z += (float)(font.glyphs[index].offsetY - font.glyphPadding)*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)*scale; float height = (float)(font.recs[index].height + 2.0f*font.glyphPadding)*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; 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 += fontSize + lineSpacing; textOffsetX = 0.0f; } else { if ((codepoint != ' ') && (codepoint != '\t')) { DrawTextCodepoint3D(font, codepoint, (Vector3){ position.x + textOffsetX, position.y, position.z + textOffsetY }, fontSize, backface, tint); } if (font.glyphs[index].advanceX == 0) textOffsetX += (float)font.recs[index].width*scale + fontSpacing; else textOffsetX += (float)font.glyphs[index].advanceX*scale + fontSpacing; } i += codepointByteCount; // Move text bytes counter to next codepoint } } #endif