29 #define _USE_MATH_DEFINES 42 #include <glad/glad.h> 46 #ifndef GL_EXT_separate_specular_color 47 #define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 48 #define GL_SINGLE_COLOR_EXT 0x81F9 49 #define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA 50 #endif // GL_EXT_separate_specular_color 104 #define P_TEX_WIDTH 8 // Particle texture dimensions 105 #define P_TEX_HEIGHT 8 106 #define F_TEX_WIDTH 16 // Floor texture dimensions 107 #define F_TEX_HEIGHT 16 114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
115 0x00, 0x00, 0x11, 0x22, 0x22, 0x11, 0x00, 0x00,
116 0x00, 0x11, 0x33, 0x88, 0x77, 0x33, 0x11, 0x00,
117 0x00, 0x22, 0x88, 0xff, 0xee, 0x77, 0x22, 0x00,
118 0x00, 0x22, 0x77, 0xee, 0xff, 0x88, 0x22, 0x00,
119 0x00, 0x11, 0x33, 0x77, 0x88, 0x33, 0x11, 0x00,
120 0x00, 0x00, 0x11, 0x33, 0x22, 0x11, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
126 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
127 0xff, 0xf0, 0xcc, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
128 0xf0, 0xcc, 0xee, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0x66, 0x30, 0x30, 0x30, 0x20, 0x30, 0x30,
129 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xee, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
130 0xf0, 0xf0, 0xf0, 0xf0, 0xcc, 0xf0, 0xf0, 0xf0, 0x30, 0x30, 0x55, 0x30, 0x30, 0x44, 0x30, 0x30,
131 0xf0, 0xdd, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
132 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0x30,
133 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x33, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
134 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
135 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x30, 0x30, 0xf0, 0xff, 0xf0, 0xf0, 0xdd, 0xf0, 0xf0, 0xff,
136 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x55, 0x33, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0,
137 0x30, 0x44, 0x66, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
138 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xaa, 0xf0, 0xf0, 0xcc, 0xf0,
139 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xdd, 0xf0,
140 0x30, 0x30, 0x30, 0x77, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
141 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
151 #define MAX_PARTICLES 3000 154 #define LIFE_SPAN 8.f 157 #define BIRTH_INTERVAL (LIFE_SPAN/(float)MAX_PARTICLES) 160 #define PARTICLE_SIZE 0.7f 169 #define FRICTION 0.75f 172 #define FOUNTAIN_HEIGHT 3.f 175 #define FOUNTAIN_RADIUS 1.6f 178 #define MIN_DELTA_T (BIRTH_INTERVAL * 0.5f) 227 printf(
"Usage: particles [-bfhs]\n");
228 printf(
"Options:\n");
229 printf(
" -f Run in full screen\n");
230 printf(
" -h Display this help\n");
231 printf(
" -s Run program as single thread (default is to use two threads)\n");
233 printf(
"Program runtime controls:\n");
234 printf(
" W Toggle wireframe mode\n");
235 printf(
" Esc Exit program\n");
245 float xy_angle, velocity;
253 p->
vz = 0.7f + (0.3f / 4096.f) * (
float) (rand() & 4095);
256 xy_angle = (2.f * (float) M_PI / 4096.
f) * (float) (rand() & 4095);
257 p->
vx = 0.4f * (float) cos(xy_angle);
258 p->
vy = 0.4f * (float) sin(xy_angle);
261 velocity =
VELOCITY * (0.8f + 0.1f * (float) (sin(0.5 * t) + sin(1.31 * t)));
267 p->
r = 0.7f + 0.3f * (float) sin(0.34 * t + 0.1);
268 p->
g = 0.6f + 0.4f * (float) sin(0.63 * t + 1.1);
269 p->
b = 0.6f + 0.4f * (float) sin(0.91 * t + 2.1);
272 glow_pos[0] = 0.4f * (float) sin(1.34 * t);
273 glow_pos[1] = 0.4f * (float) sin(3.11 * t);
291 #define FOUNTAIN_R2 (FOUNTAIN_RADIUS+PARTICLE_SIZE/2)*(FOUNTAIN_RADIUS+PARTICLE_SIZE/2) 369 if (!particles[i].active)
388 #define BATCH_PARTICLES 70 // Number of particles to draw in each batch 391 #define PARTICLE_VERTS 4 // Number of vertices per particle 395 int i, particle_count;
400 Vec3 quad_lower_left, quad_lower_right;
459 clock_gettime(CLOCK_REALTIME, &ts);
460 ts.tv_nsec += 100 * 1000 * 1000;
461 ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
462 ts.tv_nsec %= 1000 * 1000 * 1000;
484 alpha = 4.f * pptr->
life;
503 vptr->
x = pptr->
x + quad_lower_left.
x;
504 vptr->
y = pptr->
y + quad_lower_left.
y;
505 vptr->
z = pptr->
z + quad_lower_left.
z;
512 vptr->
x = pptr->
x + quad_lower_right.
x;
513 vptr->
y = pptr->
y + quad_lower_right.
y;
514 vptr->
z = pptr->
z + quad_lower_right.
z;
521 vptr->
x = pptr->
x - quad_lower_left.
x;
522 vptr->
y = pptr->
y - quad_lower_left.
y;
523 vptr->
z = pptr->
z - quad_lower_left.
z;
530 vptr->
x = pptr->
x - quad_lower_right.
x;
531 vptr->
y = pptr->
y - quad_lower_right.
y;
532 vptr->
z = pptr->
z - quad_lower_right.
z;
579 #define FOUNTAIN_SIDE_POINTS 14 580 #define FOUNTAIN_SWEEP_STEPS 32 584 1.2f, 0.f, 1.f, 0.2f, 0.41f, 0.3f, 0.4f, 0.35f,
585 0.4f, 1.95f, 0.41f, 2.f, 0.8f, 2.2f, 1.2f, 2.4f,
586 1.5f, 2.7f, 1.55f,2.95f, 1.6f, 3.f, 1.f, 3.f,
592 1.0000f, 0.0000f, 0.6428f, 0.7660f, 0.3420f, 0.9397f, 1.0000f, 0.0000f,
593 1.0000f, 0.0000f, 0.3420f,-0.9397f, 0.4226f,-0.9063f, 0.5000f,-0.8660f,
594 0.7660f,-0.6428f, 0.9063f,-0.4226f, 0.0000f,1.00000f, 0.0000f,1.00000f,
595 0.0000f,1.00000f, 0.0000f,1.00000f
605 static GLuint fountain_list = 0;
627 x = (float) cos(angle);
628 y = (float) sin(angle);
668 x = (float) (fabs(x1) < fabs(x2) ? fabs(x1) : fabs(x2));
669 y = (float) (fabs(y1) < fabs(y2) ? fabs(y1) : fabs(y2));
676 x = (x1 +
x2) * 0.5
f;
677 y = (y1 +
y2) * 0.5
f;
705 static GLuint floor_list = 0;
749 float l1pos[4], l1amb[4], l1dif[4], l1spec[4];
750 float l2pos[4], l2amb[4], l2dif[4], l2spec[4];
753 l1pos[0] = 0.f; l1pos[1] = -9.f; l1pos[2] = 8.f; l1pos[3] = 1.f;
754 l1amb[0] = 0.2f; l1amb[1] = 0.2f; l1amb[2] = 0.2f; l1amb[3] = 1.f;
755 l1dif[0] = 0.8f; l1dif[1] = 0.4f; l1dif[2] = 0.2f; l1dif[3] = 1.f;
756 l1spec[0] = 1.f; l1spec[1] = 0.6f; l1spec[2] = 0.2f; l1spec[3] = 0.f;
759 l2pos[0] = -15.f; l2pos[1] = 12.f; l2pos[2] = 1.5f; l2pos[3] = 1.f;
760 l2amb[0] = 0.f; l2amb[1] = 0.f; l2amb[2] = 0.f; l2amb[3] = 1.f;
761 l2dif[0] = 0.2f; l2dif[1] = 0.4f; l2dif[2] = 0.8f; l2dif[3] = 1.f;
762 l2spec[0] = 0.2f; l2spec[1] = 0.6f; l2spec[2] = 1.f; l2spec[3] = 0.f;
788 double xpos,
ypos, zpos, angle_x, angle_y, angle_z;
789 static double t_old = 0.0;
794 dt = (float) (t - t_old);
798 65.
f * (
float) M_PI / 180.
f,
813 angle_x = 90.0 - 10.0;
814 angle_y = 10.0 * sin(0.3 * t);
821 xpos = 15.0 * sin((M_PI / 180.0) * angle_z) +
822 2.0 * sin((M_PI / 180.0) * 3.1 * t);
823 ypos = -15.0 * cos((M_PI / 180.0) * angle_z) +
824 2.0 * cos((M_PI / 180.0) * 2.9 * t);
825 zpos = 4.0 + 2.0 * cos((M_PI / 180.0) * 4.9 * t);
912 clock_gettime(CLOCK_REALTIME, &ts);
913 ts.tv_nsec += 100 * 1000 * 1000;
914 ts.tv_sec += ts.tv_nsec / (1000 * 1000 * 1000);
915 ts.tv_nsec %= 1000 * 1000 * 1000;
941 int main(
int argc,
char** argv)
944 thrd_t physics_thread = 0;
950 fprintf(stderr,
"Failed to initialize GLFW\n");
954 while ((ch =
getopt(argc, argv,
"fh")) != -1)
988 fprintf(stderr,
"Failed to create GLFW window\n");
#define glDisableClientState
#define GL_TEXTURE_MAG_FILTER
static int physics_thread_main(void *arg)
GLboolean GLboolean GLboolean b
The header of the GLFW 3 API.
int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
GLFWAPI GLFWglproc glfwGetProcAddress(const char *procname)
Returns the address of the specified function for the current context.
#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT
const GLfloat floor_shininess
#define GL_TRIANGLE_STRIP
int mtx_init(mtx_t *mtx, int type)
void *(* GLADloadproc)(const char *name)
static GLFWwindow * window
GLdouble GLdouble GLdouble y2
static void init_particle(PARTICLE *p, double t)
static void particle_engine(double t, float dt)
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
GLFWAPI const GLFWvidmode * glfwGetVideoMode(GLFWmonitor *monitor)
Returns the current mode of the specified monitor.
struct GLFWmonitor GLFWmonitor
#define GLFW_REFRESH_RATE
Monitor refresh rate hint.
static void resize_callback(GLFWwindow *window, int width, int height)
GLint GLint GLsizei GLsizei GLsizei depth
const GLfloat fountain_diffuse[4]
GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow *window, GLFWframebuffersizefun cbfun)
Sets the framebuffer resize callback for the specified window.
int getopt(int argc, char *const argv[], const char *optstring)
#define FOUNTAIN_SIDE_POINTS
static void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float n, float f)
static void draw_scene(GLFWwindow *window, double t)
#define GL_TEXTURE_WRAP_T
static const float fountain_normal[FOUNTAIN_SIDE_POINTS *2]
#define GLFW_CURSOR_DISABLED
int main(int argc, char **argv)
GLFWAPI int glfwInit(void)
Initializes the GLFW library.
#define glInterleavedArrays
#define GLFW_RED_BITS
Framebuffer bit depth hint.
static void draw_fountain(void)
GLfloat GLfloat GLfloat alpha
static void tessellate_floor(float x1, float y1, float x2, float y2, int depth)
int mtx_unlock(mtx_t *mtx)
#define GL_COLOR_BUFFER_BIT
#define GL_FRONT_AND_BACK
int cnd_init(cnd_t *cond)
static const float fountain_side[FOUNTAIN_SIDE_POINTS *2]
GLFWAPI void glfwSwapInterval(int interval)
Sets the swap interval for the current context.
#define GL_SEPARATE_SPECULAR_COLOR_EXT
#define GL_UNPACK_ALIGNMENT
GLint GLsizei GLsizei height
GLFWAPI void glfwSwapBuffers(GLFWwindow *window)
Swaps the front and back buffers of the specified window.
GLFWAPI void glfwMakeContextCurrent(GLFWwindow *window)
Makes the context of the specified window current for the calling thread.
#define GL_TEXTURE_MIN_FILTER
const GLfloat fog_color[4]
static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
static void draw_particles(GLFWwindow *window, double t, float dt)
int thrd_join(thrd_t thr, int *res)
#define GLFW_GREEN_BITS
Framebuffer bit depth hint.
const GLfloat floor_specular[4]
GLAPI int gladLoadGLLoader(GLADloadproc)
#define GL_DEPTH_BUFFER_BIT
static const textual_icon exit
GLFWAPI void glfwSetWindowShouldClose(GLFWwindow *window, int value)
Sets the close flag of the specified window.
#define FOUNTAIN_SWEEP_STEPS
GLFWAPI GLFWwindow * glfwCreateWindow(int width, int height, const char *title, GLFWmonitor *monitor, GLFWwindow *share)
Creates a window and its associated context.
const unsigned char floor_texture[F_TEX_WIDTH *F_TEX_HEIGHT]
GLuint GLfloat GLfloat GLfloat x1
static void setup_lights(void)
#define GL_COMPILE_AND_EXECUTE
int cnd_signal(cnd_t *cond)
GLFWAPI GLFWmonitor * glfwGetPrimaryMonitor(void)
Returns the primary monitor.
GLFWAPI void glfwDestroyWindow(GLFWwindow *window)
Destroys the specified window and its context.
GLFWAPI void glfwGetFramebufferSize(GLFWwindow *window, int *width, int *height)
Retrieves the size of the framebuffer of the specified window.
const unsigned char particle_texture[P_TEX_WIDTH *P_TEX_HEIGHT]
const GLfloat fountain_shininess
GLFWAPI void glfwTerminate(void)
Terminates the GLFW library.
#define GL_MODELVIEW_MATRIX
GLFWAPI void glfwPollEvents(void)
Processes all pending events.
#define GLFW_BLUE_BITS
Framebuffer bit depth hint.
GLFWAPI int glfwExtensionSupported(const char *extension)
Returns whether the specified extension is available.
static void draw_floor(void)
static void update_particle(PARTICLE *p, float dt)
const GLfloat floor_diffuse[4]
#define GL_TEXTURE_COORD_ARRAY
const GLfloat fountain_specular[4]
#define GL_TEXTURE_WRAP_S
static float glow_color[4]
struct GLFWwindow GLFWwindow
GLFWAPI void glfwWindowHint(int hint, int value)
Sets the specified window hint to the desired value.
static PARTICLE particles[MAX_PARTICLES]
GLFWAPI int glfwWindowShouldClose(GLFWwindow *window)
Checks the close flag of the specified window.