|
@ -3638,11 +3638,11 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Draw a billboard |
|
|
// Draw a billboard |
|
|
void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint) |
|
|
|
|
|
|
|
|
void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float scale, Color tint) |
|
|
{ |
|
|
{ |
|
|
Rectangle source = { 0.0f, 0.0f, (float)texture.width, (float)texture.height }; |
|
|
Rectangle source = { 0.0f, 0.0f, (float)texture.width, (float)texture.height }; |
|
|
|
|
|
|
|
|
DrawBillboardRec(camera, texture, source, position, (Vector2){ size, size }, tint); |
|
|
|
|
|
|
|
|
DrawBillboardRec(camera, texture, source, position, (Vector2) { scale*fabsf((float)source.width/source.height), scale }, tint); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Draw a billboard (part of a texture defined by a rectangle) |
|
|
// Draw a billboard (part of a texture defined by a rectangle) |
|
@ -3651,116 +3651,82 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector |
|
|
// NOTE: Billboard locked on axis-Y |
|
|
// NOTE: Billboard locked on axis-Y |
|
|
Vector3 up = { 0.0f, 1.0f, 0.0f }; |
|
|
Vector3 up = { 0.0f, 1.0f, 0.0f }; |
|
|
|
|
|
|
|
|
DrawBillboardPro(camera, texture, source, position, up, size, Vector2Zero(), 0.0f, tint); |
|
|
|
|
|
|
|
|
DrawBillboardPro(camera, texture, source, position, up, size, Vector2Scale(size, 0.5), 0.0f, tint); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Draw a billboard with additional parameters |
|
|
// Draw a billboard with additional parameters |
|
|
// NOTE: Size defines the destination rectangle size, stretching the source texture as required |
|
|
|
|
|
void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint) |
|
|
void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint) |
|
|
{ |
|
|
{ |
|
|
// NOTE: Billboard size will maintain source rectangle aspect ratio, size will represent billboard width |
|
|
|
|
|
Vector2 sizeRatio = { size.x*fabsf((float)source.width/source.height), size.y }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Compute the up vector and the right vector |
|
|
Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); |
|
|
Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); |
|
|
|
|
|
|
|
|
Vector3 right = { matView.m0, matView.m4, matView.m8 }; |
|
|
Vector3 right = { matView.m0, matView.m4, matView.m8 }; |
|
|
//Vector3 up = { matView.m1, matView.m5, matView.m9 }; |
|
|
|
|
|
|
|
|
|
|
|
Vector3 rightScaled = Vector3Scale(right, sizeRatio.x/2); |
|
|
|
|
|
Vector3 upScaled = Vector3Scale(up, sizeRatio.y/2); |
|
|
|
|
|
|
|
|
right = Vector3Scale(right, size.x); |
|
|
|
|
|
up = Vector3Scale(up, size.y); |
|
|
|
|
|
|
|
|
Vector3 p1 = Vector3Add(rightScaled, upScaled); |
|
|
|
|
|
Vector3 p2 = Vector3Subtract(rightScaled, upScaled); |
|
|
|
|
|
|
|
|
|
|
|
Vector3 topLeft = Vector3Scale(p2, -1); |
|
|
|
|
|
Vector3 topRight = p1; |
|
|
|
|
|
Vector3 bottomRight = p2; |
|
|
|
|
|
Vector3 bottomLeft = Vector3Scale(p1, -1); |
|
|
|
|
|
|
|
|
// Flip the content of the billboard while maintaining the counterclockwise edge rendering order |
|
|
|
|
|
if (size.x < 0.0f) |
|
|
|
|
|
{ |
|
|
|
|
|
source.x += size.x; |
|
|
|
|
|
source.width *= -1.0; |
|
|
|
|
|
right = Vector3Negate(right); |
|
|
|
|
|
origin.x *= -1.0f; |
|
|
|
|
|
} |
|
|
|
|
|
if (size.y < 0.0f) |
|
|
|
|
|
{ |
|
|
|
|
|
source.y += size.y; |
|
|
|
|
|
source.height *= -1.0; |
|
|
|
|
|
up = Vector3Negate(up); |
|
|
|
|
|
origin.y *= -1.0f; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (rotation != 0.0f) |
|
|
|
|
|
|
|
|
// Draw the texture region described by source on the following rectangle in 3D space: |
|
|
|
|
|
// |
|
|
|
|
|
// size.x <--. |
|
|
|
|
|
// 3 ^---------------------------+ 2 \ rotation |
|
|
|
|
|
// | | / |
|
|
|
|
|
// | | |
|
|
|
|
|
// | origin.x position | |
|
|
|
|
|
// up |.............. | size.y |
|
|
|
|
|
// | . | |
|
|
|
|
|
// | . origin.y | |
|
|
|
|
|
// | . | |
|
|
|
|
|
// 0 +---------------------------> 1 |
|
|
|
|
|
// right |
|
|
|
|
|
Vector3 forward; |
|
|
|
|
|
if (rotation != 0.0) forward = Vector3CrossProduct(right, up); |
|
|
|
|
|
|
|
|
|
|
|
Vector3 origin3D = Vector3Add(Vector3Scale(Vector3Normalize(right), origin.x), Vector3Scale(Vector3Normalize(up), origin.y)); |
|
|
|
|
|
|
|
|
|
|
|
Vector3 points[4]; |
|
|
|
|
|
points[0] = Vector3Zero(); |
|
|
|
|
|
points[1] = right; |
|
|
|
|
|
points[2] = Vector3Add(up, right); |
|
|
|
|
|
points[3] = up; |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; i++) |
|
|
{ |
|
|
{ |
|
|
float sinRotation = sinf(rotation*DEG2RAD); |
|
|
|
|
|
float cosRotation = cosf(rotation*DEG2RAD); |
|
|
|
|
|
|
|
|
|
|
|
// NOTE: (-1, 1) is the range where origin.x, origin.y is inside the texture |
|
|
|
|
|
float rotateAboutX = sizeRatio.x*origin.x/2; |
|
|
|
|
|
float rotateAboutY = sizeRatio.y*origin.y/2; |
|
|
|
|
|
|
|
|
|
|
|
float xtvalue, ytvalue; |
|
|
|
|
|
float rotatedX, rotatedY; |
|
|
|
|
|
|
|
|
|
|
|
xtvalue = Vector3DotProduct(right, topLeft) - rotateAboutX; // Project points to x and y coordinates on the billboard plane |
|
|
|
|
|
ytvalue = Vector3DotProduct(up, topLeft) - rotateAboutY; |
|
|
|
|
|
rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; // Rotate about the point origin |
|
|
|
|
|
rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY; |
|
|
|
|
|
topLeft = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); // Translate back to cartesian coordinates |
|
|
|
|
|
|
|
|
|
|
|
xtvalue = Vector3DotProduct(right, topRight) - rotateAboutX; |
|
|
|
|
|
ytvalue = Vector3DotProduct(up, topRight) - rotateAboutY; |
|
|
|
|
|
rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; |
|
|
|
|
|
rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY; |
|
|
|
|
|
topRight = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); |
|
|
|
|
|
|
|
|
|
|
|
xtvalue = Vector3DotProduct(right, bottomRight) - rotateAboutX; |
|
|
|
|
|
ytvalue = Vector3DotProduct(up, bottomRight) - rotateAboutY; |
|
|
|
|
|
rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; |
|
|
|
|
|
rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY; |
|
|
|
|
|
bottomRight = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); |
|
|
|
|
|
|
|
|
|
|
|
xtvalue = Vector3DotProduct(right, bottomLeft)-rotateAboutX; |
|
|
|
|
|
ytvalue = Vector3DotProduct(up, bottomLeft)-rotateAboutY; |
|
|
|
|
|
rotatedX = xtvalue*cosRotation - ytvalue*sinRotation + rotateAboutX; |
|
|
|
|
|
rotatedY = xtvalue*sinRotation + ytvalue*cosRotation + rotateAboutY; |
|
|
|
|
|
bottomLeft = Vector3Add(Vector3Scale(up, rotatedY), Vector3Scale(right, rotatedX)); |
|
|
|
|
|
|
|
|
points[i] = Vector3Subtract(points[i], origin3D); |
|
|
|
|
|
if (rotation != 0.0) points[i] = Vector3RotateByAxisAngle(points[i], forward, rotation * DEG2RAD); |
|
|
|
|
|
points[i] = Vector3Add(points[i], position); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
o">// Translate points to the draw center (position) |
|
|
|
|
|
topLeft = Vector3Add(topLeft, position); |
|
|
|
|
|
topRight = Vector3Add(topRight, position); |
|
|
|
|
|
bottomRight = Vector3Add(bottomRight, position); |
|
|
|
|
|
bottomLeft = Vector3Add(bottomLeft, position); |
|
|
|
|
|
|
|
|
Vector2 texcoords[4]; |
|
|
|
|
|
texcoords[0] = (Vector2) { (float)source.x/texture.width, (float)(source.y + source.height)/texture.height }; |
|
|
|
|
|
texcoords[1] = (Vector2) { (float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height }; |
|
|
|
|
|
texcoords[2] = (Vector2) { (float)(source.x + source.width)/texture.width, (float)source.y/texture.height }; |
|
|
|
|
|
texcoords[3] = (Vector2) { (float)source.x/texture.width, (float)source.y/texture.height }; |
|
|
|
|
|
|
|
|
rlSetTexture(texture.id); |
|
|
rlSetTexture(texture.id); |
|
|
|
|
|
|
|
|
rlBegin(RL_QUADS); |
|
|
rlBegin(RL_QUADS); |
|
|
rlColor4ub(tint.r, tint.g, tint.b, tint.a); |
|
|
|
|
|
|
|
|
|
|
|
if (sizeRatio.x*sizeRatio.y >= 0.0f) |
|
|
|
|
|
{ |
|
|
|
|
|
// Bottom-left corner for texture and quad |
|
|
|
|
|
rlTexCoord2f((float)source.x/texture.width, (float)source.y/texture.height); |
|
|
|
|
|
rlVertex3f(topLeft.x, topLeft.y, topLeft.z); |
|
|
|
|
|
|
|
|
|
|
|
// Top-left corner for texture and quad |
|
|
|
|
|
rlTexCoord2f((float)source.x/texture.width, (float)(source.y + source.height)/texture.height); |
|
|
|
|
|
rlVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); |
|
|
|
|
|
|
|
|
|
|
|
// Top-right corner for texture and quad |
|
|
|
|
|
rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height); |
|
|
|
|
|
rlVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); |
|
|
|
|
|
|
|
|
|
|
|
// Bottom-right corner for texture and quad |
|
|
|
|
|
rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)source.y/texture.height); |
|
|
|
|
|
rlVertex3f(topRight.x, topRight.y, topRight.z); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
|
|
|
rlColor4ub(tint.r, tint.g, tint.b, tint.a); |
|
|
|
|
|
for (int i = 0; i < 4; i++) |
|
|
{ |
|
|
{ |
|
|
// Reverse vertex order if the size has only one negative dimension |
|
|
|
|
|
rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)source.y/texture.height); |
|
|
|
|
|
rlVertex3f(topRight.x, topRight.y, topRight.z); |
|
|
|
|
|
|
|
|
|
|
|
rlTexCoord2f((float)(source.x + source.width)/texture.width, (float)(source.y + source.height)/texture.height); |
|
|
|
|
|
rlVertex3f(bottomRight.x, bottomRight.y, bottomRight.z); |
|
|
|
|
|
|
|
|
|
|
|
rlTexCoord2f((float)source.x/texture.width, (float)(source.y + source.height)/texture.height); |
|
|
|
|
|
rlVertex3f(bottomLeft.x, bottomLeft.y, bottomLeft.z); |
|
|
|
|
|
|
|
|
|
|
|
rlTexCoord2f((float)source.x/texture.width, (float)source.y/texture.height); |
|
|
|
|
|
rlVertex3f(topLeft.x, topLeft.y, topLeft.z); |
|
|
|
|
|
|
|
|
rlTexCoord2f(texcoords[i].x, texcoords[i].y); |
|
|
|
|
|
rlVertex3f(points[i].x, points[i].y, points[i].z); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
rlEnd(); |
|
|
rlEnd(); |
|
|
|
|
|
|
|
|
rlSetTexture(0); |
|
|
rlSetTexture(0); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|