Does someone have a Frustum culling function for C++ OpenGL that is complete and works?

I have been looking for days now and everything that I have seen requires me to do some kind of conversion to try to figure out what the person means. I have completed two examples and both have failed.

I could use the sphere shape, but would settle for box if it works.

1 Like

i’ve shown you here how it can be done

you need to start easy …
checking if a sphere is colliding with a plane OR on a certain side of a plane is relatively easy
getting the 6 planes equations for the view frustum of a camera is also not too hard
merge these 2 steps, and you’ve got it …

once you have that, you can start to replace the sphere with an AABB / OBB

1 Like

I think that I have tried this and it not only included a lot of other things that weren’t supposed to be there and when it is maximized my objects disappear before they exit the side. I counted the objects and displayed them on the title bar

1 Like

the position of the bounding sphere enclosing your mesh needs to be in “eye-space”. if you have a “scale”-component in your “model-to-world”-matrix, you need to scale the radius of your bounding sphere too. it can be problematic if you scale the mesh differently in the x/y/z axis, using …

glm::scale(vec3(1, 2, 3))

for example … because the length of the radius depends then on the direction. do you have a simple example?

1 Like

This is something that I came up with myself. What it essentially does solve 2 equations one for the field of view and another for the aspect ratio. Too bad it doesn’t work.

#include "glm/glm.hpp"
//#include <iostream>
class FrustumCulling4
{
public:
	void setAngles(float fov, float aspect);
	bool isInside(glm::vec3 viewPos, glm::vec3 modpos);
private:
	float widthAng;
	float heightAng;
	float func1(float inv, float diaglen);
	float func2(float inv, float aspect);
	bool inVector(glm::vec3 viewPos, glm::vec3 location);
	float getAngle(float depth, float side);
};
source:

#include "FrustumCulling4.h"
 
void FrustumCulling4::setAngles(float fov, float aspect) {
	float diaglen = 2 * sin(glm::radians(fov) / 2);
 
	float wa, ha1, ha2;
	wa = 0;
	for (float wh = 2; wh > pow(2, -32); wh /= 2) {
		ha1 = 0;
		ha2 = 0;
		for (float hh1 = 2; hh1 > pow(2, -32); hh1 /= 2) {
			if (func1(ha1 + hh1, diaglen) > wa + wh) ha1 += hh1;
		}
 
		for (float hh2 = 2; hh2 > pow(2, -32); hh2 /= 2) {
			if (func2(ha2 + hh2, aspect) < wa + wh) ha2 += hh2;
		}
		if (ha1 > ha2) wa += wh;
	}
	widthAng = wa;
	heightAng = ha1;
}
 
bool FrustumCulling4::isInside(glm::vec3 viewPos, glm::vec3 modpos) {
	for (float iz = -1; iz < 2; iz += 2) {
		for (float iy = -1; iy < 2; iy += 2) {
			for (float ix = -1; ix < 2; ix += 2) if (!inVector(viewPos, modpos + glm::vec3(ix, iy, iz))) {
				return false;
			}
		}
	}
	
	return true;
}
 
float FrustumCulling4::func1(float inv, float diaglen) {
	float hlen = pow(sin(inv / 2) * 2, 2);
	float spart = pow(pow(diaglen, 2) - hlen, .5) / 2;
	return asin(spart) * 2;
}
float FrustumCulling4::func2(float inv, float aspect) {
	return aspect * inv;
}
 
bool FrustumCulling4::inVector(glm::vec3 viewPos, glm::vec3 location) {
	glm::vec3 myVector = viewPos - location;
	if (myVector.z <= 0) {
		return false;
	}
	if (getAngle(myVector.z, myVector.x) > widthAng / 2) return false;
	if (getAngle(myVector.z, myVector.y) > heightAng / 2) return false;
	return true;
}
 
float FrustumCulling4::getAngle(float depth, float side) {
	float hypot = pow(depth * depth + side * side, .5);
	return asin(side / hypot);
}