/* normalise vector */ void vector_norm(Vec *v1, Vec *v2) { if (v_len(v1) > 0) vector_div_sca(v1, v_len(v1), v2); else v_zero(v2); }
/* normalise vector */ void v_norm(Vec *v2, Vec *v1) { if (v_len(v1) > 0) v_div_sca(v2, v1, v_len(v1)); else v_zero(v2); }
/* * Integrate the rotation of the given basis E under angular velocity W * through time DT. */ void sol_rotate(float e[3][3], const float w[3], float dt) { if (v_len(w) > 0.0f) { float a[3], M[16], f[3][3]; /* Compute the rotation matrix. */ v_nrm(a, w); m_rot(M, a, v_len(w) * dt); /* Apply it to the basis. */ m_vxfm(f[0], M, e[0]); m_vxfm(f[1], M, e[1]); m_vxfm(f[2], M, e[2]); /* Re-orthonormalize the basis. */ v_crs(e[2], f[0], f[1]); v_crs(e[1], f[2], f[0]); v_crs(e[0], f[1], f[2]); v_nrm(e[0], e[0]); v_nrm(e[1], e[1]); v_nrm(e[2], e[2]); } }
struct b_goal *sol_goal_test(struct s_vary *vary, float *p, int ui) { const float *ball_p = vary->uv[ui].p; const float ball_r = vary->uv[ui].r; int zi; for (zi = 0; zi < vary->base->zc; zi++) { struct b_goal *zp = vary->base->zv + zi; float r[3]; r[0] = ball_p[0] - zp->p[0]; r[1] = ball_p[2] - zp->p[2]; r[2] = 0; if (v_len(r) + ball_r < zp->r && ball_p[1] > zp->p[1] && ball_p[1] < zp->p[1] + GOAL_HEIGHT / 2) { p[0] = zp->p[0]; p[1] = zp->p[1]; p[2] = zp->p[2]; return zp; } } return NULL; }
/* vector angle */ float v_ang(Vec *v1, Vec *v2) { float cos_angle; /* float c_angle, s_angle, sin_angle; */ /* Vec v3; */ /* cosinus of vector angle from dot product */ /* cos angle = v1 * v2 / ||v1|| * ||v2|| */ /* angle = acos (cos angle) */ cos_angle = v_dot_pro(v1, v2) / (v_len(v1) * v_len(v2)); /*c_angle = acos(cos_angle);*/ /* sinus of vector angle from cross product */ /* sin angle = length (v1 x v2) / (length (v1) * length (v2)) v_cro_pro(&v3, v1, v2); sin_angle = v_len(&v3) / (v_len(v1) * v_len(v2)); s_angle = asin(sin_angle);*/ return (AN * acos(cos_angle)); }
/* * Test for a ball entering a teleporter. */ int sol_jump_test(struct s_vary *vary, float *p, int ui) { const float *ball_p = vary->uv[ui].p; const float ball_r = vary->uv[ui].r; int ji, touch = 0; for (ji = 0; ji < vary->base->jc; ji++) { struct b_jump *jp = vary->base->jv + ji; float d, r[3]; r[0] = ball_p[0] - jp->p[0]; r[1] = ball_p[2] - jp->p[2]; r[2] = 0; /* Distance of the far side from the edge of the halo. */ d = v_len(r) + ball_r - jp->r; /* * The "touch" distance, which must be cleared before being * able to trigger a teleporter, is the ball's radius. (This * is different from switches.) */ if (d <= ball_r && ball_p[1] > jp->p[1] && ball_p[1] < jp->p[1] + JUMP_HEIGHT / 2) { touch = 1; if (d <= 0.0f) { p[0] = jp->q[0] + (ball_p[0] - jp->p[0]); p[1] = jp->q[1] + (ball_p[1] - jp->p[1]); p[2] = jp->q[2] + (ball_p[2] - jp->p[2]); return JUMP_INSIDE; } } } return touch ? JUMP_TOUCH : JUMP_OUTSIDE; }
int sol_item_test(struct s_vary *vary, float *p, float item_r) { const float *ball_p = vary->uv->p; const float ball_r = vary->uv->r; int hi; for (hi = 0; hi < vary->hc; hi++) { struct v_item *hp = vary->hv + hi; float r[3]; v_sub(r, ball_p, hp->p); if (hp->t != ITEM_NONE && v_len(r) < ball_r + item_r) { p[0] = hp->p[0]; p[1] = hp->p[1]; p[2] = hp->p[2]; return hi; } } return -1; }
void game_draw(int pose, float t) { const float light_p[4] = { 8.f, 32.f, 8.f, 0.f }; struct s_draw *fp = &file.draw; struct s_rend rend; float fov = FOV; if (!state) return; fp->shadow_ui = ball; game_shadow_conf(1); sol_draw_enable(&rend); if (jump_b) fov *= 2.0f * fabsf(jump_dt - 0.5f); video_push_persp(fov, 0.1f, FAR_DIST); glPushMatrix(); { float T[16], M[16], v[3], rx, ry; m_view(T, view_c, view_p, view_e[1]); m_xps(M, T); v_sub(v, view_c, view_p); rx = V_DEG(fatan2f(-v[1], fsqrtf(v[0] * v[0] + v[2] * v[2]))); ry = V_DEG(fatan2f(+v[0], -v[2])); glTranslatef(0.f, 0.f, -v_len(v)); glMultMatrixf(M); glTranslatef(-view_c[0], -view_c[1], -view_c[2]); /* Center the skybox about the position of the camera. */ glPushMatrix(); { glTranslatef(view_p[0], view_p[1], view_p[2]); back_draw(&rend, 0); } glPopMatrix(); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, light_p); /* Draw the floor. */ sol_draw(fp, &rend, 0, 1); /* Draw the game elements. */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if (pose == 0) { game_draw_balls(&rend, fp->vary, T, t); game_draw_vect(&rend, fp->vary); } glDisable(GL_LIGHTING); glDepthMask(GL_FALSE); { game_draw_goals(&rend, fp->base); game_draw_jumps(&rend, fp->base); game_draw_swchs(&rend, fp->vary); } glDepthMask(GL_TRUE); glEnable(GL_LIGHTING); } glPopMatrix(); video_pop_matrix(); sol_draw_disable(&rend); game_shadow_conf(0); }
/* * Test for a ball entering a switch. */ int sol_swch_test(struct s_vary *vary, int ui) { const float *ball_p = vary->uv[ui].p; const float ball_r = vary->uv[ui].r; union cmd cmd; int xi, rc = SWCH_OUTSIDE; for (xi = 0; xi < vary->xc; xi++) { struct v_swch *xp = vary->xv + xi; /* FIXME enter/exit events don't work for timed switches */ if (xp->base->t == 0 || xp->f == xp->base->f) { float d, r[3]; r[0] = ball_p[0] - xp->base->p[0]; r[1] = ball_p[2] - xp->base->p[2]; r[2] = 0; /* Distance of the far side from the edge of the halo. */ d = v_len(r) + ball_r - xp->base->r; /* * The "touch" distance, which must be cleared before * being able to trigger a switch, is the ball's diameter. * (This is different from teleporters.) */ if (d <= ball_r * 2 && ball_p[1] > xp->base->p[1] && ball_p[1] < xp->base->p[1] + SWCH_HEIGHT / 2) { if (!xp->e && d <= 0.0f) { /* The ball enters. */ if (xp->base->tm == 0) { xp->e = 1; cmd.type = CMD_SWCH_ENTER; cmd.swchenter.xi = xi; sol_cmd_enq(&cmd); } /* Toggle the state, update the path. */ xp->f = xp->f ? 0 : 1; cmd.type = CMD_SWCH_TOGGLE; cmd.swchtoggle.xi = xi; sol_cmd_enq(&cmd); sol_path_loop(vary, xp->base->pi, xp->f); /* It toggled to non-default state, start the timer. */ if (xp->f != xp->base->f) { xp->t = 0.0f; xp->tm = 0; } /* If visible, set the result. */ if (!xp->base->i) rc = SWCH_INSIDE; } } /* The ball exits. */ else if (xp->e) { xp->e = 0; cmd.type = CMD_SWCH_EXIT; cmd.swchexit.xi = xi; sol_cmd_enq(&cmd); } } } return rc; }
void game_draw(int pose, float t) { const float light_p[4] = { 8.f, 32.f, 8.f, 0.f }; struct s_draw *fp = &file.draw; struct s_rend rend; float fov = FOV; if (!state) return; fp->shadow_ui = ball; game_shadow_conf(1); sol_draw_enable(&rend); if (jump_b) fov *= 2.0f * fabsf(jump_dt - 0.5f); video_push_persp(fov, 0.1f, FAR_DIST); glPushMatrix(); { float T[16], M[16], v[3], c[3]; /* In VR, move the view center up to keep the viewer level. */ v_cpy(c, view_c); if (hmd_stat()) c[1] += view_dy; video_calc_view(T, c, view_p, view_e[1]); m_xps(M, T); v_sub(v, c, view_p); glTranslatef(0.f, 0.f, -v_len(v)); glMultMatrixf(M); glTranslatef(-c[0], -c[1], -c[2]); /* Center the skybox about the position of the camera. */ glPushMatrix(); { glTranslatef(view_p[0], view_p[1], view_p[2]); back_draw(&rend); } glPopMatrix(); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, light_p); /* Draw the floor. */ sol_draw(fp, &rend, 0, 1); /* Draw the game elements. */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if (pose == 0) { game_draw_balls(&rend, fp->vary, T, t); game_draw_vect(&rend, fp->vary); } glDisable(GL_LIGHTING); glDepthMask(GL_FALSE); { game_draw_flags(&rend, fp->base); game_draw_beams(&rend, fp->base, fp->vary); } glDepthMask(GL_TRUE); glEnable(GL_LIGHTING); } glPopMatrix(); video_pop_matrix(); sol_draw_disable(&rend); game_shadow_conf(0); }
void game_draw(struct game_draw *gd, int pose, float t) { float fov = (float) config_get_d(CONFIG_VIEW_FOV); if (gd->jump_b) fov *= 2.f * fabsf(gd->jump_dt - 0.5f); if (gd->state) { const struct game_view *view = &gd->view; struct s_rend rend; gd->draw.shadow_ui = 0; game_shadow_conf(pose, 1); sol_draw_enable(&rend); video_push_persp(fov, 0.1f, FAR_DIST); glPushMatrix(); { float T[16], U[16], M[16], v[3]; /* Compute direct and reflected view bases. */ v[0] = +view->p[0]; v[1] = -view->p[1]; v[2] = +view->p[2]; video_calc_view(T, view->c, view->p, view->e[1]); video_calc_view(U, view->c, v, view->e[1]); m_xps(M, T); /* Apply the current view. */ v_sub(v, view->c, view->p); glTranslatef(0.f, 0.f, -v_len(v)); glMultMatrixf(M); glTranslatef(-view->c[0], -view->c[1], -view->c[2]); /* Draw the background. */ game_draw_back(&rend, gd, pose, +1, t); /* Draw the reflection. */ if (gd->draw.reflective && config_get_d(CONFIG_REFLECTION)) { glEnable(GL_STENCIL_TEST); { /* Draw the mirrors only into the stencil buffer. */ glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(GL_FALSE); game_refl_all(&rend, gd); glDepthMask(GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); /* Draw the scene reflected into color and depth buffers. */ glFrontFace(GL_CW); glPushMatrix(); { glScalef(+1.0f, -1.0f, +1.0f); game_draw_light(gd, -1); game_draw_back(&rend, gd, pose, -1, t); game_draw_fore(&rend, gd, pose, U, -1, t); } glPopMatrix(); glFrontFace(GL_CCW); glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF); } glDisable(GL_STENCIL_TEST); } /* Ready the lights for foreground rendering. */ game_draw_light(gd, 1); /* When reflection is disabled, mirrors must be rendered opaque */ /* to prevent the background from showing. */ if (gd->draw.reflective && !config_get_d(CONFIG_REFLECTION)) { sol_color_mtrl(&rend, 1); { glColor4f(0.0f, 0.0f, 0.0f, 1.0f); game_refl_all(&rend, gd); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); } sol_color_mtrl(&rend, 0); } /* Draw the mirrors and the rest of the foreground. */ game_refl_all (&rend, gd); game_draw_fore(&rend, gd, pose, T, +1, t); } glPopMatrix(); video_pop_matrix(); /* Draw the fade overlay. */ sol_fade(&gd->draw, &rend, gd->fade_k); sol_draw_disable(&rend); game_shadow_conf(pose, 0); } }
int mergevertices(Mvert *data, int vc, int *indices, int fc) { int killed=0; int x; float ea=0.0; int ec=0; // calc edge average for (x=0; x<fc; x++) { int v1, v2, v3; int d; v1=getroot(data, indices[x*3+0], &d); v2=getroot(data, indices[x*3+1], &d); v3=getroot(data, indices[x*3+2], &d); if (v1==v2 || v2==v3 || v3==v1) { // degenerate } else { ea+=v_len(data[v1].pos, data[v2].pos); ea+=v_len(data[v2].pos, data[v3].pos); ea+=v_len(data[v3].pos, data[v1].pos); ec+=3; } } ea/=(float)ec; ea*=0.75; // kludge // merge for (x=0; x<fc; x++) { int v1, v2, v3; int d; v1=getroot(data, indices[x*3+0], &d); v2=getroot(data, indices[x*3+1], &d); v3=getroot(data, indices[x*3+2], &d); #ifdef DEBUG_LODDER if (v1<0 || v1>=vc) glueErrorf("getroot fail v1: %i", v1); if (v2<0 || v2>=vc) glueErrorf("getroot fail v2: %i", v2); if (v3<0 || v3>=vc) glueErrorf("getroot fail v3: %i", v3); #endif if (v1==v2 || v2==v3 || v3==v1) { // degenerate } else { float e1=v_len(data[v1].pos, data[v2].pos); float e2=v_len(data[v2].pos, data[v3].pos); float e3=v_len(data[v3].pos, data[v1].pos); // if one of the edges is shorter than avg*kludge, kill the shortest if (e1<ea || e2<ea || e3<ea) { if (e1<e2 && e1<e3) { data[v2].parent = v1; killed++; } else if (e2<e1 && e2<e3) { data[v3].parent = v2; killed++; } else { // if (e3<e1 && e3<e2) { data[v1].parent = v3; killed++; } } } } return killed; }
/* Third version of draw triangle uses a z_buffer And we're using flat shading clear_z_buffer needs to be run in the main loop before every frame. */ void draw_triangle3(int *a,int *b,int *c,vect_t pos,vect_t rot,rgb color){ int x0,y0,x1,y1,x2,y2; // this is is the format that the triangles should be passed to us already vect_t x={a[0],a[1],a[2]+Z}; vect_t y={b[0],b[1],b[2]+Z}; vect_t z={c[0],c[1],c[2]+Z}; // Lighting vect_t n=v_norm(v_cross(x,y)); // vect_t l=v_sub(cam.pos,x); vect_t l=cam.pos; double lum=1.0; // if( lum < 0 ) return 0; rgb colors[3]; point p[3]; x=v_rot(x,rot); y=v_rot(y,rot); z=v_rot(z,rot); // should we do the translation here as well does this make sense? x=v_add(x,pos); y=v_add(y,pos); z=v_add(z,pos); double lums[3]; lums[0]=v_dot(l,x)/(v_len(l)*v_len(x)); lums[1]=v_dot(l,y)/(v_len(l)*v_len(y)); lums[2]=v_dot(l,z)/(v_len(l)*v_len(z)); #if 1 for(int i=0;i<3;i++){ #if 0 lum=lums[i]; if( lum < 0 ) lum=0; #else lum=1.0; #endif colors[i].r=clip(color.r*lum); colors[i].g=clip(color.g*lum); colors[i].b=clip(color.b*lum); } #else for(int i=0;i<3;i++){ colors[i].r=color.r; colors[i].g=color.g; colors[i].b=color.b; } #endif int q,w,e; q=project_coord(x,&p[0].x,&p[0].y); w=project_coord(y,&p[1].x,&p[1].y); e=project_coord(z,&p[2].x,&p[2].y); if(outside_of_screen(p)){ return; } rgb ca[3]; ca[0]=ca[1]=ca[2]=color; vect_t v3[3]; v3[0]=x; v3[1]=y; v3[2]=z; double distances[3]; // introduce max distance of 5000 distances[0]=clipfloat(v_len(v_sub(x,cam.pos)),0,MAX_DIST)/MAX_DIST; distances[1]=clipfloat(v_len(v_sub(y,cam.pos)),0,MAX_DIST)/MAX_DIST; distances[2]=clipfloat(v_len(v_sub(z,cam.pos)),0,MAX_DIST)/MAX_DIST; /* distances[0]=v_len(v_sub(z,cam.pos)); distances[1]=v_len(v_sub(y,cam.pos)); distances[2]=v_len(v_sub(x,cam.pos)); */ draw_triangle_gradient_new(p,v3,distances,colors); #if 0 draw_line_color(p[0].x,p[0].y,p[1].x,p[1].y,black); draw_line_color(p[1].x,p[1].y,p[2].x,p[2].y,black); draw_line_color(p[1].x,p[1].y,p[0].x,p[0].y,black); #endif }
void multiple_common_substring( const std::vector<std::string> &strs, std::vector<std::string> &align) { if (strs.size() == 1) { align.push_back(strs[0]); align.push_back(std::string(strs[0].length(), ' ')); return; } // std::vector<char> seq; std::vector<id_type> ids; std::vector<word_t> offs; for (id_type id = 0; id != strs.size(); ++id) { offs.push_back(seq.size()); std::copy(strs[id].begin(), strs[id].end(), std::back_inserter(seq)); seq.push_back('\0'); seq.push_back(id); ids.insert(ids.end(), strs[id].length() + 2, id); } offs.push_back(seq.size()); // const word_t K = strs.size(); // suffix_t suf(&seq[0], seq.size()); for (word_t i = 0; i != seq.size() - 1; ++i) suf.push_back(); // std::vector<word_t> h(suf.size() * 2); // { patl::lca_oracle<suffix_t> lca(suf); // std::vector<const_vertex> last_vtx(K); // for (suffix_t::const_iterator it = suf.begin(); it != suf.end(); ++it) { const word_t k = ids[*it - suf.keys()]; const const_vertex &vtx = static_cast<const const_vertex&>(it); if (last_vtx[k].compact()) ++h[suf.vertex_index_of(lca(last_vtx[k], vtx))]; last_vtx[k] = vtx; } } // #ifdef MULTI_ALIGN_DEBUG { std::ofstream fout("malign_suf.dot"); patricia_dot_base<suffix_t> pdb(&ids, &h); patl::patricia_dot_creator< suffix_t, std::ofstream, patricia_dot_base<suffix_t> > dotcr(fout, pdb); dotcr.create(suf.root()); } #endif // std::vector<const_vertex> v(K + 1); std::vector<word_t> v_len(K + 1); // std::vector<word_t> s, u; const const_vertex root = suf.root(); const suffix_t::const_postorder_iterator pit_beg = root.postorder_begin(), pit_end = root.postorder_end(); for (suffix_t::const_postorder_iterator pit = pit_beg; pit != pit_end; ++pit) { if (pit->get_qtag()) { s.push_back(1); u.push_back(0); } else { const word_t s_v = s.back() + s[s.size() - 2], u_v = u.back() + u[u.size() - 2] + h[suf.vertex_index_of(*pit)], c_v = s_v - u_v, idx = suf.index_of(*pit), len = patl::impl::get_min( pit->next_skip() / 8, patl::impl::max0(strs[ids[idx]].length() - (idx - offs[ids[idx]]))); if (len > v_len[c_v]) { v[c_v] = *pit; v_len[c_v] = len; } s.pop_back(); s.back() = s_v; u.pop_back(); u.back() = u_v; } } // for (word_t k = K - 1; k != 1; --k) { if (v_len[k] < v_len[k + 1]) { v[k] = v[k + 1]; v_len[k] = v_len[k + 1]; } } // multiple common substrings #ifdef MULTI_ALIGN_DEBUG printf("---\n"); for (word_t k = 2; k != v.size(); ++k) { if (v[k].compact()) printf("%u\t%u\t%s\n", k, v_len[k], std::string(v[k].key(), v_len[k]).c_str()); } #endif // эвристический выбор подход¤щего k word_t k_cur = v.size() - 1; for (; k_cur != 1 && v_len[k_cur] < 2; --k_cur) ; if (k_cur == 1) { for (k_cur = v.size() - 1; k_cur != 1 && !v_len[k_cur]; --k_cur) ; if (k_cur == 1) { word_t max_len = 0; for (id_type i = 0; i != strs.size(); ++i) { if (strs[i].length() > max_len) max_len = strs[i].length(); } for (id_type i = 0; i != strs.size(); ++i) { align.push_back(strs[i]); std::string &ref = align.back(); while (ref.length() != max_len) ref.push_back(' '); } align.push_back(std::string(max_len, ' ')); return; } } // // std::pair<номер строки, смещение в строке> typedef std::map<id_type, word_t> motif_map; motif_map motifs; // номера строк с повтор¤ющимс¤ мотивом { const suffix_t::const_iterator it_end = v[k_cur].end(); for (suffix_t::const_iterator it = v[k_cur].begin(); it != it_end; ++it) { const id_type id = ids[*it - suf.keys()]; const word_t off = *it - suf.keys() - offs[id]; motifs[id] = off; } } const word_t motif_len = v_len[k_cur]; const std::string motif(v[k_cur].key(), motif_len), padding(motif_len, ' '); align.clear(); for (id_type i = 0; i != K; ++i) align.push_back(motifs.find(i) != motifs.end() ? motif : padding); align.push_back(std::string(motif_len, '^')); word_t sum_left = 0, sum_right = 0; for (motif_map::const_iterator it = motifs.begin(); it != motifs.end(); ++it) { if (it->second) ++sum_left; if (strs[it->first].length() - it->second - motif_len) ++sum_right; } // left side if (sum_left) { std::vector<id_type> left_ids; std::vector<std::string> left_strs; for (id_type i = 0; i != K; ++i) { const motif_map::const_iterator it = motifs.find(i); if (it != motifs.end()) { if (it->second) { left_ids.push_back(it->first); left_strs.push_back(strs[it->first].substr(0, it->second)); } } else { left_ids.push_back(i); left_strs.push_back(strs[i]); } } std::vector<std::string> left_align; multiple_common_substring(left_strs, left_align); const word_t left_len = left_align[0].length(); const std::string left_pad(left_len, ' '); for (id_type i = 0, j = 0; i != K; ++i) { align[i].insert(0, j != left_ids.size() && left_ids[j] == i ? left_align[j++] : left_pad); } align.back().insert(0, left_align.back()); } // right side if (sum_right) { std::vector<id_type> right_ids; std::vector<std::string> right_strs; for (id_type i = 0; i != K; ++i) { const motif_map::const_iterator it = motifs.find(i); if (it != motifs.end()) { if (strs[it->first].length() - it->second - motif_len) { right_ids.push_back(it->first); right_strs.push_back(strs[it->first].substr(it->second + motif_len)); } } else if (!sum_left) { right_ids.push_back(i); right_strs.push_back(strs[i]); } } std::vector<std::string> right_align; multiple_common_substring(right_strs, right_align); const word_t right_len = right_align[0].length(); const std::string right_pad(right_len, ' '); for (id_type i = 0, j = 0; i != K; ++i) { align[i].append(j != right_ids.size() && right_ids[j] == i ? right_align[j++] : right_pad); } align.back().append(right_align.back()); } // neither left nor right if (!sum_left && !sum_right && K - k_cur) { std::vector<id_type> neither_ids; std::vector<std::string> neither_strs; for (id_type i = 0; i != K; ++i) { const motif_map::const_iterator it = motifs.find(i); if (it == motifs.end()) { neither_ids.push_back(i); neither_strs.push_back(strs[i]); } } std::vector<std::string> neither_align; multiple_common_substring(neither_strs, neither_align); const word_t neither_len = neither_align[0].length(); const std::string neither_pad(neither_len, ' '); for (id_type i = 0, j = 0; i != K; ++i) { align[i].append(j != neither_ids.size() && neither_ids[j] == i ? neither_align[j++] : neither_pad); } align.back().append(neither_align.back()); } }
void game_draw(int pose, float t) { static const float a[4] = { 0.2f, 0.2f, 0.2f, 1.0f }; static const float s[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; static const float e[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; static const float h[1] = { 0.0f }; const float light_p[4] = { 8.f, 32.f, 8.f, 1.f }; const struct s_file *fp = &file; float fov = FOV; if (jump_b) fov *= 2.0f * fabsf(jump_dt - 0.5f); video_push_persp(fov, 0.1f, FAR_DIST); glPushAttrib(GL_LIGHTING_BIT); glPushMatrix(); { float T[16], M[16], v[3], rx, ry; m_view(T, view_c, view_p, view_e[1]); m_xps(M, T); v_sub(v, view_c, view_p); rx = V_DEG(fatan2f(-v[1], fsqrtf(v[0] * v[0] + v[2] * v[2]))); ry = V_DEG(fatan2f(+v[0], -v[2])); glTranslatef(0.f, 0.f, -v_len(v)); glMultMatrixf(M); glTranslatef(-view_c[0], -view_c[1], -view_c[2]); /* Center the skybox about the position of the camera. */ glPushMatrix(); { glTranslatef(view_p[0], view_p[1], view_p[2]); back_draw(0); } glPopMatrix(); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0, GL_POSITION, light_p); /* Draw the floor. */ sol_draw(fp, 0, 1); if (config_get_d(CONFIG_SHADOW) && !pose) { shad_draw_set(fp->uv[ball].p, fp->uv[ball].r); sol_shad(fp); shad_draw_clr(); } /* Draw the game elements. */ glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if (pose == 0) { game_draw_balls(fp, T, t); game_draw_vect(fp); } glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, a); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, s); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, e); glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, h); game_draw_goals(fp); glEnable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glDepthMask(GL_FALSE); { game_draw_jumps(fp); game_draw_swchs(fp); } glDepthMask(GL_TRUE); glEnable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); } glPopMatrix(); glPopAttrib(); video_pop_matrix(); }
float sol_step(struct s_vary *vary, const float *g, float dt, int ui, int *m) { float P[3], V[3], v[3], r[3], a[3], d, e, nt, b = 0.0f, tt = dt, t; int c; union cmd cmd; if (ui < vary->uc) { struct v_ball *up = vary->uv + ui; /* If the ball is in contact with a surface, apply friction. */ v_cpy(a, up->v); v_cpy(v, up->v); v_cpy(up->v, g); if (m && sol_test_file(tt, P, V, up, vary) < 0.0005f) { v_cpy(up->v, v); v_sub(r, P, up->p); t = v_len(r) * v_len(g); if (t == 0.f) { t = SMALL; } if ((d = v_dot(r, g) / t) > 0.999f) { if ((e = (v_len(up->v) - dt)) > 0.0f) { /* Scale the linear velocity. */ v_nrm(up->v, up->v); v_scl(up->v, up->v, e); /* Scale the angular velocity. */ v_sub(v, V, up->v); v_crs(up->w, v, r); v_scl(up->w, up->w, -1.0f / (up->r * up->r)); } else { /* Friction has brought the ball to a stop. */ up->v[0] = 0.0f; up->v[1] = 0.0f; up->v[2] = 0.0f; (*m)++; } } else v_mad(up->v, v, g, tt); } else v_mad(up->v, v, g, tt); /* Test for collision. */ for (c = 16; c > 0 && tt > 0; c--) { float st; int mi, ms; /* HACK: avoid stepping across path changes. */ st = tt; for (mi = 0; mi < vary->mc; mi++) { struct v_move *mp = vary->mv + mi; struct v_path *pp = vary->pv + mp->pi; if (!pp->f) continue; if (mp->tm + ms_peek(st) > pp->base->tm) st = MS_TO_TIME(pp->base->tm - mp->tm); } /* Miss collisions if we reach the iteration limit. */ if (c > 1) nt = sol_test_file(st, P, V, up, vary); else nt = tt; cmd.type = CMD_STEP_SIMULATION; cmd.stepsim.dt = nt; sol_cmd_enq(&cmd); ms = ms_step(nt); sol_move_step(vary, nt, ms); sol_swch_step(vary, nt, ms); sol_ball_step(vary, nt); if (nt < st) if (b < (d = sol_bounce(up, P, V, nt))) b = d; tt -= nt; } v_sub(a, up->v, a); sol_pendulum(up, a, g, dt); } return b; }
void game_draw(int pose, float st) { float fov = view_fov; if (jump_b) fov *= 2.f * fabsf(jump_dt - 0.5); if (game_state) { config_push_persp(fov, 0.1f, FAR_DIST); glPushMatrix(); { float v[3], rx, ry; float pup[3]; float pdn[3]; v_cpy(pup, view_p); v_cpy(pdn, view_p); pdn[1] = -pdn[1]; /* Compute and apply the view. */ v_sub(v, view_c, view_p); rx = V_DEG(fatan2f(-v[1], fsqrtf(v[0] * v[0] + v[2] * v[2]))); ry = V_DEG(fatan2f(+v[0], -v[2])) + st; glTranslatef(0.f, 0.f, -v_len(v)); glRotatef(rx, 1.f, 0.f, 0.f); glRotatef(ry, 0.f, 1.f, 0.f); glTranslatef(-view_c[0], -view_c[1], -view_c[2]); #ifndef DREAMCAST_KGL_NOT_IMPLEMENT if (config_get_d(CONFIG_REFLECTION)) { /* Draw the mirror only into the stencil buffer. */ glDisable(GL_DEPTH_TEST); glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); game_refl_all(0); /* Draw the scene reflected into color and depth buffers. */ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); glEnable(GL_DEPTH_TEST); glFrontFace(GL_CW); glPushMatrix(); { glScalef(+1.f, -1.f, +1.f); game_draw_light(); game_draw_back(pose, -1, pdn); game_draw_fore(pose, rx, ry, -1, pdn); } glPopMatrix(); glFrontFace(GL_CCW); glDisable(GL_STENCIL_TEST); } #endif /* Draw the scene normally. */ game_draw_light(); game_refl_all(pose ? 0 : config_get_d(CONFIG_SHADOW)); game_draw_back(pose, +1, pup); game_draw_fore(pose, rx, ry, +1, pup); } glPopMatrix(); config_pop_matrix(); /* Draw the fade overlay. */ fade_draw(fade_k); } }
static void game_update_view(float dt) { float dc = view.dc * (jump_b > 0 ? 2.0f * fabsf(jump_dt - 0.5f) : 1.0f); float da = input_get_r() * dt * 90.0f; float k; float M[16], v[3], Y[3] = { 0.0f, 1.0f, 0.0f }; float view_v[3]; float spd = (float) cam_speed(input_get_c()) / 1000.0f; /* Track manual rotation time. */ if (da == 0.0f) { if (view_time < 0.0f) { /* Transition time is influenced by activity time. */ view_fade = CLAMP(VIEW_FADE_MIN, -view_time, VIEW_FADE_MAX); view_time = 0.0f; } /* Inactivity. */ view_time += dt; } else { if (view_time > 0.0f) { view_fade = 0.0f; view_time = 0.0f; } /* Activity (yes, this is negative). */ view_time -= dt; } /* Center the view about the ball. */ v_cpy(view.c, vary.uv->p); view_v[0] = -vary.uv->v[0]; view_v[1] = 0.0f; view_v[2] = -vary.uv->v[2]; /* Compute view vector. */ if (spd >= 0.0f) { /* Viewpoint chases ball position. */ if (da == 0.0f) { float s; v_sub(view.e[2], view.p, view.c); v_nrm(view.e[2], view.e[2]); /* Gradually restore view vector convergence rate. */ s = fpowf(view_time, 3.0f) / fpowf(view_fade, 3.0f); s = CLAMP(0.0f, s, 1.0f); v_mad(view.e[2], view.e[2], view_v, v_len(view_v) * spd * s * dt); } } else { /* View vector is given by view angle. */ view.e[2][0] = fsinf(V_RAD(view.a)); view.e[2][1] = 0.0; view.e[2][2] = fcosf(V_RAD(view.a)); } /* Apply manual rotation. */ if (da != 0.0f) { m_rot(M, Y, V_RAD(da)); m_vxfm(v, M, view.e[2]); v_cpy(view.e[2], v); } /* Orthonormalize the new view reference frame. */ v_crs(view.e[0], view.e[1], view.e[2]); v_crs(view.e[2], view.e[0], view.e[1]); v_nrm(view.e[0], view.e[0]); v_nrm(view.e[2], view.e[2]); /* Compute the new view position. */ k = 1.0f + v_dot(view.e[2], view_v) / 10.0f; view_k = view_k + (k - view_k) * dt; if (view_k < 0.5) view_k = 0.5; v_scl(v, view.e[1], view.dp * view_k); v_mad(v, v, view.e[2], view.dz * view_k); v_add(view.p, v, vary.uv->p); /* Compute the new view center. */ v_cpy(view.c, vary.uv->p); v_mad(view.c, view.c, view.e[1], dc); /* Note the current view angle. */ view.a = V_DEG(fatan2f(view.e[2][0], view.e[2][2])); game_cmd_updview(); }