1
Graphics / How to DRAW custom shapes?
« on: January 15, 2022, 01:32:45 pm »
Hi! I'm trying to make a 3D engine with SFML, and for now it's going quite well.
I'm using a single "cube" to test out different things, which was just a sf::VertexArray.
The problem appears once I want to use multiple cubes since I have to use nested for loops (one for the number of cubes, one for the 8 vertices of the cubes) or just one for loop, but either way, I want to avoid doing it like that since it doesn't feel expandable and easy to use. I would like to be able to instantiate the cubes like this for example:
This is the current cube code:
And this is how I'm showing the vertices on the screen:
I'm using a single "cube" to test out different things, which was just a sf::VertexArray.
The problem appears once I want to use multiple cubes since I have to use nested for loops (one for the number of cubes, one for the 8 vertices of the cubes) or just one for loop, but either way, I want to avoid doing it like that since it doesn't feel expandable and easy to use. I would like to be able to instantiate the cubes like this for example:
sf::VertexArray cubes(sf::Cubes, 10); // create 10 cubes
and then draw them like so:window.draw(cubes);
I can't understand how to set up custom shapes tho and https://www.sfml-dev.org/tutorials/2.0/graphics-shape.php doesn't really help me. This is the current cube code:
struct Cube
{
float scale;
Vector3 pos;
Vector3 vertexLocal[8] =
{
// Front face
Vector3(-1.0, -1.0, 1.0),
Vector3(1.0, -1.0, 1.0),
Vector3(1.0, 1.0, 1.0),
Vector3(-1.0, 1.0, 1.0),
// Back face
Vector3(-1.0, -1.0, -1.0),
Vector3(1.0, -1.0, -1.0),
Vector3(1.0, 1.0, -1.0),
Vector3(-1.0, 1.0, -1.0)
};
Vector3 vertexGlobal[8];
float vertexDistances[8];
Cube(const float _scale)
{
scale = _scale;
for(int v = 0; v < 8; v++)
{
vertexGlobal[v] = Vector3(vertexLocal[v].x + pos.x, vertexLocal[v].y + pos.y, vertexLocal[v].z + pos.z);
vertexDistances[v] = sqrt((vertexLocal[v].x - pos.x)*(vertexLocal[v].x - pos.x) + (vertexLocal[v].y - pos.y)*(vertexLocal[v].y - pos.y) + (vertexLocal[v].z - pos.z)*(vertexLocal[v].z - pos.z));
vertexGlobal[v] *= scale;
vertexDistances[v] *= scale;
//vertexGlobal[i] = Vector3(vertexGlobal[i].x / 2, vertexGlobal[i].y / 2, vertexGlobal[i].z / 2);
vertexGlobal[v].UpdateVector();
}
}
void UpdateCube()
{
for(int i = 0; i < 8; i++)
{
vertexGlobal[i] = Vector3(vertexLocal[i].x + pos.x, vertexLocal[i].y + pos.y, vertexLocal[i].z + pos.z);
vertexGlobal[i] *= scale;
vertexGlobal[i].UpdateVector();
vertexLocal[i].UpdateVector();
}
}
};
{
float scale;
Vector3 pos;
Vector3 vertexLocal[8] =
{
// Front face
Vector3(-1.0, -1.0, 1.0),
Vector3(1.0, -1.0, 1.0),
Vector3(1.0, 1.0, 1.0),
Vector3(-1.0, 1.0, 1.0),
// Back face
Vector3(-1.0, -1.0, -1.0),
Vector3(1.0, -1.0, -1.0),
Vector3(1.0, 1.0, -1.0),
Vector3(-1.0, 1.0, -1.0)
};
Vector3 vertexGlobal[8];
float vertexDistances[8];
Cube(const float _scale)
{
scale = _scale;
for(int v = 0; v < 8; v++)
{
vertexGlobal[v] = Vector3(vertexLocal[v].x + pos.x, vertexLocal[v].y + pos.y, vertexLocal[v].z + pos.z);
vertexDistances[v] = sqrt((vertexLocal[v].x - pos.x)*(vertexLocal[v].x - pos.x) + (vertexLocal[v].y - pos.y)*(vertexLocal[v].y - pos.y) + (vertexLocal[v].z - pos.z)*(vertexLocal[v].z - pos.z));
vertexGlobal[v] *= scale;
vertexDistances[v] *= scale;
//vertexGlobal[i] = Vector3(vertexGlobal[i].x / 2, vertexGlobal[i].y / 2, vertexGlobal[i].z / 2);
vertexGlobal[v].UpdateVector();
}
}
void UpdateCube()
{
for(int i = 0; i < 8; i++)
{
vertexGlobal[i] = Vector3(vertexLocal[i].x + pos.x, vertexLocal[i].y + pos.y, vertexLocal[i].z + pos.z);
vertexGlobal[i] *= scale;
vertexGlobal[i].UpdateVector();
vertexLocal[i].UpdateVector();
}
}
};
And this is how I'm showing the vertices on the screen:
class Camera
{
public:
float nearClippingPlane, farClippingPlane, fieldOfView, focalLength;
Vector3 position, rotation, resolution;
vector<Vector3> verticesOnScreen, verticesOffScreen;
Camera(float _nearClippingPlane, float _farClippingPlane, float focal, Vector3 res)
{
nearClippingPlane = _nearClippingPlane;
farClippingPlane = _farClippingPlane;
focalLength = focal;
fieldOfView = 2 * atan(res.x / (2 * focal));
resolution = res;
if(!verticesOnScreen.empty())
verticesOnScreen.clear();
if(!verticesOffScreen.empty())
verticesOffScreen.clear();
}
Camera()
{
nearClippingPlane = 1.0f;
farClippingPlane = 100.0f;
fieldOfView = 60.0f;
resolution = Vector3(W_SCREEN, H_SCREEN, 0);
}
Vector3 WorldToCamera(Vector3 vertex)
{
//cout << "WorldToCamera: " << vertex.x << " : " << scaleFactor << endl;
vertex += position;
vertex.UpdateVector();
vertex.z *= -1; //invert the camera's view (or else it would appear we are looking "through" a mirror)
if(vertex.z < nearClippingPlane + position.z) //if the vertex's z coordinate is smaller than the near clipping plane's
vertex.z = nearClippingPlane; // distance from the camera, clip the vertex's z to the value of near clipping plane's distance
//treat camera's position as 0, 0, 0 if using verToCam variable
vertex.x *= (focalLength / vertex.z);
vertex.y *= (focalLength / vertex.z);
//cout << "wtc" << endl;
//cout << "WorldToCamera: " << output.x << " : " << scaleFactor << endl;
return vertex;
}
sf::Vector2f CameraToScreen(Vector3 vertex)
{
Vector3 cam = WorldToCamera(vertex);
cam.UpdateVector();
//cout << "CameraToScreen: " << cam.x << endl;
return sf::Vector2f(-cam.x + W_SCREEN/2, -cam.y + H_SCREEN/2); //center the coords to the screen and return them
}
};
I'm still a bit new to posting on forums, so if you need more information, just ask and I'll provide.
{
public:
float nearClippingPlane, farClippingPlane, fieldOfView, focalLength;
Vector3 position, rotation, resolution;
vector<Vector3> verticesOnScreen, verticesOffScreen;
Camera(float _nearClippingPlane, float _farClippingPlane, float focal, Vector3 res)
{
nearClippingPlane = _nearClippingPlane;
farClippingPlane = _farClippingPlane;
focalLength = focal;
fieldOfView = 2 * atan(res.x / (2 * focal));
resolution = res;
if(!verticesOnScreen.empty())
verticesOnScreen.clear();
if(!verticesOffScreen.empty())
verticesOffScreen.clear();
}
Camera()
{
nearClippingPlane = 1.0f;
farClippingPlane = 100.0f;
fieldOfView = 60.0f;
resolution = Vector3(W_SCREEN, H_SCREEN, 0);
}
Vector3 WorldToCamera(Vector3 vertex)
{
//cout << "WorldToCamera: " << vertex.x << " : " << scaleFactor << endl;
vertex += position;
vertex.UpdateVector();
vertex.z *= -1; //invert the camera's view (or else it would appear we are looking "through" a mirror)
if(vertex.z < nearClippingPlane + position.z) //if the vertex's z coordinate is smaller than the near clipping plane's
vertex.z = nearClippingPlane; // distance from the camera, clip the vertex's z to the value of near clipping plane's distance
//treat camera's position as 0, 0, 0 if using verToCam variable
vertex.x *= (focalLength / vertex.z);
vertex.y *= (focalLength / vertex.z);
//cout << "wtc" << endl;
//cout << "WorldToCamera: " << output.x << " : " << scaleFactor << endl;
return vertex;
}
sf::Vector2f CameraToScreen(Vector3 vertex)
{
Vector3 cam = WorldToCamera(vertex);
cam.UpdateVector();
//cout << "CameraToScreen: " << cam.x << endl;
return sf::Vector2f(-cam.x + W_SCREEN/2, -cam.y + H_SCREEN/2); //center the coords to the screen and return them
}
};