Beispiel #1
0
void DXPrimitives::DrawLineCircle(vec3 position, float radius, vec3 axisOfRotation)
{
	vec3 referenceAxis = UNIT_X;
	if(axisOfRotation == referenceAxis)
		referenceAxis = UNIT_Z;

	vec3 rotPoint = cross(axisOfRotation, referenceAxis) * radius;
	const int numSegments = 30;
	float* verts = new float[numSegments * vertexSize];
	for(int i = 0; i < numSegments; i++)
	{
		float theta = 2.0f * M_PI * float(i) / float(numSegments - 1);
		quaternion quat = quat_from_axis_angle(axisOfRotation, theta);
		vec3 point = quat * rotPoint;

		verts[i*vertexSize+0] = point.x + position.x;
		verts[i*vertexSize+1] = point.y + position.y;
		verts[i*vertexSize+2] = point.z + position.z;
		verts[i*vertexSize+3] = 1.0f;
		verts[i*vertexSize+4] = 0.5f;
		verts[i*vertexSize+5] = 0.5f;
	}
	DrawPrimitives(verts, numSegments, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP);
	delete[] verts;
}
Beispiel #2
0
void quat_mul_axis_angle(const Quat q, const Vec3f axis, const float angle, Quat r) {
    if( (fabs(axis[0]) < CUTE_EPSILON && fabs(axis[1]) < CUTE_EPSILON && fabs(axis[2]) < CUTE_EPSILON) ||
        fabs(angle) < CUTE_EPSILON )
    {
        quat_copy(q, r);
    }

    Quat rotation = {0};
    quat_from_axis_angle(axis, angle, rotation);
    quat_mul(q, rotation, r);
}
Beispiel #3
0
void quat_from_vec_pair(const Vec3f a, const Vec3f b, Quat q) {
    Vec4f axis;
    vec_cross(a,b,axis);

    float angle;
    vec_angle(a,b,&angle);

    if( (fabs(axis[0]) < CUTE_EPSILON && fabs(axis[1]) < CUTE_EPSILON && fabs(axis[2]) < CUTE_EPSILON) ||
        fabs(angle) < CUTE_EPSILON )
    {
        quat_identity(q);
    }

    quat_from_axis_angle(axis, angle, q);
}
Beispiel #4
0
int32_t main(int32_t argc, char *argv[]) {
    if( init_sdl2() ) {
        return 1;
    }

    int width = 1280;
    int height = 720;

    SDL_Window* window;
    sdl2_window("cute3d: " __FILE__, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, &window);

    SDL_GLContext* context;
    sdl2_glcontext(3, 2, window, &context);

    if( init_shader() ) {
        return 1;
    }

    if( init_canvas(width, height) ) {
        return 1;
    }
    canvas_create("global_dynamic_canvas", &global_dynamic_canvas);
    canvas_create("global_static_canvas", &global_static_canvas);

    struct Vbo vbo = {0};
    vbo_create(&vbo);
    vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX, 3, GL_FLOAT, GL_STATIC_DRAW);
    vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX_NORMAL, 3, GL_FLOAT, GL_STATIC_DRAW);
    vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX_COLOR, 4, GL_UNSIGNED_BYTE, GL_STATIC_DRAW);
    vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX_NORMAL, NORMAL_SIZE, GL_FLOAT, GL_STATIC_DRAW);

    struct Ibo ibo = {0};
    ibo_create(GL_TRIANGLES, GL_UNSIGNED_INT, GL_STATIC_DRAW, &ibo);

    struct SolidTetrahedron hard_tetrahedron = {0};
    struct SolidBox hard_cube = {0};
    struct SolidSphere16 hard_sphere16 = {0};
    struct SolidSphere32 hard_sphere32 = {0};
    solid_tetrahedron_create(1.0, (Color){255, 0, 0, 255}, &hard_tetrahedron);
    solid_cube_create(0.5, (Color){0, 255, 0, 255}, &hard_cube);
    solid_sphere16_create(16, 8, 0.75, (Color){0, 255, 255, 255}, &hard_sphere16);
    solid_sphere32_create(32, 16, 0.75, (Color){255, 255, 0, 255}, &hard_sphere32);

    solid_optimize((struct Solid*)&hard_tetrahedron);
    solid_optimize((struct Solid*)&hard_cube);
    solid_optimize((struct Solid*)&hard_sphere16);
    solid_optimize((struct Solid*)&hard_sphere32);

    struct VboMesh hard_tetrahedron_mesh, hard_box_mesh, hard_cube_mesh, hard_sphere16_mesh, hard_sphere32_mesh;
    vbo_mesh_create_from_solid((struct Solid*)&hard_tetrahedron, &vbo, &ibo, &hard_tetrahedron_mesh);
    vbo_mesh_create_from_solid((struct Solid*)&hard_cube, &vbo, &ibo, &hard_cube_mesh);
    vbo_mesh_create_from_solid((struct Solid*)&hard_sphere16, &vbo, &ibo, &hard_sphere16_mesh);
    vbo_mesh_create_from_solid((struct Solid*)&hard_sphere32, &vbo, &ibo, &hard_sphere32_mesh);

    struct SolidTetrahedron smooth_tetrahedron = {0};
    struct SolidBox smooth_cube = {0};
    struct SolidSphere16 smooth_sphere16 = {0};
    struct SolidSphere32 smooth_sphere32 = {0};
    solid_tetrahedron_create(1.0, (Color){255, 0, 0, 255}, &smooth_tetrahedron);
    solid_cube_create(0.5, (Color){0, 255, 0, 255}, &smooth_cube);
    solid_sphere16_create(16, 8, 0.75, (Color){0, 255, 255, 255}, &smooth_sphere16);
    solid_sphere32_create(32, 16, 0.75, (Color){255, 255, 0, 255}, &smooth_sphere32);

    solid_optimize((struct Solid*)&smooth_tetrahedron);
    solid_optimize((struct Solid*)&smooth_cube);
    solid_optimize((struct Solid*)&smooth_sphere16);
    solid_optimize((struct Solid*)&smooth_sphere32);
    solid_smooth_normals((struct Solid*)&smooth_tetrahedron, smooth_tetrahedron.normals, smooth_tetrahedron.normals);
    solid_smooth_normals((struct Solid*)&smooth_cube, smooth_cube.normals, smooth_cube.normals);
    solid_smooth_normals((struct Solid*)&smooth_sphere16, smooth_sphere16.normals, smooth_sphere16.normals);
    solid_smooth_normals((struct Solid*)&smooth_sphere32, smooth_sphere32.normals, smooth_sphere32.normals);

    struct VboMesh smooth_tetrahedron_mesh, smooth_box_mesh, smooth_cube_mesh, smooth_sphere16_mesh, smooth_sphere32_mesh;
    vbo_mesh_create_from_solid((struct Solid*)&smooth_tetrahedron, &vbo, &ibo, &smooth_tetrahedron_mesh);
    vbo_mesh_create_from_solid((struct Solid*)&smooth_cube, &vbo, &ibo, &smooth_cube_mesh);
    vbo_mesh_create_from_solid((struct Solid*)&smooth_sphere16, &vbo, &ibo, &smooth_sphere16_mesh);
    vbo_mesh_create_from_solid((struct Solid*)&smooth_sphere32, &vbo, &ibo, &smooth_sphere32_mesh);

    struct Arcball arcball = {0};
    arcball_create(width, height, (Vec4f){2.5,17.0,17.0,1.0}, (Vec4f){2.5,0.0,0.0,1.0}, 0.1, 100.0, &arcball);

    float circular_motion_angle = 0.0f;
    float circular_motion_speed = (2.0f*PI)/30;
    float circular_motion_radius = 12.0f;

    Vec3f light_position = { circular_motion_radius, 10.0, circular_motion_radius };
    Vec3f light_direction = {0};
    vec_sub((Vec3f){0.0f, 0.0f, 0.0f}, light_position, light_direction);
    vec_normalize(light_direction, light_direction);

    Vec3f eye_position = {0};
    vec_copy3f(arcball.camera.pivot.position, eye_position);

    Color ambiance = {50, 25, 150, 255};
    Color specular = {255, 255, 255, 255};
    float material_shininess = 1.0;
    Vec4f material_coefficients = { 0.8, 0.2, 0.0, 0.0 };

    // flat
    struct Shader flat_shader = {0};
    shader_create(&flat_shader);
    shader_attach(&flat_shader, GL_VERTEX_SHADER, "prefix.vert", 1, "flat_shading.vert");
    shader_attach(&flat_shader, GL_FRAGMENT_SHADER, "prefix.frag", 1, "flat_shading.frag");
    shader_make_program(&flat_shader, SHADER_DEFAULT_NAMES, "flat_shader");

    shader_set_uniform_3f(&flat_shader, flat_shader.program, SHADER_UNIFORM_LIGHT_DIRECTION, 3, GL_FLOAT, light_direction);
    shader_set_uniform_4f(&flat_shader, flat_shader.program, SHADER_UNIFORM_AMBIENT_LIGHT, 4, GL_UNSIGNED_BYTE, ambiance);

    // gouraud
    struct Shader gouraud_shader = {0};
    shader_create(&gouraud_shader);
    shader_attach(&gouraud_shader, GL_VERTEX_SHADER, "prefix.vert", 1, "gouraud_shading.vert");
    shader_attach(&gouraud_shader, GL_FRAGMENT_SHADER, "prefix.frag", 1, "gouraud_shading.frag");
    shader_make_program(&gouraud_shader, SHADER_DEFAULT_NAMES, "gouraud_shader");

    shader_set_uniform_3f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_LIGHT_POSITION, 3, GL_FLOAT, light_position);
    shader_set_uniform_3f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_EYE_POSITION, 3, GL_FLOAT, eye_position);
    shader_set_uniform_4f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_AMBIENT_LIGHT, 4, GL_UNSIGNED_BYTE, ambiance);
    shader_set_uniform_4f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_SPECULAR_LIGHT, 4, GL_UNSIGNED_BYTE, specular);
    shader_set_uniform_1f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_MATERIAL_SHININESS, 1, GL_FLOAT, &material_shininess);
    shader_set_uniform_4f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_MATERIAL_COEFFICIENTS, 4, GL_FLOAT, material_coefficients);
    shader_set_uniform_3f(&gouraud_shader, gouraud_shader.program, SHADER_UNIFORM_EYE_POSITION, 3, GL_FLOAT, &arcball.camera.pivot.position);

    Mat identity = IDENTITY_MAT;
    draw_grid(&global_static_canvas, 0, identity, (Color){127, 127, 127, 255}, 0.03f, 12.0f, 12.0f, 12);

    Mat shading_label_transform = IDENTITY_MAT;
    Quat text_rotation = IDENTITY_QUAT;
    quat_from_axis_angle((Vec3f)X_AXIS, -PI/2.0f, text_rotation);
    mat_rotate(shading_label_transform, text_rotation, shading_label_transform);
    mat_translate(shading_label_transform, (float[4]){ 6.5, 0.0, -2.5, 1.0 }, shading_label_transform);
Beispiel #5
0
bool arcball_event(struct Arcball* arcball, SDL_Event event) {
    static int32_t mouse_down = 0;
    static const float rotation_slowness_factor = 0.25f;
    static int32_t next_flipped = 0;

    // - arcball rotation is performed by dragging the mouse, so I just keep track of when
    // a mouse button is pressed and released between calls to this function by setting a
    // static variable mouse_down to the button number when a button is pressed and back
    // to 0 when that button is released
    if( event.type == SDL_MOUSEBUTTONDOWN && mouse_down == 0 ) {
        mouse_down = event.button.button;
    } else if( event.type == SDL_MOUSEBUTTONUP && mouse_down == event.button.button ) {
        arcball->flipped = next_flipped;
        mouse_down = 0;
    }

    if( mouse_down == arcball->translate_button && event.type == SDL_MOUSEMOTION ) {
        SDL_MouseMotionEvent mouse = event.motion;
        float eye_distance = arcball->camera.pivot.eye_distance;

        // - when an mouse motion event occurs, and mouse_down to the translation_button so we compute
        // a camera translation
        // - the camera should pan around on the x-z-plane, keeping its height and orientation
        Quat inverted_orientation = {0};
        quat_invert(arcball->camera.pivot.orientation, inverted_orientation);

        // - the sideways translation is computed by taking the right_axis and orienting it with
        // the cameras orientation, the way I set up the lookat implementation this should always
        // result in a vector parallel to the x-z-plane
        Vec4f right_axis = RIGHT_AXIS;
        vec_rotate4f(right_axis, inverted_orientation, right_axis);
        if( mouse.xrel != 0 ) {
            // - then we'll just multiply the resulting axis with the mouse x relative movement, inversely
            // scaled by how far we are away from what we are looking at (farer means faster, nearer
            // means slower), the translation_factor is just a value that felt good when this was implemented
            Vec4f x_translation = {0};
            vec_mul1f(right_axis, (float)mouse.xrel/arcball->translate_factor*eye_distance, x_translation);

            // - finally just add the x_translation to the target and position so that the whole arcball moves
            vec_add(arcball->target, x_translation, arcball->target);
            vec_add(arcball->camera.pivot.position, x_translation, arcball->camera.pivot.position);
        }

        // - the z translation can't be done along the orientated forward axis because that would include
        // the camera pitch, here, same as above, we need an axis that is parallel to the x-z-plane
        Vec4f up_axis = UP_AXIS;
        if( mouse.yrel != 0 ) {
            // - luckily such an axis is easily computed from the crossproduct of the orientated right_axis and
            // the default up_axis, the result is an axis pointing in the direction of the cameras forward axis,
            // while still being parallel to the x-z-plane
            Vec4f forward_axis;
            vec_cross(right_axis, up_axis, forward_axis);

            // - same as above
            Vec4f z_translation;
            vec_mul1f(forward_axis, (float)mouse.yrel/arcball->translate_factor*eye_distance, z_translation);

            // - dito
            vec_add(arcball->target, z_translation, arcball->target);
            vec_add(arcball->camera.pivot.position, z_translation, arcball->camera.pivot.position);
        }
    } else if( mouse_down == arcball->rotate_button && event.type == SDL_MOUSEMOTION ) {
        SDL_MouseMotionEvent mouse = event.motion;

        // - above case was translation, this is an rotation occuring: mouse_down is equal to the
        // rotation_button and the event is a mouse motion
        // - the camera needs to rotate around the target while keeping its height, orientation and
        // without _any_ rolling

        // - we want only yaw and pitch movement
        // - yaw is easy, just use the fixed up_axis and create a rotation the rotates around it
        // by the mouse x relative movement (converted to radians)
        // - the flipped value indicates if the camera is flipped over, so we'll just use that to
        // change the sign of the yaw to make the mouse movement on the screen always correctly
        // relates to the movement of the rotation
        Vec4f up_axis = UP_AXIS;
        Quat yaw_rotation = {0};
        quat_from_axis_angle(up_axis, arcball->flipped * PI/180 * mouse.xrel * rotation_slowness_factor, yaw_rotation);

        // - pitch is a little more involved, I need to compute the orientated right axis and use
        // that to compute the pitch_rotation
        Quat inverted_orientation = {0};
        quat_invert(arcball->camera.pivot.orientation, inverted_orientation);

        Vec4f right_axis = RIGHT_AXIS;
        vec_rotate4f(right_axis, inverted_orientation, right_axis);

        Quat pitch_rotation = {0};
        quat_from_axis_angle(right_axis, -PI/180 * mouse.yrel * rotation_slowness_factor, pitch_rotation);

        // - combine yaw and pitch into a single rotation
        Quat rotation = {0};
        quat_mul(yaw_rotation, pitch_rotation, rotation);

        // - orbit is the position translated to the coordinate root
        // - the yaw and pitch rotation is applied to the orbit
        // - orbit is translated back and replaces the camera position
        Vec4f orbit = {0};
        vec_sub(arcball->camera.pivot.position, arcball->target, orbit);
        vec_rotate4f(orbit, rotation, orbit);
        vec_add(arcball->target, orbit, arcball->camera.pivot.position);

        // - after updating the position we just call lookat to compute the new
        // orientation, and also set the flipped state
        next_flipped = pivot_lookat(&arcball->camera.pivot, arcball->target);
    }

    if( event.type == SDL_MOUSEWHEEL ) {
        SDL_MouseWheelEvent wheel = event.wheel;

        // - zooming when mouse wheel event happens
        float* eye_distance = &arcball->camera.pivot.eye_distance;
        if( (*eye_distance > arcball->camera.frustum.z_near || wheel.y < 0) &&
            (*eye_distance < arcball->camera.frustum.z_far || wheel.y > 0))
        {
            // - just going back and forth along the oriented forward axis, using wheel
            // y motion inversly scaled by the eye_distance, similar to what is done
            // for the translation above (farer == faster zoom, nearer == slower zoom)
            Quat inverted_orientation = {0};
            quat_invert(arcball->camera.pivot.orientation, inverted_orientation);

            Vec4f forward_axis = FORWARD_AXIS;
            vec_rotate4f(forward_axis, inverted_orientation, forward_axis);

            Vec4f zoom = {0};
            vec_mul1f(forward_axis, wheel.y/arcball->zoom_factor*(*eye_distance), zoom);
            vec_add(arcball->camera.pivot.position, zoom, arcball->camera.pivot.position);

            // - eye_distance is kept in camera state, so we need to update it here
            *eye_distance = vlength(arcball->camera.pivot.position);
        }
    }

    return true;
}
#include <math.h>
#include <stdlib.h>

#include "catch.hpp"

XMFLOAT3 up(0, 1, 0);

SCENARIO("Quaternion and Axis-Rotation Transforms behave equivalently") {
	GIVEN("Two equivalent transforms of different rotation implementations") {

		AxisTransform at(XMFLOAT3(1, 1, 0), XMFLOAT3(1, 1, 1), up, 90);

		// we must convert to the equivalent quaternion-- putting the hard-coded values
		// in ourselves is counterintuitive (unless you're really good at 4D geometry)
		auto quat = quat_from_axis_angle(up, 90);
		QuaternionTransform qt(XMFLOAT3(1, 1, 0), XMFLOAT3(1, 1, 1), quat);

		WHEN("Their world matrices are calculated") {

			auto axis_mat = make_worldmatrix(at);
			auto quat_mat = make_worldmatrix(qt);

			THEN("They should be roughly equivalent") {

				// if each respective member float is roughly equivalent, then we're good
				for (auto i = 0; i < 4; ++i) for (auto j = 0; j < 4; ++j) {
					CHECK(quat_mat.m[i][j] == Approx(axis_mat.m[i][j]));
				}
			}
Beispiel #7
0
int32_t main(int32_t argc, char *argv[]) {
    printf("<<watchlist//>>\n");

    if( init_sdl2() ) {
        return 1;
    }

    uint32_t width = 1280;
    uint32_t height = 720;

    SDL_Window* window;
    sdl2_window("test-canvas", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, &window);

    SDL_GLContext* context;
    sdl2_glcontext(3, 2, window, &context);

    if( init_shader() ) {
        return 1;
    }

    if( init_canvas() ) {
        return 1;
    }

    printf("sizeof(struct Canvas): %zu\n", sizeof(struct Canvas));
    printf("MAX_OGL_PRIMITIVES: %d\n", MAX_OGL_PRIMITIVES);

    struct Arcball arcball = {0};
    arcball_create(width, height, (Vec4f){1.0,2.0,8.0,1.0}, (Vec4f){0.0,0.0,0.0,1.0}, 0.01, 1000.0, &arcball);

    struct Character symbols[256] = {0};
    default_font_create(symbols);

    struct Shader shader = {0};
    shader_create(&shader);
    shader_attach(&shader, GL_VERTEX_SHADER, "prefix.vert", 1, "volumetric_lines.vert");
    shader_attach(&shader, GL_FRAGMENT_SHADER, "prefix.frag", 1, "volumetric_lines.frag");
    shader_make_program(&shader, SHADER_DEFAULT_NAMES, "lines_shader");

    struct Font font = {0};
    font_create_from_characters(L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,:;", 256, symbols, 9, 3, global_default_font_palette, &font);

    struct Canvas text_canvas = {0};
    canvas_create("text_canvas", &text_canvas);
    canvas_add_attribute(&text_canvas, SHADER_ATTRIBUTE_VERTEX, 3, GL_FLOAT);
    canvas_add_attribute(&text_canvas, SHADER_ATTRIBUTE_VERTEX_COLOR, 4, GL_UNSIGNED_BYTE);
    canvas_add_attribute(&text_canvas, SHADER_ATTRIBUTE_VERTEX_TEXCOORD, 2, GL_FLOAT);
    log_assert( canvas_add_shader(&text_canvas, shader.name, &shader) < MAX_CANVAS_SHADER );
    log_assert( canvas_add_font(&text_canvas, "other_font", &font) < MAX_CANVAS_FONTS );

    struct GameTime time = {0};
    gametime_create(1.0f / 60.0f, &time);

    SDL_SetEventFilter(event_filter, NULL);
    while (true) {
        SDL_Event event;
        while( sdl2_poll_event(&event) ) {
            if( sdl2_handle_quit(event) ) {
                goto done;
            }
            sdl2_handle_resize(event);

            arcball_handle_resize(&arcball, event);
            arcball_handle_mouse(&arcball, event);
        }

        gametime_advance(&time, sdl2_time_delta());

        sdl2_debug( SDL_GL_SetSwapInterval(1) );

        ogl_debug( glClearDepth(1.0f);
                   glClearColor(.0f, .0f, .0f, 1.0f);
                   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); );

        draw_grid(&text_canvas, 0, (Mat)IDENTITY_MAT, (Color){20, 180, 240, 255}, 0.02f, 12.0f, 12.0f, 12);

        draw_basis(&text_canvas, 1, (Mat)IDENTITY_MAT, 0.02f, 1.0f);

        Mat text_matrix = {0};
        Quat text_rotation = {0};
        quat_from_axis_angle((Vec4f){1.0, 0.0, 0.0, 1.0}, PI/2, text_rotation);
        mat_rotate(NULL, text_rotation, text_matrix);
        mat_translate(text_matrix, (Vec4f){-3.5, -1.0, 6.25, 1.0}, text_matrix);

        Vec4f world_cursor = {0,0,0,1};
        text_put_world(&text_canvas, 0, world_cursor, text_matrix, (Color){0, 255, 255, 255}, 0.5f, "other_font", L"Dies ist ein Test\n");
        text_put_world(&text_canvas, 0, world_cursor, text_matrix, (Color){255, 255, 0, 255}, 0.5f, "other_font", L"fuer einen Text");

        gametime_integrate(&time);
        Vec4f screen_cursor = {0,0,0,1};
        double fps = text_show_fps(&global_dynamic_canvas, 0, screen_cursor, 0, 0, (Color){255, 255, 255, 255}, 20.0f, "default_font", time.frame);

        /* text_show_time(&text_canvas, screen_cursor, 0, "default_font", 20.0, (Color){255, 255, 255, 255}, 0, 0, time.t); */

        /* text_put_screen(&text_canvas, screen_cursor, 0, "default_font", 20.0, (Color){255, 210, 255, 255}, 0, 0, L"LALA singt das Meerschweinchen\n"); */
        /* text_put_screen(&text_canvas, screen_cursor, 0, "default_font", 20.0, (Color){0, 210, 255, 255}, 0, 0, L"FICKEN immer und ueberall\n"); */
        /* text_put_screen(&text_canvas, screen_cursor, 0, "default_font", 20.0, (Color){20, 210, 110, 255}, 0, 0, L"FUMMELN den ganzen Tag lang\n"); */

        /* text_printf(&text_canvas, screen_cursor, 0, "default_font", 20.0, (Color){255, 40, 60, 255}, 0, 0, L"PRINTF %d Luftballons\n", 99); */

        canvas_render_layers(&text_canvas, 0, MAX_CANVAS_LAYERS, &arcball.camera, (Mat)IDENTITY_MAT);
        canvas_clear(&text_canvas);

        canvas_render_layers(&global_dynamic_canvas, 0, MAX_CANVAS_LAYERS, &arcball.camera, (Mat)IDENTITY_MAT);
        canvas_clear(&global_dynamic_canvas);

        sdl2_debug( SDL_GL_SwapWindow(window) );
    }
Beispiel #8
0
int32_t main(int32_t argc, char *argv[]) {
    printf("<<watchlist//>>\n");

    if( init_sdl2() ) {
        return 1;
    }

    int32_t width = 1280;
    int32_t height = 720;

    SDL_Window* window;
    sdl2_window("cute3d: " __FILE__, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, &window);

    SDL_GLContext* context;
    sdl2_glcontext(3, 2, window, &context);

    if( init_shader() ) {
        return 1;
    }

    if( init_canvas(width, height) ) {
        return 1;
    }
    canvas_create("global_dynamic_canvas", &global_dynamic_canvas);

    struct Arcball arcball = {0};
    arcball_create(width, height, (Vec4f){0.0,6.0,10.0,1.0}, (Vec4f){0.0,0.0,0.0,1.0}, 0.001f, 100.0, &arcball);

    struct GameTime time = {0};
    gametime_create(1.0f / 60.0f, &time);


    Vec4f a = {0.0f, 0.0f, 1.0f};
    Vec4f b = {1.0f, 0.0f, 1.0f};
    draw_vec(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){25, 255, 25, 255}, 0.01f, a, (Vec3f){0.0f, 0.0f, 0.0f}, 1.0f, 1.0f);
    draw_vec(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 25, 25, 255}, 0.01f, b, (Vec3f){0.0f, 0.0f, 0.0f}, 1.0f, 1.0f);

    Quat axis_angle_rot = {0};
    quat_from_axis_angle((Vec4f)Y_AXIS, PI/4, axis_angle_rot);
    draw_quaternion(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 255, 255, 255}, (Color){255, 0, 255, 255}, 0.01f, axis_angle_rot, 2.0f);

    vec_print("axis_angle_rot: ", axis_angle_rot);
    Vec4f axis_angle_result = {0};
    vec_rotate(a, axis_angle_rot, axis_angle_result);
    draw_vec(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 255, 25, 255}, 0.01f, axis_angle_result, (Vec3f){0.0f, 0.0f, 0.0f}, 1.0f, 2.0f);

    Vec4f axis = {0};
    float angle = 0.0f;
    quat_to_axis_angle(axis_angle_rot, axis, &angle);
    Quat axis_angle_rot2 = {0};
    quat_from_axis_angle(axis, angle, axis_angle_rot2);
    vec_print("axis_angle_rot2: ", axis_angle_rot2);

    Quat euler_angles_rot = {0};
    quat_from_euler_angles(0.0f, PI/4, 0.0f, euler_angles_rot);
    vec_print("euler_angles_rot: ", euler_angles_rot);
    Vec4f euler_angles_result = {0};
    vec_rotate(a, euler_angles_rot, euler_angles_result);
    draw_vec(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){25, 255, 255, 255}, 0.01f, euler_angles_result, (Vec3f){0.0f, 0.0f, 0.0f}, 1.0f, 3.0f);

    Quat vec_pair_rot = {0};
    quat_from_vec_pair(a, b, vec_pair_rot);
    vec_print("vec_pair_rot: ", vec_pair_rot);
    Vec4f vec_pair_result = {0};
    vec_rotate(a, vec_pair_rot, vec_pair_result);
    draw_vec(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){255, 25, 255, 255}, 0.01f, vec_pair_result, (Vec3f){0.0f, 0.0f, 0.0f}, 1.0f, 4.0f);

    Mat xaxis_control = {0};
    xaxis_control[0] = 1; xaxis_control[4] = 0;          xaxis_control[8]  = 0;           xaxis_control[12] = 0;
    xaxis_control[1] = 0; xaxis_control[5] = cosf(PI/4); xaxis_control[9]  = -sinf(PI/4); xaxis_control[13] = 0;
    xaxis_control[2] = 0; xaxis_control[6] = sinf(PI/4); xaxis_control[10] = cosf(PI/4);  xaxis_control[14] = 0;
    xaxis_control[3] = 0; xaxis_control[7] = 0;          xaxis_control[11] = 0;           xaxis_control[15] = 1;
    mat_print("xaxis_control: ", xaxis_control);

    Quat xaxis_rot = {0};
    quat_from_axis_angle((Vec4f)X_AXIS, PI/4, xaxis_rot);
    Mat xaxis_mat = {0};
    quat_to_mat(xaxis_rot, xaxis_mat);
    mat_print("xaxis_mat: ", xaxis_mat);

    Mat yaxis_control = {0};
    yaxis_control[0] = cosf(PI/4);  yaxis_control[4] = 0; yaxis_control[8]  = sinf(PI/4); yaxis_control[12] = 0;
    yaxis_control[1] = 0;           yaxis_control[5] = 1; yaxis_control[9]  = 0;          yaxis_control[13] = 0;
    yaxis_control[2] = -sinf(PI/4); yaxis_control[6] = 0; yaxis_control[10] = cosf(PI/4); yaxis_control[14] = 0;
    yaxis_control[3] = 0;           yaxis_control[7] = 0; yaxis_control[11] = 0;          yaxis_control[15] = 1;
    mat_print("yaxis_control: ", yaxis_control);

    Quat yaxis_rot = {0};
    quat_from_axis_angle((Vec4f)Y_AXIS, PI/4, yaxis_rot);
    Mat yaxis_mat = {0};
    quat_to_mat(yaxis_rot, yaxis_mat);
    mat_print("yaxis_mat: ", yaxis_mat);

    Mat zaxis_control = {0};
    zaxis_control[0] = cosf(PI/4); zaxis_control[4] = -sinf(PI/4); zaxis_control[8]  = 0; zaxis_control[12] = 0;
    zaxis_control[1] = sinf(PI/4); zaxis_control[5] = cosf(PI/4);  zaxis_control[9]  = 0; zaxis_control[13] = 0;
    zaxis_control[2] = 0;          zaxis_control[6] = 0;           zaxis_control[10] = 1; zaxis_control[14] = 0;
    zaxis_control[3] = 0;          zaxis_control[7] = 0;           zaxis_control[11] = 0; zaxis_control[15] = 1;
    mat_print("zaxis_control: ", zaxis_control);

    Quat zaxis_rot = {0};
    quat_from_axis_angle((Vec4f)Z_AXIS, PI/4, zaxis_rot);
    Mat zaxis_mat = {0};
    quat_to_mat(zaxis_rot, zaxis_mat);
    mat_print("zaxis_mat: ", zaxis_mat);

    draw_grid(&global_static_canvas, 0, (Mat)IDENTITY_MAT, (Color){120, 120, 120, 255}, 0.01f, 12.0f, 12.0f, 12);

    while(true) {
        SDL_Event event;
        while( sdl2_poll_event(&event) ) {
            if( sdl2_handle_quit(event) ) {
                goto done;
            }
            sdl2_handle_resize(event);

            arcball_handle_resize(&arcball, event);
            arcball_handle_mouse(&arcball, event);
        }

        sdl2_gl_set_swap_interval(0);

        ogl_debug( glClearDepth(1.0f);
                   glClearColor(.0f, .0f, .0f, 1.0f);
                   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); );

        gametime_advance(&time, sdl2_time_delta());
        gametime_integrate(&time);

        canvas_render_layers(&global_static_canvas, 0, MAX_CANVAS_LAYERS, &arcball.camera, (Mat)IDENTITY_MAT);

        sdl2_gl_swap_window(window);
    }
Beispiel #9
0
int32_t pivot_lookat(struct Pivot* pivot, const Vec3f target) {
    int32_t result = -1;

    Vec4f right_axis = RIGHT_AXIS;
    Vec4f up_axis = UP_AXIS;
    Vec4f forward_axis = FORWARD_AXIS;

    struct Pivot world_pivot;
    pivot_combine(pivot->parent, pivot, &world_pivot);

    Vec4f target_direction;
    vec_sub(target, world_pivot.position, target_direction);

    float dot_yaw = vec_dot(target_direction, forward_axis);

    Quat rotation = {0};
    if( fabs(dot_yaw + 1.0f) < CUTE_EPSILON ) {
        // vector a and b point exactly in the opposite direction,
        // so it is a 180 degrees turn around the up-axis
        Quat rotation = {0};
        quat_from_axis_angle(up_axis, PI, rotation);
        quat_mul(world_pivot.orientation, rotation, rotation);
    } else if( fabs(dot_yaw - (1.0f)) < CUTE_EPSILON ) {
        // vector a and b point exactly in the same direction
        // so we return the identity quaternion
        quat_copy(world_pivot.orientation, rotation);
    } else {
        // - I look at the target by turning the pivot orientation using only
        // yaw and pitch movement
        // - I always rotate the pivot from its initial orientation (up and forward
        // basis vectors like initialized above), so this does not incrementally
        // advance the orientation
        quat_identity(rotation);

        // - to find the amount of yaw I project the target_direction into the
        //   up_axis plane, resulting in up_projection which is a vector that
        //   points from the up_axis plane to the tip of the target_direction
        Vec4f up_projection = {0};
        vec_mul1f(up_axis, vec_dot(target_direction, up_axis), up_projection);

        // - so then by subtracting the up_projection from the target_direction,
        //   I get a vector lying in the up_axis plane, pointing towards the target
        Vec4f yaw_direction = {0};
        vec_sub(target_direction, up_projection, yaw_direction);

        // - angle between yaw_direction and forward_axis is the amount of yaw we
        //   need to point the forward_axis toward the target
        float yaw = 0.0f;
        vec_angle(yaw_direction, forward_axis, &yaw);
        log_assert( ! isnan(yaw),
                    "vec_angle(%f %f %f, %f %f %f, %f);\n",
                    yaw_direction[0], yaw_direction[1], yaw_direction[2],
                    forward_axis[0], forward_axis[1], forward_axis[2],
                    yaw );

        // - I have to compute the cross product between yaw_direction and
        //   forward_axis and use the resulting yaw_axis
        Vec4f yaw_axis = {0};
        vec_cross(yaw_direction, forward_axis, yaw_axis);
        if( vec_nullp(yaw_axis) ) {
            vec_copy4f(up_axis, yaw_axis);
        }

        // - compute the yaw rotation
        Quat yaw_rotation = {0};
        quat_from_axis_angle(yaw_axis, yaw, yaw_rotation);

        // - to compute, just as with the yaw, I want an axis that lies on the plane that
        //   is spanned in this case by the right_axis, when the camera points toward the
        //   target
        // - I could compute an axis, but I already have a direction vector that points
        //   toward the target, the yaw_direction, I just have to normalize it to make it
        //   an axis (and put the result in forward_axis, since it now is the forward_axis
        //   of the yaw turned camera)
        Vec4f yaw_forward_axis = {0};
        vec_normalize(yaw_direction, yaw_forward_axis);

        // - then use the new forward axis with the old target_direction to compute the angle
        //   between those
        float pitch = 0.0f;
        vec_angle(target_direction, yaw_forward_axis, &pitch);
        log_assert( ! isnan(pitch),
                    "vec_angle(%f %f %f, %f %f %f, %f);\n",
                    target_direction[0], target_direction[1], target_direction[2],
                    yaw_forward_axis[0], yaw_forward_axis[1], yaw_forward_axis[2],
                    pitch );


        // - and just as in the yaw case we compute an rotation pitch_axis
        Vec4f pitch_axis = {0};
        vec_cross(target_direction, yaw_forward_axis, pitch_axis);
        if( vec_nullp(pitch_axis) ) {
            vec_copy4f(right_axis, pitch_axis);
        }

        // - and finally compute the pitch rotation and combine it with the yaw_rotation
        //   in the same step
        Quat pitch_rotation;
        quat_from_axis_angle(pitch_axis, pitch, pitch_rotation);
        Quat yaw_pitch_rotation;
        quat_mul(yaw_rotation, pitch_rotation, yaw_pitch_rotation);

        Quat inverted_orientation = {0};
        quat_invert(world_pivot.orientation, inverted_orientation);

        // - the int32_t I want to return indicates the cameras 'flip' status, that is, it is
        //   one when the camera angle was pitched so much that it flipped over and its
        //   up axis is now pointing downwards
        // - to find out if I am flipped over, I compute the flipped up_axis called
        //   flip_axis and then use the dot product between the flip_axis and up_axis
        //   to decide if I am flipped
        Vec4f flip_axis = {0};
        vec_rotate(up_axis, inverted_orientation, flip_axis);
        vec_rotate(flip_axis, yaw_pitch_rotation, flip_axis);

        float dot_pitch = vec_dot(up_axis, flip_axis);

        Vec4f target_axis = {0};
        vec_normalize(target_direction, target_axis);

        // - check if we are flipped and if we are, set result to 1 meaning we are flipped
        // - turn the camera around PI so that we can continue pitching, otherwise we just get
        //   stuck when trying to flip the camera over
        if( dot_pitch < 0.0f ) {
            result = 1;
            quat_from_axis_angle(target_axis, PI, rotation);
            quat_mul(yaw_pitch_rotation, rotation, yaw_pitch_rotation);
        }

        quat_copy(yaw_pitch_rotation, rotation);
    }

    if( ! isnan(rotation[0]) &&
        ! isnan(rotation[1]) &&
        ! isnan(rotation[2]) &&
        ! isnan(rotation[3]) )
    {
        quat_copy(rotation, pivot->orientation);
    }

    pivot->eye_distance = vec_length(target_direction);

    return result;
}
Beispiel #10
0
QuatP* qfrom_axis_angle(Quat axis, const float angle) {
    quat_from_axis_angle(axis, angle, axis);
    return axis;
}