void batching_add_point_bitmap(primitive_batch *batch, vertex *position, float rad, float angle, float depth) { Assert(batch->get_render_info().prim_type == PRIM_TYPE_POINTS); float radius = rad; radius *= 1.41421356f;//1/0.707, becase these are the points of a square or width and height rad vec3d PNT(position->world); vec3d fvec; // get the direction from the point to the eye vm_vec_sub(&fvec, &View_position, &PNT); vm_vec_normalize_safe(&fvec); // move the center of the sprite based on the depth parameter if ( depth != 0.0f ) vm_vec_scale_add(&PNT, &PNT, &fvec, depth); batch_vertex new_particle; vec3d up; vm_rot_point_around_line(&up, &vmd_y_vector, angle, &vmd_zero_vector, &vmd_z_vector); new_particle.position = position->world; new_particle.radius = radius; new_particle.uvec = up; batch->add_point_sprite(&new_particle); }
void batching_add_point_bitmap(primitive_batch *batch, vertex *position, int orient, float rad, float depth) { Assert(batch->get_render_info().prim_type == PRIM_TYPE_POINTS); float radius = rad; radius *= 1.41421356f;//1/0.707, becase these are the points of a square or width and height rad vec3d PNT(position->world); vec3d fvec; // get the direction from the point to the eye vm_vec_sub(&fvec, &View_position, &PNT); vm_vec_normalize_safe(&fvec); // move the center of the sprite based on the depth parameter if ( depth != 0.0f ) vm_vec_scale_add(&PNT, &PNT, &fvec, depth); batch_vertex new_particle; vec3d up = {{{ 0.0f, 1.0f, 0.0f }}}; new_particle.position = position->world; new_particle.radius = radius; int direction = orient % 4; switch ( direction ) { case 0: up.xyz.x = 0.0f; up.xyz.y = 1.0f; up.xyz.z = 0.0f; break; case 1: up.xyz.x = 0.0f; up.xyz.y = -1.0f; up.xyz.z = 0.0f; break; case 2: up.xyz.x = -1.0f; up.xyz.y = 0.0f; up.xyz.z = 0.0f; break; case 3: up.xyz.x = 1.0f; up.xyz.y = 0.0f; up.xyz.z = 0.0f; break; } new_particle.uvec = up; batch->add_point_sprite(&new_particle); }
// Creates a bunch of particles. You pass a structure // rather than a bunch of parameters. void particle_emit( particle_emitter *pe, int type, int optional_data, float range ) { int i, n; if ( !Particles_enabled ) return; int n1, n2; // Account for detail int percent = get_percent(Detail.num_particles); //Particle rendering drops out too soon. Seems to be around 150 m. Is it detail level controllable? I'd like it to be 500-1000 float min_dist = 125.0f; float dist = vm_vec_dist_quick( &pe->pos, &Eye_position ) / range; if ( dist > min_dist ) { percent = fl2i( i2fl(percent)*min_dist / dist ); if ( percent < 1 ) { return; } } //mprintf(( "Dist = %.1f, percent = %d%%\n", dist, percent )); n1 = (pe->num_low*percent)/100; n2 = (pe->num_high*percent)/100; // How many to emit? n = (rand() % (n2-n1+1)) + n1; if ( n < 1 ) return; for (i=0; i<n; i++ ) { // Create a particle vec3d tmp_vel; vec3d normal; // What normal the particle emit arond float radius = (( pe->max_rad - pe->min_rad ) * frand()) + pe->min_rad; float speed = (( pe->max_vel - pe->min_vel ) * frand()) + pe->min_vel; float life = (( pe->max_life - pe->min_life ) * frand()) + pe->min_life; normal.xyz.x = pe->normal.xyz.x + (frand()*2.0f - 1.0f)*pe->normal_variance; normal.xyz.y = pe->normal.xyz.y + (frand()*2.0f - 1.0f)*pe->normal_variance; normal.xyz.z = pe->normal.xyz.z + (frand()*2.0f - 1.0f)*pe->normal_variance; vm_vec_normalize_safe( &normal ); vm_vec_scale_add( &tmp_vel, &pe->vel, &normal, speed ); particle_create( &pe->pos, &tmp_vel, life, radius, type, optional_data ); } }
void geometry_shader_batcher::draw_bitmap(vertex *position, int orient, float rad, float depth) { rad *= 1.41421356f;//1/0.707, becase these are the points of a square or width and height rad vec3d PNT(position->world); vec3d fvec; // get the direction from the point to the eye vm_vec_sub(&fvec, &View_position, &PNT); vm_vec_normalize_safe(&fvec); // move the center of the sprite based on the depth parameter if ( depth != 0.0f ) vm_vec_scale_add(&PNT, &PNT, &fvec, depth); particle_pnt new_particle; vec3d up = {{{0.0f, 1.0f, 0.0f}}}; new_particle.position = position->world; new_particle.size = rad; int direction = orient % 4; if ( direction == 1 ) { up.xyz.x = 0.0f; up.xyz.y = -1.0f; up.xyz.z = 0.0f; } else if ( direction == 2 ) { up.xyz.x = -1.0f; up.xyz.y = 0.0f; up.xyz.z = 0.0f; } else if ( direction == 3 ) { up.xyz.x = 1.0f; up.xyz.y = 0.0f; up.xyz.z = 0.0f; } new_particle.up = up; vertices.push_back(new_particle); }
float g3_draw_laser_htl(vec3d* p0, float width1, vec3d* p1, float width2, int r, int g, int b, uint tmap_flags) { width1 *= 0.5f; width2 *= 0.5f; vec3d uvec, fvec, rvec, center, reye; vm_vec_sub(&fvec, p0, p1); vm_vec_normalize_safe(&fvec); vm_vec_avg(¢er, p0, p1); //needed for the return value only vm_vec_sub(&reye, &Eye_position, ¢er); vm_vec_normalize(&reye); vm_vec_crossprod(&uvec, &fvec, &reye); vm_vec_normalize(&uvec); vm_vec_crossprod(&fvec, &uvec, &reye); vm_vec_normalize(&fvec); // if(vm_vec_mag_squared(&uvec)==0) uvec.xyz.y = 1.0f; //in case fvec is exactly equal to matrx.rvec, stick some arbitrary value in uvec //normalize new perpendicular vector // vm_vec_normalize(&uvec); //now recompute right vector, in case it wasn't entirely perpendiclar vm_vec_crossprod(&rvec, &uvec, &fvec); // Now have uvec, which is up vector and rvec which is the normal // of the face. int i; vec3d start, end; vm_vec_scale_add(&start, p0, &fvec, -width1); vm_vec_scale_add(&end, p1, &fvec, width2); vec3d vecs[4]; vertex pts[4]; vertex* ptlist[8] = { &pts[3], &pts[2], &pts[1], &pts[0], &pts[0], &pts[1], &pts[2], &pts[3] }; vm_vec_scale_add(&vecs[0], &start, &uvec, width1); vm_vec_scale_add(&vecs[1], &end, &uvec, width2); vm_vec_scale_add(&vecs[2], &end, &uvec, -width2); vm_vec_scale_add(&vecs[3], &start, &uvec, -width1); for (i = 0; i < 4; i++) { g3_transfer_vertex(&pts[i], &vecs[i]); } ptlist[0]->u = 0.0f; ptlist[0]->v = 0.0f; ptlist[1]->u = 1.0f; ptlist[1]->v = 0.0f; ptlist[2]->u = 1.0f; ptlist[2]->v = 1.0f; ptlist[3]->u = 0.0f; ptlist[3]->v = 1.0f; ptlist[0]->r = (ubyte)r; ptlist[0]->g = (ubyte)g; ptlist[0]->b = (ubyte)b; ptlist[0]->a = 255; ptlist[1]->r = (ubyte)r; ptlist[1]->g = (ubyte)g; ptlist[1]->b = (ubyte)b; ptlist[1]->a = 255; ptlist[2]->r = (ubyte)r; ptlist[2]->g = (ubyte)g; ptlist[2]->b = (ubyte)b; ptlist[2]->a = 255; ptlist[3]->r = (ubyte)r; ptlist[3]->g = (ubyte)g; ptlist[3]->b = (ubyte)b; ptlist[3]->a = 255; gr_tmapper(4, ptlist, tmap_flags | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_FLAG_CORRECT); return center.xyz.z; }
void physics_apply_shock(vec3d *direction_vec, float pressure, physics_info *pi, matrix *orient, vec3d *min, vec3d *max, float radius) { vec3d normal; vec3d local_torque, temp_torque, torque; vec3d impact_vec; vec3d area; vec3d sin; if (radius > MAX_RADIUS) { return; } vm_vec_normalize_safe ( direction_vec ); area.xyz.x = (max->xyz.y - min->xyz.z) * (max->xyz.z - min->xyz.z); area.xyz.y = (max->xyz.x - min->xyz.x) * (max->xyz.z - min->xyz.z); area.xyz.z = (max->xyz.x - min->xyz.x) * (max->xyz.y - min->xyz.y); normal.xyz.x = vm_vec_dotprod( direction_vec, &orient->vec.rvec ); normal.xyz.y = vm_vec_dotprod( direction_vec, &orient->vec.uvec ); normal.xyz.z = vm_vec_dotprod( direction_vec, &orient->vec.fvec ); sin.xyz.x = fl_sqrt( fl_abs(1.0f - normal.xyz.x*normal.xyz.x) ); sin.xyz.y = fl_sqrt( fl_abs(1.0f - normal.xyz.y*normal.xyz.y) ); sin.xyz.z = fl_sqrt( fl_abs(1.0f - normal.xyz.z*normal.xyz.z) ); vm_vec_make( &torque, 0.0f, 0.0f, 0.0f ); // find the torque exerted due to the shockwave hitting each face // model the effect of the shockwave as if the shockwave were a plane of projectiles, // all moving in the direction direction_vec. then find the torque as the cross prod // of the force (pressure * area * normal * sin * scale * mass) // normal takes account the fraction of the surface exposed to the shockwave // the sin term is not technically needed but "feels" better // scale factors out the increase in area with larger objects // more massive objects get less rotation // find torque due to forces on the right/left face if ( normal.xyz.x < 0.0f ) // normal < 0, hits the right face vm_vec_copy_scale( &impact_vec, &orient->vec.rvec, max->xyz.x * pressure * area.xyz.x * normal.xyz.x * sin.xyz.x / pi->mass ); else // normal > 0, hits the left face vm_vec_copy_scale( &impact_vec, &orient->vec.rvec, min->xyz.x * pressure * area.xyz.x * -normal.xyz.x * sin.xyz.x / pi->mass ); vm_vec_crossprod( &temp_torque, &impact_vec, direction_vec ); vm_vec_add2( &torque, &temp_torque ); // find torque due to forces on the up/down face if ( normal.xyz.y < 0.0f ) vm_vec_copy_scale( &impact_vec, &orient->vec.uvec, max->xyz.y * pressure * area.xyz.y * normal.xyz.y * sin.xyz.y / pi->mass ); else vm_vec_copy_scale( &impact_vec, &orient->vec.uvec, min->xyz.y * pressure * area.xyz.y * -normal.xyz.y * sin.xyz.y / pi->mass ); vm_vec_crossprod( &temp_torque, &impact_vec, direction_vec ); vm_vec_add2( &torque, &temp_torque ); // find torque due to forces on the forward/backward face if ( normal.xyz.z < 0.0f ) vm_vec_copy_scale( &impact_vec, &orient->vec.fvec, max->xyz.z * pressure * area.xyz.z * normal.xyz.z * sin.xyz.z / pi->mass ); else vm_vec_copy_scale( &impact_vec, &orient->vec.fvec, min->xyz.z * pressure * area.xyz.z * -normal.xyz.z * sin.xyz.z / pi->mass ); vm_vec_crossprod( &temp_torque, &impact_vec, direction_vec ); vm_vec_add2( &torque, &temp_torque ); // compute delta rotvel, scale according to blast and radius float scale; if (radius < MIN_RADIUS) { scale = 1.0f; } else { scale = (MAX_RADIUS - radius)/(MAX_RADIUS-MIN_RADIUS); } // set shockwave shake amplitude, duration, flag pi->shockwave_shake_amp = (float)(MAX_SHAKE*(pressure/STD_PRESSURE)*scale); pi->shockwave_decay = timestamp( SW_BLAST_DURATION ); pi->flags |= PF_IN_SHOCKWAVE; // safety dance if (!(IS_VEC_NULL_SQ_SAFE(&torque))) { vec3d delta_rotvel; vm_vec_rotate( &local_torque, &torque, orient ); vm_vec_copy_normalize(&delta_rotvel, &local_torque); vm_vec_scale(&delta_rotvel, (float)(MAX_ROTVEL*(pressure/STD_PRESSURE)*scale)); // nprintf(("Physics", "rotvel scale %f\n", (MAX_ROTVEL*(pressure/STD_PRESSURE)*scale))); vm_vec_add2(&pi->rotvel, &delta_rotvel); } // set reduced translational damping, set flags float velocity_scale = (float)MAX_VEL*scale; pi->flags |= PF_REDUCED_DAMP; update_reduced_damp_timestamp( pi, velocity_scale*pi->mass ); vm_vec_scale_add2( &pi->vel, direction_vec, velocity_scale ); vm_vec_rotate(&pi->prev_ramp_vel, &pi->vel, orient); // set so velocity will ramp starting from current speed // check that kick from shockwave is not too large if (!(pi->flags & PF_USE_VEL) && (vm_vec_mag_squared(&pi->vel) > MAX_SHIP_SPEED*MAX_SHIP_SPEED)) { // Get DaveA nprintf(("Physics", "speed reset in physics_apply_shock [speed: %f]\n", vm_vec_mag(&pi->vel))); vm_vec_normalize(&pi->vel); vm_vec_scale(&pi->vel, (float)RESET_SHIP_SPEED); } }
void batching_add_beam_internal(primitive_batch *batch, vec3d *start, vec3d *end, float width, color *clr, float offset) { Assert(batch->get_render_info().prim_type == PRIM_TYPE_TRIS); vec3d p[4]; batch_vertex verts[6]; vec3d fvec, uvecs, uvece, evec; vm_vec_sub(&fvec, start, end); vm_vec_normalize_safe(&fvec); vm_vec_sub(&evec, &View_position, start); vm_vec_normalize_safe(&evec); vm_vec_cross(&uvecs, &fvec, &evec); vm_vec_normalize_safe(&uvecs); vm_vec_sub(&evec, &View_position, end); vm_vec_normalize_safe(&evec); vm_vec_cross(&uvece, &fvec, &evec); vm_vec_normalize_safe(&uvece); vm_vec_scale_add(&p[0], start, &uvecs, width); vm_vec_scale_add(&p[1], end, &uvece, width); vm_vec_scale_add(&p[2], end, &uvece, -width); vm_vec_scale_add(&p[3], start, &uvecs, -width); //move all the data from the vecs into the verts //tri 1 verts[0].position = p[3]; verts[1].position = p[2]; verts[2].position = p[1]; //tri 2 verts[3].position = p[3]; verts[4].position = p[1]; verts[5].position = p[0]; //set up the UV coords //tri 1 verts[0].tex_coord.u = 0.0f; verts[0].tex_coord.v = 0.0f; verts[1].tex_coord.u = 1.0f; verts[1].tex_coord.v = 0.0f; verts[2].tex_coord.u = 1.0f; verts[2].tex_coord.v = 1.0f; //tri 2 verts[3].tex_coord.u = 0.0f; verts[3].tex_coord.v = 0.0f; verts[4].tex_coord.u = 1.0f; verts[4].tex_coord.v = 1.0f; verts[5].tex_coord.u = 0.0f; verts[5].tex_coord.v = 1.0f; for(int i = 0; i < 6; i++) { verts[i].r = clr->red; verts[i].g = clr->green; verts[i].b = clr->blue; verts[i].a = clr->alpha; if(offset > 0.0f) { verts[i].radius = offset; } else { verts[i].radius = width; } } batch->add_triangle(&verts[0], &verts[1], &verts[2]); batch->add_triangle(&verts[3], &verts[4], &verts[5]); }
void batching_add_laser_internal(primitive_batch *batch, vec3d *p0, float width1, vec3d *p1, float width2, int r, int g, int b) { Assert(batch->get_render_info().prim_type == PRIM_TYPE_TRIS); width1 *= 0.5f; width2 *= 0.5f; vec3d uvec, fvec, rvec, center, reye; vm_vec_sub( &fvec, p0, p1 ); vm_vec_normalize_safe( &fvec ); vm_vec_avg( ¢er, p0, p1 ); // needed for the return value only vm_vec_sub(&reye, &Eye_position, ¢er); vm_vec_normalize(&reye); // compute the up vector vm_vec_cross(&uvec, &fvec, &reye); vm_vec_normalize_safe(&uvec); // ... the forward vector vm_vec_cross(&fvec, &uvec, &reye); vm_vec_normalize_safe(&fvec); // now recompute right vector, in case it wasn't entirely perpendiclar vm_vec_cross(&rvec, &uvec, &fvec); // Now have uvec, which is up vector and rvec which is the normal // of the face. vec3d start, end; vm_vec_scale_add(&start, p0, &fvec, -width1); vm_vec_scale_add(&end, p1, &fvec, width2); vec3d vecs[4]; batch_vertex verts[6]; vm_vec_scale_add( &vecs[0], &end, &uvec, width2 ); vm_vec_scale_add( &vecs[1], &start, &uvec, width1 ); vm_vec_scale_add( &vecs[2], &start, &uvec, -width1 ); vm_vec_scale_add( &vecs[3], &end, &uvec, -width2 ); verts[0].position = vecs[0]; verts[1].position = vecs[1]; verts[2].position = vecs[2]; verts[3].position = vecs[0]; verts[4].position = vecs[2]; verts[5].position = vecs[3]; verts[0].tex_coord.u = 1.0f; verts[0].tex_coord.v = 0.0f; verts[1].tex_coord.u = 0.0f; verts[1].tex_coord.v = 0.0f; verts[2].tex_coord.u = 0.0f; verts[2].tex_coord.v = 1.0f; verts[3].tex_coord.u = 1.0f; verts[3].tex_coord.v = 0.0f; verts[4].tex_coord.u = 0.0f; verts[4].tex_coord.v = 1.0f; verts[5].tex_coord.u = 1.0f; verts[5].tex_coord.v = 1.0f; verts[0].r = (ubyte)r; verts[0].g = (ubyte)g; verts[0].b = (ubyte)b; verts[0].a = 255; verts[1].r = (ubyte)r; verts[1].g = (ubyte)g; verts[1].b = (ubyte)b; verts[1].a = 255; verts[2].r = (ubyte)r; verts[2].g = (ubyte)g; verts[2].b = (ubyte)b; verts[2].a = 255; verts[3].r = (ubyte)r; verts[3].g = (ubyte)g; verts[3].b = (ubyte)b; verts[3].a = 255; verts[4].r = (ubyte)r; verts[4].g = (ubyte)g; verts[4].b = (ubyte)b; verts[4].a = 255; verts[5].r = (ubyte)r; verts[5].g = (ubyte)g; verts[5].b = (ubyte)b; verts[5].a = 255; batch->add_triangle(&verts[0], &verts[1], &verts[2]); batch->add_triangle(&verts[3], &verts[4], &verts[5]); }
void batching_add_bitmap_rotated_internal(primitive_batch *batch, vertex *pnt, float angle, float rad, color *clr, float depth) { Assert(batch->get_render_info().prim_type == PRIM_TYPE_TRIS); float radius = rad; rad *= 1.41421356f;//1/0.707, becase these are the points of a square or width and height rad extern float Physics_viewer_bank; angle -= Physics_viewer_bank; if ( angle < 0.0f ) angle += PI2; else if ( angle > PI2 ) angle -= PI2; vec3d PNT(pnt->world); vec3d p[4]; vec3d fvec, rvec, uvec; batch_vertex verts[6]; vm_vec_sub(&fvec, &View_position, &PNT); vm_vec_normalize_safe(&fvec); vm_rot_point_around_line(&uvec, &View_matrix.vec.uvec, angle, &vmd_zero_vector, &View_matrix.vec.fvec); vm_vec_cross(&rvec, &View_matrix.vec.fvec, &uvec); vm_vec_normalize_safe(&rvec); vm_vec_cross(&uvec, &View_matrix.vec.fvec, &rvec); vm_vec_scale_add(&PNT, &PNT, &fvec, depth); vm_vec_scale_add(&p[0], &PNT, &rvec, rad); vm_vec_scale_add(&p[2], &PNT, &rvec, -rad); vm_vec_scale_add(&p[1], &p[2], &uvec, rad); vm_vec_scale_add(&p[3], &p[0], &uvec, -rad); vm_vec_scale_add(&p[0], &p[0], &uvec, rad); vm_vec_scale_add(&p[2], &p[2], &uvec, -rad); //move all the data from the vecs into the verts //tri 1 verts[5].position = p[3]; verts[4].position = p[2]; verts[3].position = p[1]; //tri 2 verts[2].position = p[3]; verts[1].position = p[1]; verts[0].position = p[0]; //tri 1 verts[5].tex_coord.u = 0.0f; verts[5].tex_coord.v = 0.0f; verts[4].tex_coord.u = 1.0f; verts[4].tex_coord.v = 0.0f; verts[3].tex_coord.u = 1.0f; verts[3].tex_coord.v = 1.0f; //tri 2 verts[2].tex_coord.u = 0.0f; verts[2].tex_coord.v = 0.0f; verts[1].tex_coord.u = 1.0f; verts[1].tex_coord.v = 1.0f; verts[0].tex_coord.u = 0.0f; verts[0].tex_coord.v = 1.0f; for (int i = 0; i < 6 ; i++) { verts[i].r = clr->red; verts[i].g = clr->green; verts[i].b = clr->blue; verts[i].a = clr->alpha; verts[i].radius = radius; } batch->add_triangle(&verts[0], &verts[1], &verts[2]); batch->add_triangle(&verts[3], &verts[4], &verts[5]); }
void trail_render( trail * trailp ) { int sections[NUM_TRAIL_SECTIONS]; int num_sections = 0; int i; vec3d topv, botv, *fvec, last_pos, tmp_fvec; vertex top, bot; int nv = 0; float w; ubyte l; vec3d centerv; if (trailp->tail == trailp->head) return; // if this trail is on the player ship, and he's in any padlock view except rear view, don't draw if ( (Player_ship != NULL) && trail_is_on_ship(trailp, Player_ship) && (Viewer_mode & (VM_PADLOCK_UP | VM_PADLOCK_LEFT | VM_PADLOCK_RIGHT)) ) { return; } trail_info *ti = &trailp->info; int n = trailp->tail; do { n--; if (n < 0) n = NUM_TRAIL_SECTIONS-1; if (trailp->val[n] > 1.0f) break; sections[num_sections++] = n; } while ( n != trailp->head ); if (num_sections <= 0) return; Assertion(ti->texture.bitmap_id != -1, "Weapon trail %s could not be loaded", ti->texture.filename); // We can leave this as an assert, but tell them how to fix it. --Chief memset( &top, 0, sizeof(vertex) ); memset( &bot, 0, sizeof(vertex) ); // it's a tristrip, so allocate for 2+1 allocate_trail_verts((num_sections * 2) + 1); float w_size = (ti->w_end - ti->w_start); float a_size = (ti->a_end - ti->a_start); int num_faded_sections = ti->n_fade_out_sections; for (i = 0; i < num_sections; i++) { n = sections[i]; float init_fade_out = 1.0f; if ((num_faded_sections > 0) && (i < num_faded_sections)) { init_fade_out = ((float) i) / (float) num_faded_sections; } w = trailp->val[n] * w_size + ti->w_start; if (init_fade_out != 1.0f) { l = (ubyte)fl2i((trailp->val[n] * a_size + ti->a_start) * 255.0f * init_fade_out * init_fade_out); } else { l = (ubyte)fl2i((trailp->val[n] * a_size + ti->a_start) * 255.0f); } if ( i == 0 ) { if ( num_sections > 1 ) { vm_vec_sub(&tmp_fvec, &trailp->pos[n], &trailp->pos[sections[i+1]] ); vm_vec_normalize_safe(&tmp_fvec); fvec = &tmp_fvec; } else { fvec = &tmp_fvec; fvec->xyz.x = 0.0f; fvec->xyz.y = 0.0f; fvec->xyz.z = 1.0f; } } else { vm_vec_sub(&tmp_fvec, &last_pos, &trailp->pos[n] ); vm_vec_normalize_safe(&tmp_fvec); fvec = &tmp_fvec; } trail_calc_facing_pts( &topv, &botv, fvec, &trailp->pos[n], w ); if ( !Cmdline_nohtl ) { g3_transfer_vertex( &top, &topv ); g3_transfer_vertex( &bot, &botv ); } else { g3_rotate_vertex( &top, &topv ); g3_rotate_vertex( &bot, &botv ); } top.a = bot.a = l; if (i > 0) { float U = i2fl(i); if (i == num_sections-1) { // Last one... vm_vec_avg( ¢erv, &topv, &botv ); if ( !Cmdline_nohtl ) g3_transfer_vertex( &Trail_v_list[nv+2], ¢erv ); else g3_rotate_vertex( &Trail_v_list[nv+2], ¢erv ); Trail_v_list[nv].a = l; Trail_v_list[nv].texture_position.u = U; Trail_v_list[nv].texture_position.v = 1.0f; Trail_v_list[nv].r = Trail_v_list[nv].g = Trail_v_list[nv].b = l; nv++; Trail_v_list[nv].texture_position.u = U; Trail_v_list[nv].texture_position.v = 0.0f; Trail_v_list[nv].r = Trail_v_list[nv].g = Trail_v_list[nv].b = l; nv++; Trail_v_list[nv].texture_position.u = U + 1.0f; Trail_v_list[nv].texture_position.v = 0.5f; Trail_v_list[nv].r = Trail_v_list[nv].g = Trail_v_list[nv].b = 0; nv++; } else { Trail_v_list[nv].texture_position.u = U; Trail_v_list[nv].texture_position.v = 1.0f; Trail_v_list[nv].r = Trail_v_list[nv].g = Trail_v_list[nv].b = l; nv++; Trail_v_list[nv].texture_position.u = U; Trail_v_list[nv].texture_position.v = 0.0f; Trail_v_list[nv].r = Trail_v_list[nv].g = Trail_v_list[nv].b = l; nv++; } } last_pos = trailp->pos[n]; Trail_v_list[nv] = top; Trail_v_list[nv+1] = bot; } if ( !nv ) return; if (nv < 3) Error( LOCATION, "too few verts in trail render\n" ); // there should always be three verts in the last section and 2 everyware else, therefore there should always be an odd number of verts if ( (nv % 2) != 1 ) Warning( LOCATION, "even number of verts in trail render\n" ); profile_begin("Trail Draw"); gr_set_bitmap( ti->texture.bitmap_id, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f ); gr_render(nv, Trail_v_list, TMAP_FLAG_TEXTURED | TMAP_FLAG_ALPHA | TMAP_FLAG_GOURAUD | TMAP_FLAG_RGB | TMAP_HTL_3D_UNLIT | TMAP_FLAG_TRISTRIP); profile_end("Trail Draw"); }
void batching_add_bitmap_internal(primitive_batch *batch, vertex *pnt, int orient, float rad, color *clr, float depth) { Assert(batch->get_render_info().prim_type == PRIM_TYPE_TRIS); float radius = rad; rad *= 1.41421356f;//1/0.707, becase these are the points of a square or width and height rad vec3d PNT(pnt->world); vec3d p[4]; vec3d fvec, rvec, uvec; batch_vertex verts[6]; // get the direction from the point to the eye vm_vec_sub(&fvec, &View_position, &PNT); vm_vec_normalize_safe(&fvec); // get an up vector in the general direction of what we want uvec = View_matrix.vec.uvec; // make a right vector from the f and up vector, this r vec is exactly what we want, so... vm_vec_cross(&rvec, &View_matrix.vec.fvec, &uvec); vm_vec_normalize_safe(&rvec); // fix the u vec with it vm_vec_cross(&uvec, &View_matrix.vec.fvec, &rvec); // move the center of the sprite based on the depth parameter if ( depth != 0.0f ) vm_vec_scale_add(&PNT, &PNT, &fvec, depth); // move one of the verts to the left vm_vec_scale_add(&p[0], &PNT, &rvec, rad); // and one to the right vm_vec_scale_add(&p[2], &PNT, &rvec, -rad); // now move all oof the verts to were they need to be vm_vec_scale_add(&p[1], &p[2], &uvec, rad); vm_vec_scale_add(&p[3], &p[0], &uvec, -rad); vm_vec_scale_add(&p[0], &p[0], &uvec, rad); vm_vec_scale_add(&p[2], &p[2], &uvec, -rad); //move all the data from the vecs into the verts //tri 1 verts[5].position = p[3]; verts[4].position = p[2]; verts[3].position = p[1]; //tri 2 verts[2].position = p[3]; verts[1].position = p[1]; verts[0].position = p[0]; // set up the UV coords if ( orient & 1 ) { // tri 1 verts[5].tex_coord.u = 1.0f; verts[4].tex_coord.u = 0.0f; verts[3].tex_coord.u = 0.0f; // tri 2 verts[2].tex_coord.u = 1.0f; verts[1].tex_coord.u = 0.0f; verts[0].tex_coord.u = 1.0f; } else { // tri 1 verts[5].tex_coord.u = 0.0f; verts[4].tex_coord.u = 1.0f; verts[3].tex_coord.u = 1.0f; // tri 2 verts[2].tex_coord.u = 0.0f; verts[1].tex_coord.u = 1.0f; verts[0].tex_coord.u = 0.0f; } if ( orient & 2 ) { // tri 1 verts[5].tex_coord.v = 1.0f; verts[4].tex_coord.v = 1.0f; verts[3].tex_coord.v = 0.0f; // tri 2 verts[2].tex_coord.v = 1.0f; verts[1].tex_coord.v = 0.0f; verts[0].tex_coord.v = 0.0f; } else { // tri 1 verts[5].tex_coord.v = 0.0f; verts[4].tex_coord.v = 0.0f; verts[3].tex_coord.v = 1.0f; // tri 2 verts[2].tex_coord.v = 0.0f; verts[1].tex_coord.v = 1.0f; verts[0].tex_coord.v = 1.0f; } for (int i = 0; i < 6 ; i++) { verts[i].r = clr->red; verts[i].g = clr->green; verts[i].b = clr->blue; verts[i].a = clr->alpha; verts[i].radius = radius; } batch->add_triangle(&verts[5], &verts[4], &verts[3]); batch->add_triangle(&verts[2], &verts[1], &verts[0]); }
float g3_draw_laser_htl(vec3d *p0,float width1,vec3d *p1,float width2, int r, int g, int b, uint tmap_flags) { width1 *= 0.5f; width2 *= 0.5f; vec3d uvec, fvec, rvec, center, reye, rfvec; vm_vec_sub( &fvec, p0, p1 ); vm_vec_normalize_safe( &fvec ); vm_vec_copy_scale(&rfvec, &fvec, -1.0f); vm_vec_avg( ¢er, p0, p1 ); //needed for the return value only vm_vec_sub(&reye, &Eye_position, ¢er); vm_vec_normalize(&reye); // code intended to prevent possible null vector normalize issue - start if (vm_test_parallel(&reye,&fvec)){ fvec.xyz.x = -reye.xyz.z; fvec.xyz.y = 0.0f; fvec.xyz.z = -reye.xyz.x; } if (vm_test_parallel(&reye,&rfvec)){ fvec.xyz.x = reye.xyz.z; fvec.xyz.y = 0.0f; fvec.xyz.z = reye.xyz.x; } // code intended to prevent possible null vector normalize issue - end vm_vec_crossprod(&uvec,&fvec,&reye); vm_vec_normalize(&uvec); vm_vec_crossprod(&fvec,&uvec,&reye); vm_vec_normalize(&fvec); //now recompute right vector, in case it wasn't entirely perpendiclar vm_vec_crossprod(&rvec,&uvec,&fvec); // Now have uvec, which is up vector and rvec which is the normal // of the face. int i; vec3d start, end; vm_vec_scale_add(&start, p0, &fvec, -width1); vm_vec_scale_add(&end, p1, &fvec, width2); vec3d vecs[4]; vertex pts[4]; vertex *ptlist[8] = { &pts[3], &pts[2], &pts[1], &pts[0], &pts[0], &pts[1], &pts[2], &pts[3]}; vm_vec_scale_add( &vecs[0], &start, &uvec, width1 ); vm_vec_scale_add( &vecs[1], &end, &uvec, width2 ); vm_vec_scale_add( &vecs[2], &end, &uvec, -width2 ); vm_vec_scale_add( &vecs[3], &start, &uvec, -width1 ); for (i=0; i<4; i++ ) { g3_transfer_vertex( &pts[i], &vecs[i] ); } ptlist[0]->texture_position.u = 0.0f; ptlist[0]->texture_position.v = 0.0f; ptlist[1]->texture_position.u = 1.0f; ptlist[1]->texture_position.v = 0.0f; ptlist[2]->texture_position.u = 1.0f; ptlist[2]->texture_position.v = 1.0f; ptlist[3]->texture_position.u = 0.0f; ptlist[3]->texture_position.v = 1.0f; ptlist[0]->r = (ubyte)r; ptlist[0]->g = (ubyte)g; ptlist[0]->b = (ubyte)b; ptlist[0]->a = 255; ptlist[1]->r = (ubyte)r; ptlist[1]->g = (ubyte)g; ptlist[1]->b = (ubyte)b; ptlist[1]->a = 255; ptlist[2]->r = (ubyte)r; ptlist[2]->g = (ubyte)g; ptlist[2]->b = (ubyte)b; ptlist[2]->a = 255; ptlist[3]->r = (ubyte)r; ptlist[3]->g = (ubyte)g; ptlist[3]->b = (ubyte)b; ptlist[3]->a = 255; gr_tmapper(4, ptlist,tmap_flags | TMAP_FLAG_RGB | TMAP_FLAG_GOURAUD | TMAP_FLAG_CORRECT); return center.xyz.z; }
void trail_add_batch(trail * trailp) { int sections[NUM_TRAIL_SECTIONS]; int num_sections = 0; int i; vec3d topv, botv, *fvec, last_pos, tmp_fvec; vertex top, bot, top_prev, bot_prev; float w; ubyte l; vec3d centerv; if (trailp->tail == trailp->head) return; // if this trail is on the player ship, and he's in any padlock view except rear view, don't draw if ((Player_ship != NULL) && trail_is_on_ship(trailp, Player_ship) && (Viewer_mode & (VM_PADLOCK_UP | VM_PADLOCK_LEFT | VM_PADLOCK_RIGHT))) { return; } trail_info *ti = &trailp->info; int n = trailp->tail; do { n--; if (n < 0) n = NUM_TRAIL_SECTIONS - 1; if (trailp->val[n] > 1.0f) break; sections[num_sections++] = n; } while (n != trailp->head); if (num_sections <= 0) return; Assertion(ti->texture.bitmap_id != -1, "Weapon trail %s could not be loaded", ti->texture.filename); // We can leave this as an assert, but tell them how to fix it. --Chief memset(&top, 0, sizeof(vertex)); memset(&bot, 0, sizeof(vertex)); memset(&top_prev, 0, sizeof(vertex)); memset(&bot_prev, 0, sizeof(vertex)); float w_size = (ti->w_end - ti->w_start); float a_size = (ti->a_end - ti->a_start); int num_faded_sections = ti->n_fade_out_sections; for (i = 0; i < num_sections; i++) { n = sections[i]; float init_fade_out = 1.0f; if ((num_faded_sections > 0) && (i < num_faded_sections)) { init_fade_out = ((float)i) / (float)num_faded_sections; } w = trailp->val[n] * w_size + ti->w_start; if (init_fade_out != 1.0f) { l = (ubyte)fl2i((trailp->val[n] * a_size + ti->a_start) * 255.0f * init_fade_out * init_fade_out); } else { l = (ubyte)fl2i((trailp->val[n] * a_size + ti->a_start) * 255.0f); } if (i == 0) { if (num_sections > 1) { vm_vec_sub(&tmp_fvec, &trailp->pos[n], &trailp->pos[sections[i + 1]]); vm_vec_normalize_safe(&tmp_fvec); fvec = &tmp_fvec; } else { fvec = &tmp_fvec; fvec->xyz.x = 0.0f; fvec->xyz.y = 0.0f; fvec->xyz.z = 1.0f; } } else { vm_vec_sub(&tmp_fvec, &last_pos, &trailp->pos[n]); vm_vec_normalize_safe(&tmp_fvec); fvec = &tmp_fvec; } trail_calc_facing_pts(&topv, &botv, fvec, &trailp->pos[n], w); if (!Cmdline_nohtl) { g3_transfer_vertex(&top, &topv); g3_transfer_vertex(&bot, &botv); } else { g3_rotate_vertex(&top, &topv); g3_rotate_vertex(&bot, &botv); } top.r = top.g = top.b = l; bot.r = bot.g = bot.b = l; top.a = bot.a = l; float U = i2fl(i); top.texture_position.u = U; top.texture_position.v = 1.0f; bot.texture_position.u = U; bot.texture_position.v = 0.0f; if (i > 0) { if (i == num_sections - 1) { // Last one... vm_vec_avg(¢erv, &topv, &botv); vertex center_vert = vertex(); if (!Cmdline_nohtl) g3_transfer_vertex(¢er_vert, ¢erv); else g3_rotate_vertex(¢er_vert, ¢erv); center_vert.texture_position.u = U + 1.0f; center_vert.texture_position.v = 0.5f; center_vert.a = center_vert.r = center_vert.g = center_vert.b = l; vertex tri[3]; tri[1] = top_prev; tri[2] = bot_prev; tri[0] = center_vert; batch_add_tri( ti->texture.bitmap_id, TMAP_FLAG_TEXTURED | TMAP_FLAG_ALPHA | TMAP_FLAG_GOURAUD | TMAP_FLAG_RGB | TMAP_HTL_3D_UNLIT, tri, 1.0f ); } else { vertex quad[4]; quad[0] = top_prev; quad[1] = bot_prev; quad[2] = bot; quad[3] = top; batch_add_quad( ti->texture.bitmap_id, TMAP_FLAG_TEXTURED | TMAP_FLAG_ALPHA | TMAP_FLAG_GOURAUD | TMAP_FLAG_RGB | TMAP_HTL_3D_UNLIT, quad, 1.0f ); } } last_pos = trailp->pos[n]; top_prev = top; bot_prev = bot; } }
float geometry_batcher::draw_laser(vec3d *p0, float width1, vec3d *p1, float width2, int r, int g, int b) { width1 *= 0.5f; width2 *= 0.5f; vec3d uvec, fvec, rvec, center, reye; vm_vec_sub( &fvec, p0, p1 ); vm_vec_normalize_safe( &fvec ); vm_vec_avg( ¢er, p0, p1 ); // needed for the return value only vm_vec_sub(&reye, &Eye_position, ¢er); vm_vec_normalize(&reye); // compute the up vector vm_vec_cross(&uvec, &fvec, &reye); vm_vec_normalize_safe(&uvec); // ... the forward vector vm_vec_cross(&fvec, &uvec, &reye); vm_vec_normalize_safe(&fvec); // now recompute right vector, in case it wasn't entirely perpendiclar vm_vec_cross(&rvec, &uvec, &fvec); // Now have uvec, which is up vector and rvec which is the normal // of the face. vec3d start, end; vm_vec_scale_add(&start, p0, &fvec, -width1); vm_vec_scale_add(&end, p1, &fvec, width2); vec3d vecs[4]; vertex *pts = &vert[n_to_render * 3]; vm_vec_scale_add( &vecs[0], &end, &uvec, width2 ); vm_vec_scale_add( &vecs[1], &start, &uvec, width1 ); vm_vec_scale_add( &vecs[2], &start, &uvec, -width1 ); vm_vec_scale_add( &vecs[3], &end, &uvec, -width2 ); g3_transfer_vertex( &pts[0], &vecs[0] ); g3_transfer_vertex( &pts[1], &vecs[1] ); g3_transfer_vertex( &pts[2], &vecs[2] ); g3_transfer_vertex( &pts[3], &vecs[0] ); g3_transfer_vertex( &pts[4], &vecs[2] ); g3_transfer_vertex( &pts[5], &vecs[3] ); pts[0].texture_position.u = 1.0f; pts[0].texture_position.v = 0.0f; pts[1].texture_position.u = 0.0f; pts[1].texture_position.v = 0.0f; pts[2].texture_position.u = 0.0f; pts[2].texture_position.v = 1.0f; pts[3].texture_position.u = 1.0f; pts[3].texture_position.v = 0.0f; pts[4].texture_position.u = 0.0f; pts[4].texture_position.v = 1.0f; pts[5].texture_position.u = 1.0f; pts[5].texture_position.v = 1.0f; pts[0].r = (ubyte)r; pts[0].g = (ubyte)g; pts[0].b = (ubyte)b; pts[0].a = 255; pts[1].r = (ubyte)r; pts[1].g = (ubyte)g; pts[1].b = (ubyte)b; pts[1].a = 255; pts[2].r = (ubyte)r; pts[2].g = (ubyte)g; pts[2].b = (ubyte)b; pts[2].a = 255; pts[3].r = (ubyte)r; pts[3].g = (ubyte)g; pts[3].b = (ubyte)b; pts[3].a = 255; pts[4].r = (ubyte)r; pts[4].g = (ubyte)g; pts[4].b = (ubyte)b; pts[4].a = 255; pts[5].r = (ubyte)r; pts[5].g = (ubyte)g; pts[5].b = (ubyte)b; pts[5].a = 255; n_to_render += 2; use_radius = false; return center.xyz.z; }
void geometry_batcher::draw_beam(vec3d *start, vec3d *end, float width, float intensity, float offset) { vec3d p[4]; vertex *P = &vert[n_to_render * 3]; float *R = &radius_list[n_to_render * 3]; vec3d fvec, uvecs, uvece, evec; vm_vec_sub(&fvec, start, end); vm_vec_normalize_safe(&fvec); vm_vec_sub(&evec, &View_position, start); vm_vec_normalize_safe(&evec); vm_vec_cross(&uvecs, &fvec, &evec); vm_vec_normalize_safe(&uvecs); vm_vec_sub(&evec, &View_position, end); vm_vec_normalize_safe(&evec); vm_vec_cross(&uvece, &fvec, &evec); vm_vec_normalize_safe(&uvece); vm_vec_scale_add(&p[0], start, &uvecs, width); vm_vec_scale_add(&p[1], end, &uvece, width); vm_vec_scale_add(&p[2], end, &uvece, -width); vm_vec_scale_add(&p[3], start, &uvecs, -width); //move all the data from the vecs into the verts //tri 1 g3_transfer_vertex(&P[0], &p[3]); g3_transfer_vertex(&P[1], &p[2]); g3_transfer_vertex(&P[2], &p[1]); //tri 2 g3_transfer_vertex(&P[3], &p[3]); g3_transfer_vertex(&P[4], &p[1]); g3_transfer_vertex(&P[5], &p[0]); //set up the UV coords //tri 1 P[0].texture_position.u = 0.0f; P[0].texture_position.v = 0.0f; P[1].texture_position.u = 1.0f; P[1].texture_position.v = 0.0f; P[2].texture_position.u = 1.0f; P[2].texture_position.v = 1.0f; //tri 2 P[3].texture_position.u = 0.0f; P[3].texture_position.v = 0.0f; P[4].texture_position.u = 1.0f; P[4].texture_position.v = 1.0f; P[5].texture_position.u = 0.0f; P[5].texture_position.v = 1.0f; ubyte _color = (ubyte)(255.0f * intensity); for(int i = 0; i < 6; i++){ P[i].r = P[i].g = P[i].b = P[i].a = _color; if(offset > 0.0f) { R[i] = offset; } else { R[i] = width; } } n_to_render += 2; use_radius = true; }
void geometry_batcher::draw_bitmap(vertex *pnt, float rad, float angle, float depth) { float radius = rad; rad *= 1.41421356f;//1/0.707, becase these are the points of a square or width and height rad extern float Physics_viewer_bank; angle -= Physics_viewer_bank; if ( angle < 0.0f ) angle += PI2; else if ( angle > PI2 ) angle -= PI2; vec3d PNT(pnt->world); vec3d p[4]; vec3d fvec, rvec, uvec; vertex *P = &vert[n_to_render * 3]; float *R = &radius_list[n_to_render * 3]; vm_vec_sub(&fvec, &View_position, &PNT); vm_vec_normalize_safe(&fvec); vm_rot_point_around_line(&uvec, &View_matrix.vec.uvec, angle, &vmd_zero_vector, &View_matrix.vec.fvec); vm_vec_cross(&rvec, &View_matrix.vec.fvec, &uvec); vm_vec_normalize_safe(&rvec); vm_vec_cross(&uvec, &View_matrix.vec.fvec, &rvec); vm_vec_scale_add(&PNT, &PNT, &fvec, depth); vm_vec_scale_add(&p[0], &PNT, &rvec, rad); vm_vec_scale_add(&p[2], &PNT, &rvec, -rad); vm_vec_scale_add(&p[1], &p[2], &uvec, rad); vm_vec_scale_add(&p[3], &p[0], &uvec, -rad); vm_vec_scale_add(&p[0], &p[0], &uvec, rad); vm_vec_scale_add(&p[2], &p[2], &uvec, -rad); //move all the data from the vecs into the verts //tri 1 g3_transfer_vertex(&P[5], &p[3]); g3_transfer_vertex(&P[4], &p[2]); g3_transfer_vertex(&P[3], &p[1]); //tri 2 g3_transfer_vertex(&P[2], &p[3]); g3_transfer_vertex(&P[1], &p[1]); g3_transfer_vertex(&P[0], &p[0]); //tri 1 P[5].texture_position.u = 0.0f; P[5].texture_position.v = 0.0f; P[4].texture_position.u = 1.0f; P[4].texture_position.v = 0.0f; P[3].texture_position.u = 1.0f; P[3].texture_position.v = 1.0f; //tri 2 P[2].texture_position.u = 0.0f; P[2].texture_position.v = 0.0f; P[1].texture_position.u = 1.0f; P[1].texture_position.v = 1.0f; P[0].texture_position.u = 0.0f; P[0].texture_position.v = 1.0f; for (int i = 0; i < 6 ; i++) { P[i].r = pnt->r; P[i].g = pnt->g; P[i].b = pnt->b; P[i].a = pnt->a; R[i] = radius; } n_to_render += 2; }
/* 0----1 |\ | | \ | 3----2 */ void geometry_batcher::draw_bitmap(vertex *pnt, int orient, float rad, float depth) { float radius = rad; rad *= 1.41421356f;//1/0.707, becase these are the points of a square or width and height rad vec3d PNT(pnt->world); vec3d p[4]; vec3d fvec, rvec, uvec; vertex *P = &vert[n_to_render * 3]; float *R = &radius_list[n_to_render * 3]; // get the direction from the point to the eye vm_vec_sub(&fvec, &View_position, &PNT); vm_vec_normalize_safe(&fvec); // get an up vector in the general direction of what we want uvec = View_matrix.vec.uvec; // make a right vector from the f and up vector, this r vec is exactly what we want, so... vm_vec_cross(&rvec, &View_matrix.vec.fvec, &uvec); vm_vec_normalize_safe(&rvec); // fix the u vec with it vm_vec_cross(&uvec, &View_matrix.vec.fvec, &rvec); // move the center of the sprite based on the depth parameter if ( depth != 0.0f ) vm_vec_scale_add(&PNT, &PNT, &fvec, depth); // move one of the verts to the left vm_vec_scale_add(&p[0], &PNT, &rvec, rad); // and one to the right vm_vec_scale_add(&p[2], &PNT, &rvec, -rad); // now move all oof the verts to were they need to be vm_vec_scale_add(&p[1], &p[2], &uvec, rad); vm_vec_scale_add(&p[3], &p[0], &uvec, -rad); vm_vec_scale_add(&p[0], &p[0], &uvec, rad); vm_vec_scale_add(&p[2], &p[2], &uvec, -rad); //move all the data from the vecs into the verts //tri 1 g3_transfer_vertex(&P[5], &p[3]); g3_transfer_vertex(&P[4], &p[2]); g3_transfer_vertex(&P[3], &p[1]); //tri 2 g3_transfer_vertex(&P[2], &p[3]); g3_transfer_vertex(&P[1], &p[1]); g3_transfer_vertex(&P[0], &p[0]); // set up the UV coords if ( orient & 1 ) { // tri 1 P[5].texture_position.u = 1.0f; P[4].texture_position.u = 0.0f; P[3].texture_position.u = 0.0f; // tri 2 P[2].texture_position.u = 1.0f; P[1].texture_position.u = 0.0f; P[0].texture_position.u = 1.0f; } else { // tri 1 P[5].texture_position.u = 0.0f; P[4].texture_position.u = 1.0f; P[3].texture_position.u = 1.0f; // tri 2 P[2].texture_position.u = 0.0f; P[1].texture_position.u = 1.0f; P[0].texture_position.u = 0.0f; } if ( orient & 2 ) { // tri 1 P[5].texture_position.v = 1.0f; P[4].texture_position.v = 1.0f; P[3].texture_position.v = 0.0f; // tri 2 P[2].texture_position.v = 1.0f; P[1].texture_position.v = 0.0f; P[0].texture_position.v = 0.0f; } else { // tri 1 P[5].texture_position.v = 0.0f; P[4].texture_position.v = 0.0f; P[3].texture_position.v = 1.0f; // tri 2 P[2].texture_position.v = 0.0f; P[1].texture_position.v = 1.0f; P[0].texture_position.v = 1.0f; } for (int i = 0; i < 6 ; i++) { P[i].r = pnt->r; P[i].g = pnt->g; P[i].b = pnt->b; P[i].a = pnt->a; R[i] = radius; } n_to_render += 2; }