[rmodels] Re-implement DrawBillboardPro
This commit is contained in:
parent
9a280cda0b
commit
91e19d4c42
132
src/rmodels.c
132
src/rmodels.c
|
|
@ -3659,108 +3659,66 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector
|
||||||
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
|
// 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 };
|
size = (Vector2) { size.x*fabsf((float)source.width/source.height), size.y };
|
||||||
|
|
||||||
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 };
|
right = Vector3Scale(right, size.x);
|
||||||
|
up = Vector3Scale(up, size.y);
|
||||||
|
|
||||||
Vector3 rightScaled = Vector3Scale(right, sizeRatio.x/2);
|
if (size.x < 0.0f)
|
||||||
Vector3 upScaled = Vector3Scale(up, sizeRatio.y/2);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (rotation != 0.0f)
|
|
||||||
{
|
{
|
||||||
float sinRotation = sinf(rotation*DEG2RAD);
|
source.x += size.x;
|
||||||
float cosRotation = cosf(rotation*DEG2RAD);
|
source.width *= -1.0;
|
||||||
|
right = Vector3Negate(right);
|
||||||
// NOTE: (-1, 1) is the range where origin.x, origin.y is inside the texture
|
origin.x *= -1.0f;
|
||||||
float rotateAboutX = sizeRatio.x*origin.x/2;
|
}
|
||||||
float rotateAboutY = sizeRatio.y*origin.y/2;
|
if (size.y < 0.0f)
|
||||||
|
{
|
||||||
float xtvalue, ytvalue;
|
source.y += size.y;
|
||||||
float rotatedX, rotatedY;
|
source.height *= -1.0;
|
||||||
|
up = Vector3Negate(up);
|
||||||
xtvalue = Vector3DotProduct(right, topLeft) - rotateAboutX; // Project points to x and y coordinates on the billboard plane
|
origin.y *= -1.0f;
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate points to the draw center (position)
|
position = Vector3Add(position, Vector3Scale(Vector3Add(Vector3Scale(right, origin.x), Vector3Scale(up, origin.y)), 0.5f));
|
||||||
topLeft = Vector3Add(topLeft, position);
|
origin = Vector2Multiply(Vector2Scale(Vector2Add(origin, Vector2One()), 0.5f), (Vector2) { fabsf(size.x), fabsf(size.y) });
|
||||||
topRight = Vector3Add(topRight, position);
|
|
||||||
bottomRight = Vector3Add(bottomRight, position);
|
Vector3 forward;
|
||||||
bottomLeft = Vector3Add(bottomLeft, position);
|
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++)
|
||||||
|
{
|
||||||
|
points[i] = Vector3Subtract(points[i], origin3D);
|
||||||
|
if (rotation != 0.0) points[i] = Vector3RotateByAxisAngle(points[i], forward, rotation * DEG2RAD);
|
||||||
|
points[i] = Vector3Add(points[i], 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);
|
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
if (sizeRatio.x*sizeRatio.y >= 0.0f)
|
|
||||||
{
|
{
|
||||||
// Bottom-left corner for texture and quad
|
rlTexCoord2f(texcoords[i].x, texcoords[i].y);
|
||||||
rlTexCoord2f((float)source.x/texture.width, (float)source.y/texture.height);
|
rlVertex3f(points[i].x, points[i].y, points[i].z);
|
||||||
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
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rlEnd();
|
rlEnd();
|
||||||
|
|
||||||
rlSetTexture(0);
|
rlSetTexture(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user