-/*
+/*
* Copyright (C) 2003 Robert Kooima
*
* NEVERBALL is free software; you can redistribute it and/or modify
#include "geom.h"
#include "back.h"
#include "part.h"
-#include "hud.h"
#include "image.h"
#include "audio.h"
-#include "solid.h"
-#include "level.h"
+#include "solid_gl.h"
#include "config.h"
#include "binary.h"
+#include "level.h"
/*---------------------------------------------------------------------------*/
static float view_e[3][3]; /* Current view orientation */
static float view_k;
-static int goal_e = 0; /* Goal enabled flag */
+static int coins = 0; /* Collected coins */
+static int goal_c = 0; /* Goal coins remaining (0 = open) */
static float goal_k = 0; /* Goal animation */
-static int goal_s = 0; /* Goal reached flag */
-static int swch_e = 1; /* Switching enabled flag */
static int jump_e = 1; /* Jumping enabled flag */
static int jump_b = 0; /* Jump-in-progress flag */
static float jump_dt; /* Jump duration */
/*---------------------------------------------------------------------------*/
+static int grow = 0; /* Should the ball be changing size? */
+static float grow_orig = 0; /* the original ball size */
+static float grow_goal = 0; /* how big or small to get! */
+static float grow_t = 0.0; /* timer for the ball to grow... */
+static float grow_strt = 0; /* starting value for growth */
+static int got_orig = 0; /* Do we know original ball size? */
+
+#define GROW_TIME 0.5f /* sec for the ball to get to size. */
+#define GROW_BIG 1.5f /* large factor */
+#define GROW_SMALL 0.5f /* small factor */
+
+static int grow_state = 0; /* Current state (values -1, 0, +1) */
+
+static void grow_init(const struct s_file *fp, int type)
+{
+ if (!got_orig)
+ {
+ grow_orig = fp->uv->r;
+ grow_goal = grow_orig;
+ grow_strt = grow_orig;
+
+ grow_state = 0;
+
+ got_orig = 1;
+ }
+
+ if (type == ITEM_SHRINK)
+ {
+ audio_play(AUD_SHRINK, 1.f);
+
+ switch (grow_state)
+ {
+ case -1:
+ break;
+
+ case 0:
+ grow_goal = grow_orig * GROW_SMALL;
+ grow_state = -1;
+ grow = 1;
+ break;
+
+ case +1:
+ grow_goal = grow_orig;
+ grow_state = 0;
+ grow = 1;
+ break;
+ }
+ }
+ else if (type == ITEM_GROW)
+ {
+ audio_play(AUD_GROW, 1.f);
+
+ switch (grow_state)
+ {
+ case -1:
+ grow_goal = grow_orig;
+ grow_state = 0;
+ grow = 1;
+ break;
+
+ case 0:
+ grow_goal = grow_orig * GROW_BIG;
+ grow_state = +1;
+ grow = 1;
+ break;
+
+ case +1:
+ break;
+ }
+ }
+
+ if (grow)
+ {
+ grow_t = 0.0;
+ grow_strt = fp->uv->r;
+ }
+}
+
+static void grow_step(const struct s_file *fp, float dt)
+{
+ float dr;
+
+ if (!grow)
+ return;
+
+ /* Calculate new size based on how long since you touched the coin... */
+
+ grow_t += dt;
+
+ if (grow_t >= GROW_TIME)
+ {
+ grow = 0;
+ grow_t = GROW_TIME;
+ }
+
+ dr = grow_strt + ((grow_goal-grow_strt) * (1.0f / (GROW_TIME / grow_t)));
+
+ /* No sinking through the floor! Keeps ball's bottom constant. */
+
+ fp->uv->p[1] += (dr - fp->uv->r);
+ fp->uv->r = dr;
+}
+
+/*---------------------------------------------------------------------------*/
+
static void view_init(void)
{
view_a = 0.f;
view_e[2][2] = 1.f;
}
-int game_init(const char *file_name,
- const char *back_name,
- const char *grad_name, int t, int e)
+int game_init(const struct level *level, int t, int g)
{
clock = (float) t / 100.f;
clock_down = (t > 0);
+ coins = 0;
if (game_state)
game_free();
+ if (!sol_load_gl(&file, config_data(level->file),
+ config_get_d(CONFIG_TEXTURES),
+ config_get_d(CONFIG_SHADOW)))
+ return (game_state = 0);
+
+ game_state = 1;
+
game_ix = 0.f;
game_iz = 0.f;
game_rx = 0.f;
jump_e = 1;
jump_b = 0;
- goal_e = e ? 1 : 0;
- goal_k = e ? 1.0f : 0.0f;
- goal_s = 0;
-
- /* Reset the hud. */
-
- hud_ball_pulse(0.f);
- hud_time_pulse(0.f);
- hud_coin_pulse(0.f);
+ goal_c = g;
+ goal_k = (g == 0) ? 1.0f : 0.0f;
/* Initialise the level, background, particles, fade, and view. */
part_reset(GOAL_HEIGHT);
view_init();
- back_init(grad_name, config_get_d(CONFIG_GEOMETRY));
-
- if (sol_load(&back, config_data(back_name),
- config_get_d(CONFIG_TEXTURES), 0) &&
- sol_load(&file, config_data(file_name),
- config_get_d(CONFIG_TEXTURES), config_get_d(CONFIG_SHADOW)))
- return (game_state = 1);
- else
- return (game_state = 0);
+ back_init(level->grad, config_get_d(CONFIG_GEOMETRY));
+
+ sol_load_gl(&back, config_data(level->back),
+ config_get_d(CONFIG_TEXTURES), 0);
+
+ /* Initialize ball size tracking... */
+
+ got_orig = 0;
+ grow = 0;
+
+ return game_state;
}
void game_free(void)
{
if (game_state)
{
- sol_free(&file);
- sol_free(&back);
+ sol_free_gl(&file);
+ sol_free_gl(&back);
back_free();
}
game_state = 0;
return (int) (clock * 100.f);
}
-char *curr_intro(void)
+int curr_coins(void)
{
- return (file.ac > 0) ? file.av : NULL;
+ return coins;
+}
+
+int curr_goal(void)
+{
+ return goal_c;
}
/*---------------------------------------------------------------------------*/
fp->uv[0].r);
glColor4fv(c);
-
ball_draw();
}
glPopMatrix();
}
-static void game_draw_coins(const struct s_file *fp)
+static void game_draw_items(const struct s_file *fp)
{
float r = 360.f * SDL_GetTicks() / 1000.f;
- int ci;
+ int hi;
+
+ item_push(ITEM_COIN);
+ {
+ for (hi = 0; hi < fp->hc; hi++)
+
+ if (fp->hv[hi].t == ITEM_COIN && fp->hv[hi].n > 0)
+ {
+ glPushMatrix();
+ {
+ glTranslatef(fp->hv[hi].p[0],
+ fp->hv[hi].p[1],
+ fp->hv[hi].p[2]);
+ glRotatef(r, 0.0f, 1.0f, 0.0f);
+ item_draw(&fp->hv[hi], r);
+ }
+ glPopMatrix();
+ }
+ }
+ item_pull();
+
+ item_push(ITEM_SHRINK);
+ {
+ for (hi = 0; hi < fp->hc; hi++)
+
+ if (fp->hv[hi].t == ITEM_SHRINK)
+ {
+ glPushMatrix();
+ {
+ glTranslatef(fp->hv[hi].p[0],
+ fp->hv[hi].p[1],
+ fp->hv[hi].p[2]);
+ glRotatef(r, 0.0f, 1.0f, 0.0f);
+ item_draw(&fp->hv[hi], r);
+ }
+ glPopMatrix();
+ }
+ }
+ item_pull();
- coin_push();
+ item_push(ITEM_GROW);
{
- for (ci = 0; ci < fp->cc; ci++)
- if (fp->cv[ci].n > 0)
+ for (hi = 0; hi < fp->hc; hi++)
+
+ if (fp->hv[hi].t == ITEM_GROW)
{
glPushMatrix();
{
- glTranslatef(fp->cv[ci].p[0],
- fp->cv[ci].p[1],
- fp->cv[ci].p[2]);
+ glTranslatef(fp->hv[hi].p[0],
+ fp->hv[hi].p[1],
+ fp->hv[hi].p[2]);
glRotatef(r, 0.0f, 1.0f, 0.0f);
- coin_draw(fp->cv[ci].n, r);
+ item_draw(&fp->hv[hi], r);
}
glPopMatrix();
}
}
- coin_pull();
+ item_pull();
}
static void game_draw_goals(const struct s_file *fp, float rx, float ry)
{
- int zi;
+ if (goal_c == 0)
+ {
+ int zi;
+
+ /* Draw the goal particles. */
+
+ glEnable(GL_TEXTURE_2D);
+ {
+ for (zi = 0; zi < fp->zc; zi++)
+ {
+ glPushMatrix();
+ {
+ glTranslatef(fp->zv[zi].p[0],
+ fp->zv[zi].p[1],
+ fp->zv[zi].p[2]);
+
+ part_draw_goal(rx, ry, fp->zv[zi].r, goal_k);
+ }
+ glPopMatrix();
+ }
+ }
+ glDisable(GL_TEXTURE_2D);
+
+ /* Draw the goal column. */
- if (goal_e)
for (zi = 0; zi < fp->zc; zi++)
{
glPushMatrix();
fp->zv[zi].p[1],
fp->zv[zi].p[2]);
- part_draw_goal(rx, ry, fp->zv[zi].r, goal_k);
+ glScalef(fp->zv[zi].r,
+ goal_k,
+ fp->zv[zi].r);
- glScalef(fp->zv[zi].r, goal_k, fp->zv[zi].r);
goal_draw();
}
glPopMatrix();
}
+ }
}
static void game_draw_jumps(const struct s_file *fp)
glTranslatef(fp->jv[ji].p[0],
fp->jv[ji].p[1],
fp->jv[ji].p[2]);
+ glScalef(fp->jv[ji].r,
+ 1.0f,
+ fp->jv[ji].r);
- glScalef(fp->jv[ji].r, 1.f, fp->jv[ji].r);
- jump_draw();
+ jump_draw(!jump_e);
}
glPopMatrix();
}
for (xi = 0; xi < fp->xc; xi++)
{
+ if (fp->xv[xi].i)
+ continue;
+
glPushMatrix();
{
glTranslatef(fp->xv[xi].p[0],
fp->xv[xi].p[1],
fp->xv[xi].p[2]);
+ glScalef(fp->xv[xi].r,
+ 1.0f,
+ fp->xv[xi].r);
- glScalef(fp->xv[xi].r, 1.f, fp->xv[xi].r);
- swch_draw(fp->xv[xi].f);
+ swch_draw(fp->xv[xi].f, fp->xv[xi].e);
}
glPopMatrix();
}
/*---------------------------------------------------------------------------*/
-static void game_refl_all(int s)
+static void game_refl_all()
{
const float *ball_p = file.uv->p;
static void game_draw_light(void)
{
const float light_p[2][4] = {
- { -8.0f, +32.0f, -8.0f, 1.0f },
- { +8.0f, +32.0f, +8.0f, 1.0f },
+ { -8.0f, +32.0f, -8.0f, 0.0f },
+ { +8.0f, +32.0f, +8.0f, 0.0f },
};
const float light_c[2][4] = {
{ 1.0f, 0.8f, 0.8f, 1.0f },
{
/* Draw all background layers back to front. */
- sol_back(&back, BACK_DIST, FAR_DIST, t);
+ sol_back(&back, BACK_DIST, FAR_DIST, t);
back_draw(0);
- sol_back(&back, 0, BACK_DIST, t);
+ sol_back(&back, 0, BACK_DIST, t);
/* Draw all foreground geometry in the background file. */
+ /* HACK: This is never used.
sol_draw(&back);
+ */
}
else back_draw(0);
}
glPopMatrix();
}
-static void game_draw_fore(int pose, float rx, float ry, int d, const float p[3])
+static void game_draw_fore(int pose, float rx,
+ float ry, int d, const float p[3])
{
+ 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 *ball_p = file.uv->p;
const float ball_r = file.uv->r;
-
- glPushAttrib(GL_LIGHTING_BIT | GL_COLOR_BUFFER_BIT);
+
+ glPushMatrix();
{
- glPushMatrix();
- {
- /* Rotate the environment about the position of the ball. */
+ /* Rotate the environment about the position of the ball. */
- glTranslatef(+ball_p[0], +ball_p[1] * d, +ball_p[2]);
- glRotatef(-game_rz * d, view_e[2][0], view_e[2][1], view_e[2][2]);
- glRotatef(-game_rx * d, view_e[0][0], view_e[0][1], view_e[0][2]);
- glTranslatef(-ball_p[0], -ball_p[1] * d, -ball_p[2]);
+ glTranslatef(+ball_p[0], +ball_p[1] * d, +ball_p[2]);
+ glRotatef(-game_rz * d, view_e[2][0], view_e[2][1], view_e[2][2]);
+ glRotatef(-game_rx * d, view_e[0][0], view_e[0][1], view_e[0][2]);
+ glTranslatef(-ball_p[0], -ball_p[1] * d, -ball_p[2]);
- if (d < 0)
- {
- GLdouble e[4];
+ if (d < 0)
+ {
+ GLdouble e[4];
- e[0] = +0;
- e[1] = +1;
- e[2] = +0;
- e[3] = -0.00001;
+ e[0] = +0;
+ e[1] = +1;
+ e[2] = +0;
+ e[3] = -0.00001;
- glEnable(GL_CLIP_PLANE0);
- glClipPlane(GL_CLIP_PLANE0, e);
- }
+ glEnable(GL_CLIP_PLANE0);
+ glClipPlane(GL_CLIP_PLANE0, e);
+ }
+
+ /* Draw the floor. */
- /* Draw the floor. */
+ sol_draw(&file);
- sol_draw(&file);
+ if (pose == 0)
+ {
+ /* Draw the ball shadow. */
- if (config_get_d(CONFIG_SHADOW))
+ if (d > 0 && config_get_d(CONFIG_SHADOW))
{
shad_draw_set(ball_p, ball_r);
sol_shad(&file);
shad_draw_clr();
}
- /* Draw the game elements. */
+ /* Draw the ball and coins. */
+
+ game_draw_items(&file);
+ game_draw_balls(&file);
+ }
+
+ /* Draw the particles and light columns. */
+
+ 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);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_COLOR_MATERIAL);
+ glDisable(GL_LIGHTING);
+ glDepthMask(GL_FALSE);
+ {
+ part_draw_coin(-rx * d, -ry);
- if (pose == 0)
+ glDisable(GL_TEXTURE_2D);
{
- part_draw_coin(-rx * d, -ry);
- game_draw_coins(&file);
- game_draw_balls(&file);
+ game_draw_goals(&file, -rx * d, -ry);
+ game_draw_jumps(&file);
+ game_draw_swchs(&file);
}
- game_draw_goals(&file, -rx * d, -ry);
- game_draw_jumps(&file);
- game_draw_swchs(&file);
+ glEnable(GL_TEXTURE_2D);
+ }
+ glDepthMask(GL_TRUE);
+ glEnable(GL_LIGHTING);
+ glDisable(GL_COLOR_MATERIAL);
+ if (d < 0)
glDisable(GL_CLIP_PLANE0);
- }
- glPopMatrix();
}
- glPopAttrib();
+ glPopMatrix();
}
void game_draw(int pose, float st)
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);
+ {
+ /* Draw the mirrors only into the stencil buffer. */
- game_refl_all(0);
+ glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glDepthMask(GL_FALSE);
- /* Draw the scene reflected into color and depth buffers. */
+ game_refl_all();
- 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);
+ glDepthMask(GL_TRUE);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
- glFrontFace(GL_CW);
- glPushMatrix();
- {
- glScalef(+1.f, -1.f, +1.f);
+ /* Draw the scene reflected into color and depth buffers. */
- game_draw_light();
- game_draw_back(pose, -1, pdn);
- game_draw_fore(pose, rx, ry, -1, pdn);
- }
- glPopMatrix();
- glFrontFace(GL_CCW);
+ 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);
}
/* Draw the scene normally. */
game_draw_light();
- game_refl_all(pose ? 0 : config_get_d(CONFIG_SHADOW));
+ game_refl_all();
game_draw_back(pose, +1, pup);
game_draw_fore(pose, rx, ry, +1, pup);
}
static void game_update_time(float dt, int b)
{
- int tick = (int) floor(clock);
- int tock = (int) floor(clock * 2);
-
- if (goal_e && goal_k < 1.0f)
+ if (goal_c == 0 && goal_k < 1.0f)
goal_k += dt;
/* The ticking clock. */
clock -= dt;
if (clock < 0.f)
clock = 0.f;
-
- if (0 < tick && tick <= 10 && tick == (int) ceil(clock))
- {
- audio_play(AUD_TICK, 1.f);
- hud_time_pulse(1.50);
- }
- else if (0 < tock && tock <= 10 && tock == (int) ceil(clock * 2))
- {
- audio_play(AUD_TOCK, 1.f);
- hud_time_pulse(1.25);
- }
}
else if (b)
{
static int game_update_state(int bt)
{
struct s_file *fp = &file;
+ struct s_goal *zp;
+ struct s_item *hp;
+
float p[3];
float c[3];
- int n, e = swch_e;
- /* Test for a coin grab. */
-
- if (bt && (n = sol_coin_test(fp, p, COIN_RADIUS)) > 0)
+ /* Test for an item. */
+ if (bt && (hp = sol_item_test(fp, p, COIN_RADIUS)))
{
- coin_color(c, n);
+ const char *sound = AUD_COIN;
+
+ item_color(hp, c);
part_burst(p, c);
- if (level_score(n))
- goal_e = 1;
+ grow_init(fp, hp->t);
+
+ if (hp->t == ITEM_COIN)
+ {
+ coins += hp->n;
+
+ /* Check for goal open. */
+ if (goal_c > 0)
+ {
+ goal_c -= hp->n;
+ if (goal_c <= 0)
+ {
+ sound = AUD_SWITCH;
+ goal_c = 0;
+ }
+ }
+ }
+ audio_play(sound, 1.f);
+
+ /* Reset item type. */
+ hp->t = ITEM_NONE;
}
/* Test for a switch. */
-
- if ((swch_e = sol_swch_test(fp, swch_e, 0)) != e && e)
+ if (sol_swch_test(fp, 0))
audio_play(AUD_SWITCH, 1.f);
/* Test for a jump. */
jump_b = 1;
jump_e = 0;
jump_dt = 0.f;
-
+
audio_play(AUD_JUMP, 1.f);
}
if (jump_e == 0 && jump_b == 0 && sol_jump_test(fp, jump_p, 0) == 0)
/* Test for a goal. */
- if (bt && goal_e && sol_goal_test(fp, p, 0))
+ if (bt && goal_c == 0 && (zp = sol_goal_test(fp, p, 0)))
{
- if (!goal_s)
- {
- goal_s = 1;
- audio_play(AUD_GOAL, 1.0f);
- }
+ audio_play(AUD_GOAL, 1.0f);
return GAME_GOAL;
}
/* Test for time-out. */
if (bt && clock_down && clock <= 0.f)
+ {
+ audio_play(AUD_TIME, 1.0f);
return GAME_TIME;
+ }
/* Test for fall-out. */
if (bt && fp->uv[0].p[1] < fp->vv[0].p[1])
+ {
+ audio_play(AUD_FALL, 1.0f);
return GAME_FALL;
+ }
return GAME_NONE;
}
* the measured frame time exceeds this maximum, we cut the time step in
* half, and do two updates. If THIS time step exceeds the maximum, we do
* four updates. And so on. In this way, the physics system is allowed to
- * seek an optimal update rate independant of, yet in integral sync with, the
+ * seek an optimal update rate independent of, yet in integral sync with, the
* graphics frame rate.
*/
game_rz = game_iz;
}
+ grow_step(fp, dt);
+
game_update_grav(h, g);
part_step(h, t);
/* Mix the sound of a ball bounce. */
if (b > 0.5)
- audio_play(AUD_BUMP, (b - 0.5f) * 2.0f);
+ {
+ float k = (b - 0.5f) * 2.0f;
+
+ if (got_orig)
+ {
+ if (fp->uv->r > grow_orig) audio_play(AUD_BUMPL, k);
+ else if (fp->uv->r < grow_orig) audio_play(AUD_BUMPS, k);
+ else audio_play(AUD_BUMPM, k);
+ }
+ else audio_play(AUD_BUMPM, k);
+ }
}
game_step_fade(dt);
/*---------------------------------------------------------------------------*/
+void game_no_aa(void)
+{
+ float max = game_ix * game_ix + game_iz * game_iz;
+ if (max > ANGLE_BOUND * ANGLE_BOUND)
+ {
+ max = ANGLE_BOUND / sqrt(max);
+ game_ix *= max;
+ game_iz *= max;
+ }
+}
+
void game_set_x(int k)
{
- game_ix = -20.f * k / JOY_MAX;
+ game_ix = -(ANGLE_BOUND) * k / JOY_MAX;
+#if NO_AA
+ game_no_aa();
+#endif
}
void game_set_z(int k)
{
- game_iz = +20.f * k / JOY_MAX;
+ game_iz = +ANGLE_BOUND * k / JOY_MAX;
+#if NO_AA
+ game_no_aa();
+#endif
}
void game_set_pos(int x, int y)
{
- float bound = 20.f;
-
game_ix += 40.f * y / config_get_d(CONFIG_MOUSE_SENSE);
game_iz += 40.f * x / config_get_d(CONFIG_MOUSE_SENSE);
- if (game_ix > +bound) game_ix = +bound;
- if (game_ix < -bound) game_ix = -bound;
- if (game_iz > +bound) game_iz = +bound;
- if (game_iz < -bound) game_iz = -bound;
+#if NO_AA
+ game_no_aa();
+#else
+ if (game_ix > +ANGLE_BOUND) game_ix = +ANGLE_BOUND;
+ if (game_ix < -ANGLE_BOUND) game_ix = -ANGLE_BOUND;
+ if (game_iz > +ANGLE_BOUND) game_iz = +ANGLE_BOUND;
+ if (game_iz < -ANGLE_BOUND) game_iz = -ANGLE_BOUND;
+#endif
}
void game_set_rot(float r)
float p1[3] = { 0.f, 0.f, 0.f };
float v[3];
+ z[0] = fsinf(V_RAD(view_a));
+ z[2] = fcosf(V_RAD(view_a));
+
v_cpy(view_e[0], x);
v_cpy(view_e[1], y);
v_cpy(view_e[2], z);