Exemple #1
0
/*@T
 *
 * The [[place_particles]] routine fills a region (indicated by the
 * [[indicatef]] argument) with fluid particles.  The fluid particles
 * are placed at points inside the domain that lie on a regular mesh
 * with cell sizes of $h/1.3$.  This is close enough to allow the
 * particles to overlap somewhat, but not too much.
 *@c*/
sim_state_t* place_particles(sim_param_t* param, 
                             domain_fun_t indicatef)
{
    float h  = param->h;
    float hh = h/1.3;

    // Count mesh points that fall in indicated region.
    int count = 0;
    for (float x = 0; x < 1; x += hh)
        for (float y = 0; y < 1; y += hh)
        	for (float z = 0; z < 1; z += hh)
        		count += indicatef(x,y,z);

    // Populate the particle data structure
    sim_state_t* s = alloc_state(count);
    int p = 0;
    for (float x = 0; x < 1; x += hh) {
        for (float y = 0; y < 1; y += hh) {
            for (float z = 0; z < 1; z += hh) {
                if (indicatef(x,y,z)) {
                    vec3_set(s->part[p].x, x, y, z);
                    vec3_set(s->part[p].v, 0, 0, 0);
                    ++p;
                }
            }
        }
    }
    return s;    
}
Exemple #2
0
void		*parse_light(const parsing_sect_t *section, t_scene *scene)
{
	t_light		*light;
	t_vec3		position;
	t_vec3		color;
	float		intensity;
	
	vec3_set(&position, 0.f, 0.f, 0.f);
	
	if (section->option_count > 0)
		parse_vec3(section->options[0] + 1, &position);

	vec3_set(&color, 1.f, 1.f, 1.f);
	
	if (section->option_count > 1)
		parse_vec3(section->options[1] + 1, &color);

	intensity = 0.f;

	if (section->option_count > 2)
		intensity = atof(section->options[2][1]);

	light = create_light(&position, intensity, &color);
	lst_push_back(scene->lights, light);

	return (light);
}
Exemple #3
0
int renderer_init(struct renderer *r, int w, int h)
{
	if (framebuffer_init(&r->fb) < 0)
		return -1;
	if (renderer_init_shaders(r) < 0)
		return -1;
	if (create_cube_mesh(&r->cube_attr, &r->cube_idx) < 0) {
		fprintf(stderr, "Error creating cube mesh\n");
		return -1;
	}
	if (create_quad_mesh(&r->quad_attr) < 0) {
		fprintf(stderr, "Error creating fullscreen quad\n");
		return -1;
	}

	vec3_set(&r->pos, 2, 4, 2);
	vec3_set(&r->tar, 0, 0, 0);
	vec3_set(&r->up, 0, 1, 0);
	r->width = w;
	r->height = h;
	renderer_default_display_state(r);
	renderer_default_quadrants(r);
	renderer_default_postprocess_effects(r);

	return 0;
}
//----------------------------------------------------------------------------------------------------------------------------------------
// les 2 poly et les 6 vertx doivent etre a la suite
void CoupleShadowP3D::Set(PolygonU3D* poly, VertexU3D* vertex, MaterialU3D* mat, CoupleOnePetals3D* peta) {
    p1 = poly;
    p1->SetNbVertex(4);
    p1->m = mat;

    vertex[0].utilisateurs++;
    p1->Vtab[0] = &vertex[0];
    vertex[1].utilisateurs++;
    p1->Vtab[1] = &vertex[1];
    vertex[3].utilisateurs++;
    p1->Vtab[2] = &vertex[3];
    vertex[2].utilisateurs++;
    p1->Vtab[3] = &vertex[2];

    vertex[0].U = 0.0f;
    vertex[0].V = 0.0f;
    vertex[1].U = 1.0f;
    vertex[1].V = 0.0f;
    vertex[2].U = 0.0f;
    vertex[2].V = 1.0f;
    vertex[3].U = 1.0f;
    vertex[3].V = 1.0f;

    Ufloat sizex = DEFAULT_SHADOW*.5f;
    Ufloat sizey = DEFAULT_SHADOW*.5f;

    vec3_set(vertex[0].c->origine, -sizex, 0.0f, -sizey);
    vec3_set(vertex[1].c->origine, sizex, 0.0f, -sizey);
    vec3_set(vertex[2].c->origine, -sizex, 0.0f, sizey);
    vec3_set(vertex[3].c->origine, sizex, 0.0f, sizey);

    petal = peta;
}
Exemple #5
0
static inline void _reset_camera(game *g) {
    vec3_set(g->d.eye, 0.0, 0.0, 1.0);
    vec3_set(g->d.center, 0.0, 0.0, -1.0);
    vec3_set(g->d.up, 0.0, 1.0, 0.0);
    g->d.zoom_level = 0;
    _calc_zoom(g, 0);
}
Exemple #6
0
static void build_sprite(struct vb_data *data, float fcx, float fcy,
		float start_u, float end_u, float start_v, float end_v)
{
	struct vec2 *tvarray = data->tvarray[0].array;

	vec3_zero(data->points);
	vec3_set(data->points+1,  fcx, 0.0f, 0.0f);
	vec3_set(data->points+2, 0.0f,  fcy, 0.0f);
	vec3_set(data->points+3,  fcx,  fcy, 0.0f);
	vec2_set(tvarray,   start_u, start_v);
	vec2_set(tvarray+1, end_u,   start_v);
	vec2_set(tvarray+2, start_u, end_v);
	vec2_set(tvarray+3, end_u,   end_v);
}
Exemple #7
0
void		*parse_sphere(const parsing_sect_t *section, t_scene *scene)
{
	t_sphere	*sphere;
	t_object	*object;
	t_vec3		position;
	t_material	*material;
	float		radius;
	
	vec3_set(&position, 0, 0, 0);
	
	if (section->option_count > 0)
		parse_vec3(section->options[0] + 1, &position);

	radius = 0.f;

	if (section->option_count > 1)
		radius = atof(section->options[1][1]);

	material = NULL;

	if (section->option_count > 2)
		material = get_material(scene, section->options[2][1]);

	if (material == NULL)
		die("Unknown material.");

	sphere = create_sphere(&position, radius, material);
	object = create_object(section->name, SPHERE, sphere);
	lst_push_back(scene->objects, object);

	return (sphere);
}
Exemple #8
0
void gs_vertex2f(float x, float y)
{
	struct vec3 v3;
       
	vec3_set(&v3, x, y, 0.0f);
	gs_vertex3v(&v3);
}
static vec3 GetTransformedPos(float x, float y, const matrix4 &mat)
{
	vec3 result;
	vec3_set(&result, x, y, 0.0f);
	vec3_transform(&result, &result, &mat);
	return result;
}
Exemple #10
0
void gs_vertex3f(float x, float y, float z)
{
	struct vec3 v3;

	vec3_set(&v3, x, y, z);
	gs_vertex3v(&v3);
}
static bool FindItemAtPos(obs_scene_t scene, obs_sceneitem_t item, void *param)
{
	SceneFindData *data = reinterpret_cast<SceneFindData*>(param);
	matrix4       transform;
	vec3          transformedPos;
	vec3          pos3;

	vec3_set(&pos3, data->pos.x, data->pos.y, 0.0f);

	obs_sceneitem_get_box_transform(item, &transform);

	matrix4_inv(&transform, &transform);
	vec3_transform(&transformedPos, &pos3, &transform);

	if (transformedPos.x >= 0.0f && transformedPos.x <= 1.0f &&
	    transformedPos.y >= 0.0f && transformedPos.y <= 1.0f) {
		if (data->selectBelow && obs_sceneitem_selected(item)) {
			if (data->item)
				return false;
			else
				data->selectBelow = false;
		}

		data->item = item;
	}

	UNUSED_PARAMETER(scene);
	return true;
}
Exemple #12
0
void gs_normal3f(float x, float y, float z)
{
	struct vec3 v3;

	vec3_set(&v3, x, y, z);
	gs_normal3v(&v3);
}
Exemple #13
0
void gs_vertex2v(const struct vec2 *v)
{
	struct vec3 v3;

	vec3_set(&v3, v->x, v->y, 0.0f);
	gs_vertex3v(&v3);
}
Exemple #14
0
static void
update_eye(void)
{
	vector3 wanted, dir;
	float d;
	float max_speed;

	vec3_add_to(&gc.eye, &delta_eye);

	if (inner_state.state == IS_WAVE_CLEARED) {
		vec3_set(&wanted, 0, 0, -3.f*BASE_EYE_Z);
	} else {
		if (!ship.is_alive) {
			vec3_set(&wanted, 0, 0, -BASE_EYE_Z);
		} else {
			const struct foe_common *closest_foe;

			closest_foe = get_closest_foe(&ship.pos);

			if (closest_foe &&
#define D 4.f
					(d = vec2_distance(&closest_foe->pos, &ship.pos)) < D) {
#define R .7
				wanted.z = -(R*BASE_EYE_Z + (d/D)*(1.f - R)*BASE_EYE_Z);
			} else {
				wanted.z = -BASE_EYE_Z;
			}

			wanted.x = -(-BASE_EYE_Z/wanted.z)*.3f*ship.pos.x;
			wanted.y = -(-BASE_EYE_Z/wanted.z)*.3f*ship.pos.y;
		}
	}

	if (inner_state.state == IS_IN_GAME)
		max_speed = .5f;
	else
		max_speed = 1.5f;

	vec3_sub(&dir, &wanted, &gc.eye);
	vec3_mul_scalar(&dir, .05f);

	vec3_add_to(&delta_eye, &dir);
	vec3_clamp_length(&delta_eye, max_speed);

	/* damp */
	vec3_mul_scalar(&delta_eye, .7);
}
Exemple #15
0
void gs_matrix_scale3f(float x, float y, float z)
{
	struct matrix3 *top_mat = top_matrix(thread_graphics);
	struct vec3 p;

	vec3_set(&p, x, y, z);
	matrix3_scale(top_mat, top_mat, &p);
}
static vec3 GetTransformedPosScaled(float x, float y, const matrix4 &mat,
		float scale)
{
	vec3 result;
	vec3_set(&result, x, y, 0.0f);
	vec3_transform(&result, &result, &mat);
	vec3_mulf(&result, &result, scale);
	return result;
}
//----------------------------------------------------------------------------------------------------------------------------------------
void OneNebuRayon::Ini() {
    vec3_set(vec, 2.f*Random1() -1.f, 1.f*Random1() -.5f, 2.f*Random1() -1.f);
    vec3_normalize(vec);

    dist = NEBU_RAYON * Random1() * 2.f + BIGPART_SIZE;
    taille  = RAY_SIZE_MIN +    Random1()*RAY_SIZE_RND;

    totalTime = timeToGo =  RAY_LIFE_MIN + Random1()*RAY_LIFE_RND;
}
Exemple #18
0
void gs_matrix_translate3f(float x, float y, float z)
{
	struct matrix3 *top_mat = top_matrix(thread_graphics);
	struct vec3 p;

	if (top_mat) {
		vec3_set(&p, x, y, z);
		matrix3_translate(top_mat, top_mat, &p);
	}
}
Exemple #19
0
static void
ninja_create(struct foe_ninja *f)
{
	f->state = NINJA_ALIVE;
	f->hit_count = 10;
	evolved_duck_create(&f->evolved_duck);
	f->evolved_duck.trail_texture_id = ninja_trail;
	f->evolved_duck.max_turn_angle = .2f*MAX_EVOLVED_DUCK_TURN_ANGLE;
	vec3_set(&f->common.rot_axis, 0.f, 0.f, 1.f);
}
Exemple #20
0
static inline void build_sprite(struct vb_data *data, float fcx, float fcy,
		uint32_t flip)
{
	struct vec2 *tvarray = data->tvarray[0].array;
	float start_u, end_u;
	float start_v, end_v;

	assign_sprite_uv(&start_u, &end_u, (flip & GS_FLIP_U) != 0);
	assign_sprite_uv(&start_v, &end_v, (flip & GS_FLIP_V) != 0);

	vec3_zero(data->points);
	vec3_set(data->points+1,  fcx, 0.0f, 0.0f);
	vec3_set(data->points+2, 0.0f,  fcy, 0.0f);
	vec3_set(data->points+3,  fcx,  fcy, 0.0f);
	vec2_set(tvarray,   start_u, start_v);
	vec2_set(tvarray+1, end_u,   start_v);
	vec2_set(tvarray+2, start_u, end_v);
	vec2_set(tvarray+3, end_u,   end_v);
}
static void DrawCircleAtPos(float x, float y, matrix4 &matrix,
		float previewScale)
{
	struct vec3 pos;
	vec3_set(&pos, x, y, 0.0f);
	vec3_transform(&pos, &pos, &matrix);
	vec3_mulf(&pos, &pos, previewScale);

	gs_matrix_push();
	gs_matrix_translate(&pos);
	gs_draw(GS_LINESTRIP, 0, 0);
	gs_matrix_pop();
}
Exemple #22
0
void		switch_clear_color(void)
{
	if (g_scop.clear_color.x < 1.0f)
	{
		g_scop.clear_color.x += 0.35f;
		g_scop.clear_color.y += 0.35f;
		g_scop.clear_color.z += 0.35f;
	}
	else
		vec3_set(&g_scop.clear_color, 0, 0, 0);
	glClearColor(g_scop.clear_color.x, g_scop.clear_color.y,
		g_scop.clear_color.z, 1.0f);
}
Exemple #23
0
//----------------------------------------------------------------------------------------------------------
LightU3D::LightU3D() {
    Nom = "Default";
    Type = TYPE_LIGHT_OMNI;

    vec3_set(Pos, 0.0f, 0.0f, 0.0f);

    vec3_set(RVB, .8f, .8f, .8f);
    Intensity = 1.0f;

    Attenuation = FALSE;
    Inner = 100.f;
    Outer = 1000.f;

    vec3_set(Targ, 0.0f, 0.0f, 100.f);
    Hotspot = .7853981634;  // Hotspot a 45 degré par defaut
    Falloff = 1.570796327;  // Falloff a 90 degré par defaut

    Spos = NULL;
    Starg = NULL;
    Scolor = NULL;

    Normalize();
}
//----------------------------------------------------------------------------------------------------------------------------------------
// les 2 poly et les 6 vertx doivent etre a la suite
void CoupleOnePetals3D::Set(PolygonU3D* poly, VertexU3D* vertex, MaterialU3D* mat) {
    p1 = poly;
    p1->SetNbVertex(4);
    p1->m = mat;

    vertex[0].utilisateurs++;
    p1->Vtab[0] = &vertex[0];
    vertex[1].utilisateurs++;
    p1->Vtab[1] = &vertex[1];
    vertex[3].utilisateurs++;
    p1->Vtab[2] = &vertex[3];
    vertex[2].utilisateurs++;
    p1->Vtab[3] = &vertex[2];

    poly++;
    p2 = poly;
    p2->SetNbVertex(4);
    p2->m = mat;

    vertex[2].utilisateurs++;
    p2->Vtab[0] = &vertex[2];
    vertex[3].utilisateurs++;
    p2->Vtab[1] = &vertex[3];
    vertex[5].utilisateurs++;
    p2->Vtab[2] = &vertex[5];
    vertex[4].utilisateurs++;
    p2->Vtab[3] = &vertex[4];

    vertex[0].U = 0.0f;
    vertex[0].V = 0.0f;
    vertex[1].U = 1.0f;
    vertex[1].V = 0.0f;
    vertex[2].U = 0.0f;
    vertex[2].V = 0.5f;
    vertex[3].U = 1.0f;
    vertex[3].V = 0.5f;
    vertex[4].U = 0.0f;
    vertex[4].V = 1.0f;
    vertex[5].U = 1.0f;
    vertex[5].V = 1.0f;

    Ufloat sizex = DEFAULT_SIZEX*GetMass();
    Ufloat sizey = DEFAULT_SIZEY*GetMass();

    coord[0] = vertex[0].c;
    vec3_set(coord[0]->origine, -sizex, -sizey, 0.0f);
    coord[1] = vertex[1].c;
    vec3_set(coord[1]->origine, sizex, -sizey, 0.0f);
    coord[2] = vertex[2].c;
    vec3_set(coord[2]->origine, -sizex, 0.0f, sizex*.5f*Random1() - .25f*sizey);
    coord[3] = vertex[3].c;
    vec3_set(coord[3]->origine, sizex, 0.0f, sizex*.5f*Random1() - .25f*sizey);
    coord[4] = vertex[4].c;
    vec3_set(coord[4]->origine, -sizex, sizey, 0.0f);
    coord[5] = vertex[5].c;
    vec3_set(coord[5]->origine, sizex, sizey, 0.0f);
}
Exemple #25
0
static void	raycast_light(t_hit *hit, unsigned depth)
{
	t_lstiter	it;
	t_ray		ray;
	t_light		*light;
	int			raycast_result;
	t_vec3		lightness;
	t_hit		sub_hit;

	if (depth == 0)
		return ;

	vec3_set(&lightness, 0, 0, 0);
	init_iter(&it, rt.scene->lights, increasing);
	while (lst_iterator_next(&it))
	{
		light = (t_light*)it.data;
		vec3_copy(&ray.origin, &hit->position);
		vec3_copy(&ray.direction, &light->position);
		vec3_sub(&ray.direction, &hit->position);
		vec3_normalize(&ray.direction);

		ray.origin.x += ray.direction.x * RC_SHADOW_SHIFT;
		ray.origin.y += ray.direction.y * RC_SHADOW_SHIFT;
		ray.origin.z += ray.direction.z * RC_SHADOW_SHIFT;

		raycast_result = raycast(&ray, &sub_hit, depth - 1, NULL);

		if (sub_hit.object != NULL)
		{
			// ray bounce
		}
		else
		{
			vec3_add(&lightness, &light->color);
		}
	}

	vec3_div(&lightness, rt.scene->lights->size);
	vec3_add(&lightness, &rt.scene->ambient_light);
	color_clamp(&lightness);

	hit->color.x *= lightness.x;
	hit->color.y *= lightness.y;
	hit->color.z *= lightness.z;
}
static bool FindHandleAtPos(obs_scene_t scene, obs_sceneitem_t item,
		void *param)
{
	if (!obs_sceneitem_selected(item))
		return true;

	HandleFindData *data = reinterpret_cast<HandleFindData*>(param);
	matrix4        transform;
	vec3           pos3;
	float          closestHandle = HANDLE_SEL_RADIUS;

	vec3_set(&pos3, data->pos.x, data->pos.y, 0.0f);

	obs_sceneitem_get_box_transform(item, &transform);

	auto TestHandle = [&] (float x, float y, ItemHandle handle)
	{
		vec3 handlePos = GetTransformedPosScaled(x, y, transform,
				data->scale);

		float dist = vec3_dist(&handlePos, &pos3);
		if (dist < HANDLE_SEL_RADIUS) {
			if (dist < closestHandle) {
				closestHandle = dist;
				data->handle  = handle;
				data->item    = item;
			}
		}
	};

	TestHandle(0.0f, 0.0f, ItemHandle::TopLeft);
	TestHandle(0.5f, 0.0f, ItemHandle::TopCenter);
	TestHandle(1.0f, 0.0f, ItemHandle::TopRight);
	TestHandle(0.0f, 0.5f, ItemHandle::CenterLeft);
	TestHandle(1.0f, 0.5f, ItemHandle::CenterRight);
	TestHandle(0.0f, 1.0f, ItemHandle::BottomLeft);
	TestHandle(0.5f, 1.0f, ItemHandle::BottomCenter);
	TestHandle(1.0f, 1.0f, ItemHandle::BottomRight);

	UNUSED_PARAMETER(scene);
	return true;
}
//----------------------------------------------------------------------------------------------------------------------------------------
// affiche grosse particule centrale
void Nebuparticule::AffBigPart() {
    CoordU3D tmpc;
    Ufloat   size;

    vec3_set(tmpc.trans, BIGPART_X, BIGPART_Y, BIGPART_Z);
    U3D3Monde3D->GetActualCamera()->ProjetUni(&tmpc, 0);

    if (!(tmpc.ClipInfo&ClipProche)) {
        centreX = tmpc.ecran[0];
        centreY = tmpc.ecran[1];

        size = BIGPART_SIZE * tmpc.ecran[3] * .5f;

        partMat->SetColor(1.0f, 1.0f, 1.0f, .8f);

        partBmp->SetCoord(0, tmpc.ecran[0] - size, tmpc.ecran[1] - size);
        partBmp->SetCoord(1, tmpc.ecran[0] + size, tmpc.ecran[1] - size);
        partBmp->SetCoord(2, tmpc.ecran[0] + size, tmpc.ecran[1] + size);
        partBmp->SetCoord(3, tmpc.ecran[0] - size, tmpc.ecran[1] + size);

        partBmp->Affiche();
    }
}
void OBSBasicPreview::StretchItem(const vec2 &pos)
{
	Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers();
	obs_bounds_type boundsType = obs_sceneitem_get_bounds_type(stretchItem);
	uint32_t stretchFlags = (uint32_t)stretchHandle;
	bool shiftDown = (modifiers & Qt::ShiftModifier);
	vec3 tl, br, pos3;

	vec3_zero(&tl);
	vec3_set(&br, stretchItemSize.x, stretchItemSize.y, 0.0f);

	vec3_set(&pos3, pos.x, pos.y, 0.0f);
	vec3_transform(&pos3, &pos3, &screenToItem);

	if (stretchFlags & ITEM_LEFT)
		tl.x = pos3.x;
	else if (stretchFlags & ITEM_RIGHT)
		br.x = pos3.x;

	if (stretchFlags & ITEM_TOP)
		tl.y = pos3.y;
	else if (stretchFlags & ITEM_BOTTOM)
		br.y = pos3.y;

	if (!(modifiers & Qt::ControlModifier))
		SnapStretchingToScreen(tl, br);

	obs_source_t source = obs_sceneitem_getsource(stretchItem);

	vec2 baseSize;
	vec2_set(&baseSize,
		float(obs_source_getwidth(source)),
		float(obs_source_getheight(source)));

	vec2 size;
	vec2_set(&size,br. x - tl.x, br.y - tl.y);

	if (boundsType != OBS_BOUNDS_NONE) {
		if (shiftDown)
			ClampAspect(tl, br, size, baseSize);

		if (tl.x > br.x) std::swap(tl.x, br.x);
		if (tl.y > br.y) std::swap(tl.y, br.y);

		vec2_abs(&size, &size);

		obs_sceneitem_set_bounds(stretchItem, &size);
	} else {
		if (!shiftDown)
			ClampAspect(tl, br, size, baseSize);

		vec2_div(&size, &size, &baseSize);
		obs_sceneitem_setscale(stretchItem, &size);
	}

	pos3 = CalculateStretchPos(tl, br);
	vec3_transform(&pos3, &pos3, &itemToScreen);

	vec2 newPos;
	vec2_set(&newPos, std::round(pos3.x), std::round(pos3.y));
	obs_sceneitem_setpos(stretchItem, &newPos);
}
void render(msg_block_t *msg, rt_context_t *rtx, uint32_t *frame_buffer)
{
  uint32_t *pixel;
  float sy = rtx->sheight * 0.5f - rtx->ayc;
  unsigned int y;
  for (y = 0; y < rtx->height; y++)
  {
    uint32_t *src = frame_buffer + (y * SCALE + rtx->yoff) * msg->fbinfo.line_length / sizeof(uint32_t) + rtx->xoff;
    pixel = src;
    float sx = rtx->swidth * -0.5f;
    unsigned int x;
    for (x = 0; x < rtx->width; x++)
    {
      rtx->ray.pos = rtx->eye;
      rtx->ray.dir = normalize(vec3_sub(vec3_set(sx, sy, 0.0f), rtx->eye));
      vec3_t col = vec3_set(0.0f, 0.0f, 0.0f);
      unsigned int j;
      for (j = 0; j < MAXREF; j++)
      {
        trace_ray(rtx);
        if (rtx->hit != NOHIT)
        {
          vec3_t p, n;
          ray_t next;
          p = vec3_add(rtx->ray.pos, vec3_scale(rtx->ray.dir, rtx->dist));
          switch (rtx->obj[rtx->hit].type)
          {
            case SPHERE:
              n = normalize(vec3_sub(p, rtx->obj[rtx->hit].pos));
              break;
            case PLANE:
              n = rtx->obj[rtx->hit].norm;
              break;
            default:
              break;
          }
          next.pos = vec3_add(p, vec3_scale(n, EPSILON));
          vec3_t lv = vec3_sub(rtx->light.pos, p);
          vec3_t l = normalize(lv);
          next.dir = rtx->ray.dir;
          int prev_hit_index = rtx->hit;
          vec3_t hit_obj_col = rtx->obj[rtx->hit].col;
          float diffuse = dot(n, l);
          float specular = dot(rtx->ray.dir, vec3_sub(l, vec3_scale(n, 2.0f * diffuse)));
          diffuse = max(diffuse, 0.0f);
          specular = max(specular, 0.0f);
          specular = power_spec(specular);
          float s1 = 1.0f;
          float s2 = 1.0f;
          if (rtx->obj[rtx->hit].flag_shadow)
          {
            rtx->ray.dir = l;
            rtx->ray.pos = next.pos;
            trace_ray(rtx);
            int shadow = (rtx->dist < norm(lv));
            s1 = shadow ? 0.5f : s1;
            s2 = shadow ? 0.0f : s2;
          }
          col = vec3_add(col, vec3_add(vec3_scale(rtx->light.col, specular * s2), vec3_scale(hit_obj_col, diffuse * s1)));
          if (!rtx->obj[prev_hit_index].flag_refrect)
          {
            break;
          }
          rtx->ray.dir = vec3_sub(next.dir, vec3_scale(n, dot(next.dir, n) * 2.0f));
          rtx->ray.pos = next.pos;
        }
        else
        {
          break;
        }
      }
      col = vec3_min(vec3_max(col, 0.0f), 1.0f);
      uint32_t col2 = 0xff000000 + ((unsigned int)(col.x * 255.0f) << 16) + ((unsigned int)(col.y * 255.0f) << 8) + (unsigned int)(col.z * 255.0f);
      *pixel = col2;
#if SCALE > 1
      *(pixel + 1) = col2;
#endif
#if SCALE > 3
      *(pixel + 2) = col2;
      *(pixel + 3) = col2;
#endif
      pixel += SCALE;
      sx += rtx->ax;
    }
    uint32_t size = rtx->width * SCALE;
    unsigned int i;
    for (i = 1; i < SCALE; i++)
    {
      uint32_t *dst = src + i * msg->fbinfo.line_length / sizeof(uint32_t);
      unsigned int j;
      for (j = 0; j < size; j++)
      {
        dst[j] = src[j];
      }
    }
    sy -= rtx->ay;
  }
}
int main(int argc, char ** argv)
{
  static msg_block_t msg;
  memset((void *)&msg, 0, sizeof(msg));
  struct timespec time;
  double time0, time1;
  uint32_t notes[SCALE_PATTERN][NOTES_SIZE];
  uint32_t scales[SCALE_PATTERN][SCALE_SIZE] = {
    {0,4,7,9,},
    {0,5,7,9,},
    {2,4,7,11,},
    {2,5,7,9,},
    {2,5,7,11,},
    {0,2,4,7,},
    {0,2,5,7,},
    {0,2,5,9,},
  };
  uint32_t instruments[] = {
    0, 4, 5, 6, 8, 9, 11, 14, 15, 16, 17, 19, 24,
    25, 26, 30, 40, 42, 46, 48, 51, 52, 56, 57, 60,
    61, 63, 64, 65, 68, 69, 70, 73, 88, 89, 91, 93,
    94, 95, 98, 99, 103, 104, 110, 
  };
  uint32_t insts = sizeof(instruments) / sizeof(uint32_t);

  int fb = open(FBDEV, O_RDWR);
  if (fb > 0)
  {
    struct fb_fix_screeninfo fbfsi;
    struct fb_var_screeninfo fbvsi;
    if (ioctl(fb, FBIOGET_FSCREENINFO, &fbfsi) == 0)
    {
      msg.fbinfo.smem_start = fbfsi.smem_start;
      msg.fbinfo.smem_len = fbfsi.smem_len;
      msg.fbinfo.line_length = fbfsi.line_length;
    }
    if (ioctl(fb, FBIOGET_VSCREENINFO, &fbvsi) == 0)
    {
      msg.fbinfo.xres = fbvsi.xres;
      msg.fbinfo.yres = fbvsi.yres;
      msg.fbinfo.xres_virtual = fbvsi.xres_virtual;
      msg.fbinfo.yres_virtual = fbvsi.yres_virtual;
      msg.fbinfo.xoffset = fbvsi.xoffset;
      msg.fbinfo.yoffset = fbvsi.yoffset;
      msg.fbinfo.bits_per_pixel = fbvsi.bits_per_pixel;
    }
    close(fb);
  }

  long pagesize = (sysconf(_SC_PAGESIZE));
  int fdmem = open(MEMDEV, O_RDWR | O_SYNC);
  uint32_t *frame_buffer = NULL;
  size_t mapsize = 0;
  if ((fdmem > 0) && (msg.fbinfo.smem_start != 0))
  {
    off_t physical_page = msg.fbinfo.smem_start & (~(pagesize - 1));
    unsigned long offset = msg.fbinfo.smem_start - (unsigned long)physical_page;
    mapsize = msg.fbinfo.smem_len + offset;
    frame_buffer = mmap(NULL, mapsize, PROT_READ | PROT_WRITE, MAP_SHARED, fdmem, physical_page);
    if (frame_buffer == MAP_FAILED)
    {
      perror("Framebuffer Map Failed");
    }
  }

  struct timespec time_start;
  clock_gettime(CLOCK_MONOTONIC_RAW, &time_start);
  srand((uint32_t)time_start.tv_nsec);

  seq_context_t seq;

  if (open_sequencer(&seq) == FALSE)
  {
    exit(EXIT_FAILURE);
  }
  program_change(&seq, 0, 48);
  control_change(&seq, 0, 91, 127);

  static rt_context_t rtx;
  memset((void *)&rtx, 0, sizeof(rtx));

  int width = msg.fbinfo.xres_virtual;
  int height = msg.fbinfo.yres_virtual;
  rtx.objnum = OBJNUM;
  rtx.light.pos = vec3_set(-4.0f, 8.0f, 2.0f);
  rtx.light.col = vec3_set(1.0f, 1.0f, 1.0f);
  rtx.eye = vec3_set(0.0f, 0.0f, -7.0f);
  rtx.swidth = 10.0f * (float)width / (float)height;
  rtx.sheight = 10.0f;
  rtx.width = width / SCALE;
  rtx.height = height / SCALE;
  rtx.xoff = 0;
  rtx.yoff = 0;
  rtx.ax = rtx.swidth / (float)rtx.width;
  rtx.ayc = rtx.sheight / (float)rtx.height;
  rtx.ay = rtx.sheight / (float)rtx.height;

  uint32_t i, j;
  for (i = 0; i < SCALE_PATTERN; i++)
  {
    for (j = 0; j < NOTES_SIZE; j++)
    {
      notes[i][j] = scales[i][j % SCALE_SIZE] + (j / SCALE_SIZE) * 12;
    }
  }

  for (i = 0; i < rtx.objnum; i++)
  {
    rtx.obj[i].type = SPHERE;
    rtx.obj[i].pos = vec3_set(0.0f, -100.0f, 0.0f);
    rtx.obj[i].rad = 1.0f;
    rtx.obj[i].col = vec3_set(randf(), randf(), randf());
    rtx.obj[i].flag_shadow = TRUE;
    rtx.obj[i].flag_refrect = TRUE;
    rtx.obj[i].spd = vec3_set(0.0f, 0.0f, 0.0f);
    rtx.obj[i].note = 0;
  }

  rtx.obj[0].type = PLANE;
  rtx.obj[0].norm = normalize(vec3_set(0.0f, 1.0f, 0.0f));
  rtx.obj[0].dist = 2.0f;
  rtx.obj[0].col = vec3_set(0.1f, 0.3f, 0.6f);
  rtx.obj[0].flag_shadow = TRUE;
  rtx.obj[0].flag_refrect = TRUE;
  rtx.obj[0].spd = vec3_set(0.0f, 0.0f, 0.0f);

  uint32_t scale = 0;
  uint32_t curobj = 0;
  float next_note_time = get_elapsed(time_start) + 3.0f;
  float next_scale_time = get_elapsed(time_start) + 15.0f + randf() * 15.0f;
  float time_now = get_elapsed(time_start);
  float time_quit = time_now + 3600.0f;
  uint32_t retry_count = 0;
  uint32_t counter = 0;
  float time_prev = 0.0f;
  while(time_now < time_quit)
  {
    uint32_t e;
    for (e = 1; e < rtx.objnum; e++)
    {
      rtx.obj[e].pos = vec3_add(rtx.obj[e].pos, rtx.obj[e].spd);
    }
    time_now = get_elapsed(time_start);
    if (time_now > next_note_time)
    {
      e = (curobj % (rtx.objnum - 1)) + 1;
      rtx.obj[e].pos = vec3_set(randf()*8.0f-4.0f, randf()*6.0f-1.0f, randf()*8.0+0.0f);
      rtx.obj[e].col = vec3_set(randf(), randf(), randf());
      rtx.obj[e].spd = vec3_set(randf()*0.1f-0.05f,randf()*0.1f-0.05f,randf()*0.1f-0.05f);
      note_off(&seq, 0, rtx.obj[e].note);
      rtx.obj[e].note = notes[scale][(uint32_t)(randf() * 17.0f) + 12];
      note_on(&seq, 0, rtx.obj[e].note, 127 - rtx.obj[e].note);
      curobj++;
      float len = (randf() + 0.5f);
      next_note_time = time_now + len * len * len;
    }
    if (time_now > next_scale_time)
    {
      scale = (uint32_t)(randf() * (float)SCALE_PATTERN);
      program_change(&seq, 0, instruments[(uint32_t)(randf() * ((float)insts + 0.99f))]);
      rtx.obj[0].col = vec3_set(randf(), randf(), randf());
      rtx.light.pos = vec3_set(randf() * 8.0f - 4.0f, 8.0f, randf() * 4.0f);
      next_scale_time = time_now + (randf() + 0.1f) * 40.0f;
    }

    render(&msg, &rtx, frame_buffer);

    counter++;
    if (counter > 100)
    {
      //printf("FPS: %.2f\n", 100.0f / (time_now - time_prev));
      time_prev = time_now;
      counter = 0;
    }
  }

  close_sequencer(&seq);
  munmap(frame_buffer, mapsize);
  close(fdmem);
  return 0;
}