// Returns which octant point pnt is closet to. This will always return // a valid octant (0-7) since the point doesn't have to be in an octant. // If model_orient and/or model_pos are NULL, pnt is assumed to already // be rotated into the model's local coordinates. // If oct is not null, it will be filled in with a pointer to the octant // data. int model_which_octant_distant(vec3d* pnt, int model_num, matrix* model_orient, vec3d* model_pos, model_octant** oct) { polymodel* pm; vec3d tempv, rotpnt; pm = model_get(model_num); if (model_orient && model_pos) { // First, rotate pnt into the model's frame of reference. vm_vec_sub(&tempv, pnt, model_pos); vm_vec_rotate(&rotpnt, &tempv, model_orient); } else { rotpnt = *pnt; } vec3d center; vm_vec_avg(¢er, &pm->mins, &pm->maxs); int i, x, y, z; if (rotpnt.xyz.x > center.xyz.x) x = 1; else x = 0; if (rotpnt.xyz.y > center.xyz.y) y = 1; else y = 0; if (rotpnt.xyz.z > center.xyz.z) z = 1; else z = 0; i = ((x << 2) | (y << 1) | z); if (oct) *oct = &pm->octants[i]; return i; }
static void move_object_to_position(const vobjptridx_t objp, const vms_vector &newpos) { if (get_seg_masks(newpos, vcsegptr(objp->segnum), objp->size).facemask == 0) { objp->pos = newpos; } else { if (verify_object_seg(objp, newpos)) { int fate; object temp_viewer_obj; fvi_query fq; fvi_info hit_info; temp_viewer_obj = *Viewer; auto viewer_segnum = find_object_seg(vobjptr(Viewer)); temp_viewer_obj.segnum = viewer_segnum; // If the viewer is outside the mine, get him in the mine! if (viewer_segnum == segment_none) { editor_status("Unable to move object, viewer not in mine. Aborting"); return; #if 0 vms_vector last_outside_pos; // While outside mine, move towards object count = 0; while (viewer_segnum == segment_none) { vms_vector temp_vec; last_outside_pos = temp_viewer_obj.pos; vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, newpos); temp_viewer_obj.pos = temp_vec; viewer_segnum = find_object_seg(&temp_viewer_obj); temp_viewer_obj.segnum = viewer_segnum; if (count > 5) { editor_status("Unable to move object, can't get viewer in mine. Aborting"); return; } } count = 0; // While inside mine, move away from object. while (viewer_segnum != segment_none) { vms_vector temp_vec; vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, &last_outside_pos); temp_viewer_obj.pos = temp_vec; update_object_seg(&temp_viewer_obj); viewer_segnum = find_object_seg(&temp_viewer_obj); temp_viewer_obj.segnum = viewer_segnum; if (count > 5) { editor_status("Unable to move object, can't get viewer back out of mine. Aborting"); return; } } #endif } fq.p0 = &temp_viewer_obj.pos; fq.startseg = temp_viewer_obj.segnum; fq.p1 = &newpos; fq.rad = temp_viewer_obj.size; fq.thisobjnum = object_none; fq.ignore_obj_list.first = nullptr; fq.flags = 0; fate = find_vector_intersection(fq, hit_info); if (fate == HIT_WALL) { objp->pos = hit_info.hit_pnt; const auto &&segp = find_object_seg(objp); if (segp != segment_none) obj_relink(objp, segp); } else { editor_status("Attempted to move object out of mine. Object not moved."); } } } Update_flags |= UF_WORLD_CHANGED; }
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 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 move_object_to_position(int objnum, vms_vector *newpos) { object *objp = &Objects[objnum]; segmasks result = get_seg_masks(newpos, objp->segnum, objp->size); if (result.facemask == 0) { //mprintf((0, "Object #%i moved from (%7.3f %7.3f %7.3f) to (%7.3f %7.3f %7.3f)\n", objnum, f2fl(objp->pos.x), f2fl(objp->pos.y), f2fl(objp->pos.z), f2fl(newpos->x), f2fl(newpos->y), f2fl(newpos->z))); objp->pos = *newpos; } else { if (verify_object_seg(&Objects[objnum], newpos)) { int fate, count; int viewer_segnum; object temp_viewer_obj; fvi_query fq; fvi_info hit_info; vms_vector last_outside_pos; vms_vector last_inside_pos; temp_viewer_obj = *Viewer; viewer_segnum = find_object_seg(&temp_viewer_obj); temp_viewer_obj.segnum = viewer_segnum; // If the viewer is outside the mine, get him in the mine! if (viewer_segnum == -1) { // While outside mine, move towards object count = 0; while (viewer_segnum == -1) { vms_vector temp_vec; //mprintf((0, "[towards %7.3f %7.3f %7.3f]\n", f2fl(temp_viewer_obj.pos.x), f2fl(temp_viewer_obj.pos.y), f2fl(temp_viewer_obj.pos.z))); last_outside_pos = temp_viewer_obj.pos; vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, newpos); temp_viewer_obj.pos = temp_vec; viewer_segnum = find_object_seg(&temp_viewer_obj); temp_viewer_obj.segnum = viewer_segnum; if (count > 5) { editor_status("Unable to move object, can't get viewer in mine. Aborting"); return; } } count = 0; // While inside mine, move away from object. while (viewer_segnum != -1) { vms_vector temp_vec; //mprintf((0, "[away %7.3f %7.3f %7.3f]\n", f2fl(temp_viewer_obj.pos.x), f2fl(temp_viewer_obj.pos.y), f2fl(temp_viewer_obj.pos.z))); last_inside_pos = temp_viewer_obj.pos; vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, &last_outside_pos); temp_viewer_obj.pos = temp_vec; update_object_seg(&temp_viewer_obj); viewer_segnum = find_object_seg(&temp_viewer_obj); temp_viewer_obj.segnum = viewer_segnum; if (count > 5) { editor_status("Unable to move object, can't get viewer back out of mine. Aborting"); return; } } } fq.p0 = &temp_viewer_obj.pos; fq.startseg = temp_viewer_obj.segnum; fq.p1 = newpos; fq.rad = temp_viewer_obj.size; fq.thisobjnum = -1; fq.ignore_obj_list = NULL; fq.flags = 0; fate = find_vector_intersection(&fq,&hit_info); if (fate == HIT_WALL) { int new_segnum; //mprintf((0, "Hit wall seg:side = %i:%i, point = (%7.3f %7.3f %7.3f)\n", hit_info.hit_seg, hit_info.hit_side, f2fl(hit_info.hit_pnt.x), f2fl(hit_info.hit_pnt.y), f2fl(hit_info.hit_pnt.z))); objp->pos = hit_info.hit_pnt; new_segnum = find_object_seg(objp); Assert(new_segnum != -1); obj_relink(objp-Objects, new_segnum); //mprintf((0, "Object moved from segment %i to %i\n", old_segnum, objp->segnum)); } else { editor_status("Attempted to move object out of mine. Object not moved."); //mprintf((0,"Attempted to move object out of mine. Object not moved.")); } } } Update_flags |= UF_WORLD_CHANGED; }
void briefing_editor_dlg::OnMakeIcon() { char *name; int z, len, team, ship, waypoint, count = -1; int cargo = 0, cargo_count = 0, freighter_count = 0; object *ptr; vec3d min, max, pos; brief_icon *iconp; if (Briefing->stages[m_cur_stage].num_icons >= MAX_STAGE_ICONS) return; m_cur_icon = Briefing->stages[m_cur_stage].num_icons++; iconp = &Briefing->stages[m_cur_stage].icons[m_cur_icon]; ship = waypoint = -1; team = 0; jump_node *jnp = NULL; vm_vec_make(&min, 9e19f, 9e19f, 9e19f); vm_vec_make(&max, -9e19f, -9e19f, -9e19f); ptr = GET_FIRST(&obj_used_list); while (ptr != END_OF_LIST(&obj_used_list)) { if (ptr->flags & OF_MARKED) { if (ptr->pos.xyz.x < min.xyz.x) min.xyz.x = ptr->pos.xyz.x; if (ptr->pos.xyz.x > max.xyz.x) max.xyz.x = ptr->pos.xyz.x; if (ptr->pos.xyz.y < min.xyz.y) min.xyz.y = ptr->pos.xyz.y; if (ptr->pos.xyz.y > max.xyz.y) max.xyz.y = ptr->pos.xyz.y; if (ptr->pos.xyz.z < min.xyz.z) min.xyz.z = ptr->pos.xyz.z; if (ptr->pos.xyz.z > max.xyz.z) max.xyz.z = ptr->pos.xyz.z; switch (ptr->type) { case OBJ_SHIP: case OBJ_START: ship = ptr->instance; break; case OBJ_WAYPOINT: waypoint = ptr->instance; break; case OBJ_JUMP_NODE: jnp = ptr->jnp; break; default: Int3(); } if (ship >= 0) { team = Ships[ship].team; z = ship_query_general_type(ship); if (Ship_info[Ships[ship].ship_info_index].flags & SIF_CARGO) cargo_count++; if (Ship_info[Ships[ship].ship_info_index].flags & SIF_FREIGHTER) { // direct docked with any marked cargo? for (dock_instance *dock_ptr = ptr->dock_list; dock_ptr != NULL; dock_ptr = dock_ptr->next) { if (dock_ptr->docked_objp->flags & OF_MARKED) { if (Ship_info[Ships[dock_ptr->docked_objp->instance].ship_info_index].flags & SIF_CARGO) freighter_count++; } } } } count++; } ptr = GET_NEXT(ptr); } if (cargo_count && cargo_count == freighter_count) cargo = 1; vm_vec_avg(&pos, &min, &max); if (ship >= 0) name = Ships[ship].ship_name; else if (waypoint >= 0) name = Waypoint_lists[waypoint / 65536].name; else if (jnp != NULL) name = jnp->get_name_ptr(); else return; len = strlen(name); if (len >= MAX_LABEL_LEN - 1) len = MAX_LABEL_LEN - 1; strncpy(iconp->label, name, len); iconp->label[len] = 0; // iconp->text[0] = 0; iconp->type = 0; iconp->team = team; iconp->pos = pos; iconp->flags = 0; iconp->id = Cur_brief_id++; if (ship >= 0) { iconp->ship_class = Ships[ship].ship_info_index; switch (Ship_info[Ships[ship].ship_info_index].flags & SIF_ALL_SHIP_TYPES) { case SIF_KNOSSOS_DEVICE: iconp->type = ICON_KNOSSOS_DEVICE; break; case SIF_CORVETTE: iconp->type = ICON_CORVETTE; break; case SIF_GAS_MINER: iconp->type = ICON_GAS_MINER; break; case SIF_SUPERCAP: iconp->type = ICON_SUPERCAP; break; case SIF_SENTRYGUN: iconp->type = ICON_SENTRYGUN; break; case SIF_AWACS: iconp->type = ICON_AWACS; break; case SIF_CARGO: if (cargo) iconp->type = (count == 1) ? ICON_FREIGHTER_WITH_CARGO : ICON_FREIGHTER_WING_WITH_CARGO; else iconp->type = count ? ICON_CARGO_WING : ICON_CARGO; break; case SIF_SUPPORT: iconp->type = ICON_SUPPORT_SHIP; break; case SIF_FIGHTER: iconp->type = count ? ICON_FIGHTER_WING : ICON_FIGHTER; break; case SIF_BOMBER: iconp->type = count ? ICON_BOMBER_WING : ICON_BOMBER; break; case SIF_FREIGHTER: if (cargo) iconp->type = (count == 1) ? ICON_FREIGHTER_WITH_CARGO : ICON_FREIGHTER_WING_WITH_CARGO; else iconp->type = count ? ICON_FREIGHTER_WING_NO_CARGO : ICON_FREIGHTER_NO_CARGO; break; case SIF_CRUISER: iconp->type = count ? ICON_CRUISER_WING : ICON_CRUISER; break; case SIF_TRANSPORT: iconp->type = count ? ICON_TRANSPORT_WING : ICON_TRANSPORT; break; case SIF_CAPITAL: case SIF_DRYDOCK: iconp->type = ICON_CAPITAL; break; case SIF_NAVBUOY: iconp->type = ICON_WAYPOINT; break; default: iconp->type = ICON_ASTEROID_FIELD; break; } } // jumpnodes else if(jnp != NULL){ // find the first navbuoy iconp->ship_class = -1; for (int i = 0; i < Num_ship_classes; i++) { if (Ship_info[i].flags & SIF_NAVBUOY) { iconp->ship_class = i; break; } } iconp->type = ICON_JUMP_NODE; } // everything else else { // find the first navbuoy iconp->ship_class = -1; for (int i = 0; i < Num_ship_classes; i++) { if (Ship_info[i].flags & SIF_NAVBUOY) { iconp->ship_class = i; break; } } iconp->type = ICON_WAYPOINT; } if (!m_change_local){ propagate_icon(m_cur_icon); } icon_obj[m_cur_icon] = obj_create(OBJ_POINT, -1, m_cur_icon, NULL, &pos, 0.0f, OF_RENDERS); Assert(icon_obj[m_cur_icon] >= 0); obj_merge_created_list(); unmark_all(); set_cur_object_index(icon_obj[m_cur_icon]); GetDlgItem(IDC_MAKE_ICON) -> EnableWindow(FALSE); GetDlgItem(IDC_PROPAGATE_ICONS) -> EnableWindow(TRUE); update_data(1); }
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 draw_polygon_model(vms_vector *pos,vms_matrix *orient,vms_angvec *anim_angles,int model_num,int flags,g3s_lrgb light,fix *glow_values,bitmap_index alt_textures[]) { polymodel *po; int i; if (model_num < 0) return; Assert(model_num < N_polygon_models); po=&Polygon_models[model_num]; //check if should use simple model if (po->simpler_model ) //must have a simpler model if (flags==0) //can't switch if this is debris //!!if (!alt_textures) { //alternate textures might not match //alt textures might not match, but in the one case we're using this //for on 11/14/94, they do match. So we leave it in. { int cnt=1; fix depth; depth = g3_calc_point_depth(pos); //gets 3d depth while (po->simpler_model && depth > cnt++ * Simple_model_threshhold_scale * po->rad) po = &Polygon_models[po->simpler_model-1]; } if (alt_textures) for (i=0;i<po->n_textures;i++) { texture_list_index[i] = alt_textures[i]; texture_list[i] = &GameBitmaps[alt_textures[i].index]; } else for (i=0;i<po->n_textures;i++) { texture_list_index[i] = ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]]; texture_list[i] = &GameBitmaps[ObjBitmaps[ObjBitmapPtrs[po->first_texture+i]].index]; } // Make sure the textures for this object are paged in... piggy_page_flushed = 0; for (i=0;i<po->n_textures;i++) PIGGY_PAGE_IN( texture_list_index[i] ); // Hmmm... cache got flushed in the middle of paging all these in, // so we need to reread them all in. if (piggy_page_flushed) { piggy_page_flushed = 0; for (i=0;i<po->n_textures;i++) PIGGY_PAGE_IN( texture_list_index[i] ); } // Make sure that they can all fit in memory. Assert( piggy_page_flushed == 0 ); g3_start_instance_matrix(pos,orient); g3_set_interp_points(robot_points); if (flags == 0) //draw entire object g3_draw_polygon_model(po->model_data,texture_list,anim_angles,light,glow_values); else { int i; for (i=0;flags;flags>>=1,i++) if (flags & 1) { vms_vector ofs; Assert(i < po->n_models); //if submodel, rotate around its center point, not pivot point vm_vec_avg(&ofs,&po->submodel_mins[i],&po->submodel_maxs[i]); vm_vec_negate(&ofs); g3_start_instance_matrix(&ofs,NULL); g3_draw_polygon_model(&po->model_data[po->submodel_ptrs[i]],texture_list,anim_angles,light,glow_values); g3_done_instance(); } } g3_done_instance(); }
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_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 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; } }
// function to actually deal with weapon-ship hit stuff. separated from check_collision routine below // because of multiplayer reasons. void ship_weapon_do_hit_stuff(object *ship_obj, object *weapon_obj, vec3d *world_hitpos, vec3d *hitpos, int quadrant_num, int submodel_num, vec3d /*not a pointer intentionaly*/ hit_dir) { weapon *wp = &Weapons[weapon_obj->instance]; weapon_info *wip = &Weapon_info[wp->weapon_info_index]; ship *shipp = &Ships[ship_obj->instance]; float damage; vec3d force; // Apply hit & damage & stuff to weapon weapon_hit(weapon_obj, ship_obj, world_hitpos); damage = wip->damage; // deterine whack whack float blast = wip->mass; vm_vec_copy_scale(&force, &weapon_obj->phys_info.vel, blast ); // send player pain packet if ( (MULTIPLAYER_MASTER) && !(shipp->flags & SF_DYING) ){ int np_index = multi_find_player_by_object(ship_obj); // if this is a player ship if((np_index >= 0) && (np_index != MY_NET_PLAYER_NUM) && (wip->subtype == WP_LASER)){ send_player_pain_packet(&Net_players[np_index], wp->weapon_info_index, wip->damage * weapon_get_damage_scale(wip, weapon_obj, ship_obj), &force, hitpos); } } ship_apply_local_damage(ship_obj, weapon_obj, world_hitpos, damage, quadrant_num, CREATE_SPARKS, submodel_num); // let the hud shield gauge know when Player or Player target is hit hud_shield_quadrant_hit(ship_obj, quadrant_num); // Let wingman status gauge know a wingman ship was hit if ( (Ships[ship_obj->instance].wing_status_wing_index >= 0) && ((Ships[ship_obj->instance].wing_status_wing_pos >= 0)) ) { hud_wingman_status_start_flash(shipp->wing_status_wing_index, shipp->wing_status_wing_pos); } // Apply a wack. This used to be inside of ship_hit... duh! Ship_hit // is to apply damage, not physics, so I moved it here. // don't apply whack for multiplayer_client from laser - will occur with pain packet if (!((wip->subtype == WP_LASER) && MULTIPLAYER_CLIENT) ) { // apply a whack ship_apply_whack( &force, hitpos, ship_obj ); } if( (quadrant_num == -1) && Cmdline_decals ){ weapon_info *wip = &Weapon_info[Weapons[weapon_obj->instance].weapon_info_index]; decal_point dec; dec.orient = weapon_obj->orient; vec3d hit_fvec; vm_vec_negate(&hit_dir); vm_vec_avg(&hit_fvec, &hit_dir, &weapon_obj->orient.vec.fvec); vm_vec_normalize(&hit_fvec); dec.orient.vec.fvec = hit_fvec; vm_fix_matrix(&dec.orient); dec.pnt.xyz = hitpos->xyz; dec.radius = wip->decal_rad; if ( (dec.radius > 0) && (wip->decal_texture.bitmap_id > -1) ) decal_create(ship_obj, &dec, submodel_num, wip->decal_texture.bitmap_id, wip->decal_backface_texture.bitmap_id, wip->decal_glow_texture_id, wip->decal_burn_texture_id, wip->decal_burn_time); } }