/**********************************************************************
This file is part of Crack dot Com's free source code release of
Golgotha.
for
information about compiling & licensing issues visit this URL
If that doesn't help, contact Jonathan Clark at golgotha_source@usa.net (Subject should have "GOLG" in it) ***********************************************************************/ #include#include "obj3d.hh" #include "loaders/dir_load.hh" #include "checksum/checksum.hh" #include "string/str_checksum.hh" #include "saver_id.hh" #include "time/profile.hh" #ifdef i4_NEW_CHECK #undef new #endif void g1_quad_object_class::scale(i4_float value) { for (int j=0; j extent) extent=animation[i].vertex[k].v.length(); if(animation[i].vertex[k].v.x < minx) minx=animation[i].vertex[k].v.x; if(animation[i].vertex[k].v.y < miny) miny=animation[i].vertex[k].v.y; if(animation[i].vertex[k].v.z < minz) minz=animation[i].vertex[k].v.z; if(animation[i].vertex[k].v.x > maxx) maxx=animation[i].vertex[k].v.x; if(animation[i].vertex[k].v.y > maxy) maxy=animation[i].vertex[k].v.y; if(animation[i].vertex[k].v.z > maxz) maxz=animation[i].vertex[k].v.z; } } } } void g1_quad_object_class::update(i4_float time) { for (int i=0; i quad_number]; int max_frames = t->max_frames; if (max_frames==0) { // panning i4_float fr, du,dv; fr = time*t->speed; fr -= i4_float(int(fr)); du = t->du*fr; dv = t->dv*fr; for (int n=0; n num_verts(); n++) { q->u[n] = t->u[n] + du; q->v[n] = t->v[n] + dv; } } else { // animation int frame = int(time*t->speed)%max_frames; int x = frame%t->frames_x; int y = frame/t->frames_x; for (int n=0; n num_verts(); n++) { q->u[n] = t->u[n] + t->du*x; q->v[n] = t->v[n] + t->dv*y; } } } } i4_bool g1_quad_object_class::intersect(const i4_3d_vector &point, const i4_3d_vector &ray, int anim, int frame, i4_float *intersect_t, int *hit_poly, i4_3d_vector *normal) { g1_vert_class *verts = get_verts(anim, frame); g1_quad_class *q = quad; i4_bool hit = i4_F; i4_float new_t = 1.0; for (int i=0; i normal.dot(ray)>=0) // wrong direction, next quad continue; // find intersection point in polygon's plane i4_float d = q->normal.dot(verts[q->vertex_ref[0]].v); i4_float num = d - q->normal.dot(point); i4_float den = q->normal.dot(ray); i4_float t = num/den; if (t<0) // behind the observer, next continue; if (t>=new_t) // check if new intersection is closer than previous ones continue; // project point into plane int j, u,v; i4_3d_vector new_ray(ray); new_ray *= t; i4_3d_vector new_point(point); new_point += new_ray; // determine orthogonal plane for 2D point in polygon test i4_3d_vector abs_normal; abs_normal.set(fabs(q->normal.x), fabs(q->normal.y), fabs(q->normal.z)); if (abs_normal.x>abs_normal.y && abs_normal.x>abs_normal.z) { // test in yz plane u = 1; v = 2; } else if (abs_normal.y>abs_normal.x && abs_normal.y>abs_normal.z) { // test in zx plane u = 2; v = 0; } else { // test in xy plane u = 0; v = 1; } // count first axis crossings of polygon to determine whether point in polygon i4_float dx1, dy1, dx2 = verts[q->vertex_ref[0]].v[u] - new_point[u], dy2 = verts[q->vertex_ref[0]].v[v] - new_point[v]; int x_sign1, y_sign1, x_sign2 = dx2>0, y_sign2 = dy2>0; int inside=0; for (j=q->num_verts()-1; j>=0; j--) { dx1 = verts[q->vertex_ref[j]].v[u] - new_point[u]; dy1 = verts[q->vertex_ref[j]].v[v] - new_point[v]; x_sign1 = dx1>0; y_sign1 = dy1>0; if (y_sign1 != y_sign2) { // crosses x-axis if (x_sign1 != x_sign2) { // check if crossing point is positive ((slope2>slope1) ^ (y2>y1)) if ((dx2*dy1 > dx1*dy2) ^ (dy2>dy1)) inside = !inside; } else if (x_sign1) // crosses +x-axis inside = !inside; y_sign2 = y_sign1; } x_sign2 = x_sign1; dx2 = dx1; dy2 = dy1; } if (inside) { // update current intersection new_t = t; if (hit_poly) *hit_poly=i; if (normal) *normal=q->normal; hit = i4_T; } } if (intersect_t) *intersect_t=new_t; return hit; } i4_bool g1_quad_object_class::get_mount_point(char *name, i4_3d_vector& vect) const { w32 id = i4_check_sum32(name, strlen(name)); for (int i=0; i goto_section(G1_SECTION_MODEL_TEXTURE_NAMES)) return 0; obj=allocate_object(); pf_load_tnames.start(); w16 quads=fp->read_16(); set_num_quads(quads); char name[256]; for (i=0; i read_16(); fp->read(name, len); name[len]=0; store_texture_name(i, name); } pf_load_tnames.stop(); if (!fp->goto_section(G1_SECTION_MODEL_QUADS)) return 0; pf_load_quads.start(); fp->read_16(); // repeat of num quads (why?) for (i=0; i read_16(); u[j]=fp->read_float(); v[j]=fp->read_float(); } scale=fp->read_float(); flags=fp->read_16(); normal.x=fp->read_float(); normal.y=fp->read_float(); normal.z=fp->read_float(); create_quad(i, 4, ref, flags); store_texture_params(i, scale, u, v); store_quad_normal(i, normal); } pf_load_quads.stop(); if (!fp->goto_section(G1_SECTION_MODEL_VERT_ANIMATION)) return 0; pf_load_verts.start(); w16 nv=fp->read_16(); // number of vertexes in object w16 na=fp->read_16(); // number of animations set_num_vertex(nv); set_num_animations(na); for (i=0; i read_16(); fp->read(name, len); name[len]=0; w16 frames = fp->read_16(); create_animation(i, name, frames); for (j=0; j read_float(); v.y=fp->read_float(); v.z=fp->read_float(); n.x=fp->read_float(); n.y=fp->read_float(); n.z=fp->read_float(); create_vertex(i,j,k,v); store_vertex_normal(i,j,k,n); } } } pf_load_verts.stop(); // optional mount points if (fp->goto_section("GMOD Mounts")) { pf_load_mounts.start(); w16 mounts = fp->read_16(); set_num_mount_points(mounts); for (i=0; i read_16(); fp->read(name, len); name[len]=0; v.x = fp->read_float(); v.y = fp->read_float(); v.z = fp->read_float(); create_mount_point(i,name,v); } pf_load_mounts.stop(); } // optional mount points if (fp->goto_section("GMOD Texture Animations")) { pf_load_tanim.start(); w16 anims = fp->read_16(); set_num_texture_animations(anims); for (i=0; i read_format("211fff",&q,&maxf,&frx,&sp,&du,&dv); if (maxf>0) create_texture_animation(i,q,maxf,frx,du,dv,sp); else create_texture_pan(i,q,du,dv,sp); } pf_load_tanim.stop(); } finish_object(); return obj; }