home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright (C) Matthew 'pagan' Baranowski & Sander 'FireStorm' van Rossen
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
- #include "system.h"
- #include "ndictionary.h"
- #include "md3gl.h"
- #include "md3view.h"
-
- int m_x, m_y;
-
- /*! commands to handle mouse dragging, uses key_flags defines above */
- void start_drag( mkey_enum keyFlags, int x, int y )
- {
- m_x = x;
- m_y = y;
- }
-
- void drag( mkey_enum keyFlags, int x, int y )
- {
- if ( keyFlags != 0 )
- {
- if ( keyFlags == KEY_LBUTTON )
- {
- if ((x != m_x) || (y != m_y))
- {
- mdview.rotAngleY += (float)(x - m_x) * MOUSE_ROT_SCALE;
- mdview.rotAngleX += (float)(y - m_y) * MOUSE_ROT_SCALE;
- if (mdview.rotAngleY> 360.0f) mdview.rotAngleY=mdview.rotAngleY-360.0f;
- if (mdview.rotAngleY<-360.0f) mdview.rotAngleY=mdview.rotAngleY+360.0f;
- if (mdview.rotAngleX> 360.0f) mdview.rotAngleX=mdview.rotAngleX-360.0f;
- if (mdview.rotAngleX<-360.0f) mdview.rotAngleX=mdview.rotAngleX+360.0f;
- repaint_main();
- set_cursor( m_x, m_y );
- }
- } else
- if ( keyFlags == KEY_RBUTTON )
- {
- if ( y != m_y )
- {
- mdview.zPos += ((float)(y - m_y)/10.f) * MOUSE_ZPOS_SCALE;
- if (mdview.zPos<-1000.f) mdview.zPos=-1000.f;
- if (mdview.zPos> 1000.f) mdview.zPos= 1000.f;
- InvalidateRect( mdview.hwnd, NULL, FALSE );
- set_cursor( m_x , m_y );
- }
- }
- }
- }
-
- void end_drag( mkey_enum keyFlags, int x, int y )
- {
- }
-
-
- /*
- =======
- rotates an object by placing a trackball sphere around it
- =======
- */
- /*
- int ModelControl::TrackballRotate(SNodePrimitive *shape, int sx, int sy, int ex, int ey)
- {
- if (!m_shape) return 0;
-
- // simple quick method to avoid NAN results
- if ((abs(sx - ex) < 2) && (abs(sy - ey) < 2)) {
- return 0;
- }
-
- IAVector scale( TRACKBALL_SCALE, TRACKBALL_SCALE, TRACKBALL_SCALE);
- IAMatrix tbMatrix = scale_mat(scale) * shape->m_inv_CTM;
- IAPoint isecPnt2, isecPnt1, center, origin;
- IAVector vec1, vec2, crossVec;
- Idouble dotA, angle;
-
- if (!m_tracer->ISectRayWithSphere( tbMatrix, &isecPnt1, sx, sy,
- m_scene->width(), m_scene->height() )) {
- return 0;
- }
-
- if (!m_tracer->ISectRayWithSphere( tbMatrix, &isecPnt2, ex, ey,
- m_scene->width(), m_scene->height() )) {
- return 0;
- }
-
- center = shape->m_CTM * center;
- vec1 = isecPnt1 - center;
- vec2 = isecPnt2 - center;
- vec1.normalize();
- vec2.normalize();
-
- crossVec = cross( vec1, vec2 );
- dotA = dot( vec1, vec2 );
- angle = -atan2( 1, dotA );
-
- shape->m_CTM_rotate = rot_mat(origin, crossVec, angle) * shape->m_CTM_rotate;
- shape->updateCTM();
-
- return 1;
- }
-
- SNodePrimitive *ISectTracer::ShootRay( int x, int y, int width, int height,
- Intersection *isec, Ray *ray )
- {
- NodePosition pos;
- Ray filmRay, worldRay, objectRay;
- IAMatrix filmToWorld = m_scene->camera()->filmToWorld();
- Intersection iStack[MAX_INTERSECT_PER_RAY], *iStackP, *iStackP2, *bestISec;
- int numIntersect, isectTotal;
- NodeSequenceInfo *gData = m_scene->m_geometryList;
- Idouble tbest;
- SNodePrimitive *primData;
- Shape *rayShape;
-
-
- filmRay.d[X] = ((double)(2*x)/(double)width) - 1;
- filmRay.d[Y] = 1-((double)(2*y)/(double)height);
-
- filmRay.d[Z] = -1; filmRay.d[W] = 1;
- filmRay.P = IAPoint();
-
- worldRay.d = filmToWorld * filmRay.d;
- worldRay.P = filmToWorld * filmRay.P;
- normalize( worldRay.d );
-
- iStackP = iStack;
- isectTotal = 0;
- bestISec = NULL;
-
- // calculate intersections for all shapes
- for (pos = gData->first(); pos != NULL; pos = gData->after(pos) ) {
- primData = (SNodePrimitive *)pos->element(); // get entry from geometry list
- rayShape = primData->m_shape;
-
- objectRay.d = primData->m_inv_CTM * worldRay.d; // transform ray to object space
- objectRay.P = primData->m_inv_CTM * worldRay.P;
-
- if (!rayShape->IntersectTest( &objectRay )) {
- if (filmRay.d[X] != 0) continue;
- }
-
- numIntersect = rayShape->Intersect( &objectRay, iStackP, primData ); // calculate intersection
-
- iStackP += numIntersect;
- isectTotal += numIntersect;
- }
-
-
- // find best t for the pixel
- if (iStackP > iStack) {
- tbest = MAX_FLOAT;
- for (int i = 0; i < isectTotal; i++) {
- if (iStack[i].m_t < tbest) {
- tbest = iStack[i].m_t;
- bestISec = &iStack[i];
- }
- }
- }
-
- if (bestISec) {
- // copy the relevant data
- if (ray) {
- ray->P = worldRay.P;
- ray->d = worldRay.d;
- }
- if (isec) bestISec->copy( isec );
- return bestISec->m_shape;
- }
- else {
- return NULL;
- }
- }
-
- int ISectTracer::ISectRayWithSphere( IAMatrix &object, IAPoint *isec,
- int x, int y, int width, int height)
- {
- Ray filmRay, worldRay, objectRay;
- IAMatrix filmToWorld = m_scene->camera()->filmToWorld();
-
- filmRay.d[X] = ((double)(2*x)/(double)width) - 1;
- filmRay.d[Y] = 1-((double)(2*y)/(double)height);
- filmRay.d[Z] = -1; filmRay.d[W] = 1;
- filmRay.P = IAPoint();
-
- worldRay.d = filmToWorld * filmRay.d;
- worldRay.P = filmToWorld * filmRay.P;
- normalize( worldRay.d );
-
- objectRay.d = object * worldRay.d;
- objectRay.P = object * worldRay.P;
-
- IAVector d = objectRay.d;
- IAPoint P = objectRay.P;
-
- double a = d[Z]*d[Z] + d[X]*d[X] + d[Y]*d[Y];
- double b = 2*(P[X]*d[X] + P[Z]*d[Z] + P[Y]*d[Y]);
- double c = P[X]*P[X] + P[Y]*P[Y] + P[Z]*P[Z] - 0.25;
- double t, det = b*b-4*a*c;
-
- if (det > 0) {
- t = (-b+det)/a;
- *isec = worldRay.P + worldRay.d * t;
- return 1;
- }
- else return 0;
- }
-
- int CubeShape::Intersect( Ray *ray, Intersection *iStack, SNodePrimitive *data )
- {
- double t, det, u, v;
- IAVector d = ray->d;
- IAPoint P = ray->P;
- Intersection *iStackP = iStack;
-
- // test intersection with z up face
- if (d[Z] != 0) {
- t = -((P[Z]+0.5) / d[Z]);
- u = P[X] + d[X]*t;
- v = P[Y] + d[Y]*t;
-
- if ((u > -0.5) && (u < 0.5) && (v > -0.5) && (v < 0.5)) {
- iStackP->m_t = t;
- iStackP->m_shape = data;
- iStackP->m_faceID = FACE_ZPOS;
- iStackP++;
- }
- }
-
- // test intersection with z down face
- if (d[Z] != 0) {
- t = -((-P[Z]+0.5) / -d[Z]);
- u = P[X] + d[X]*t;
- v = P[Y] + d[Y]*t;
-
- if ((u > -0.5) && (u < 0.5) && (v > -0.5) && (v < 0.5)) {
- iStackP->m_t = t;
- iStackP->m_shape = data;
- iStackP->m_faceID = FACE_ZNEG;
- iStackP++;
- }
- }
-
- // test intersection with y up face
- if (d[Y] != 0) {
- t = -((P[Y]+0.5) / d[Y]);
- u = P[X] + d[X]*t;
- v = P[Z] + d[Z]*t;
-
- if ((u > -0.5) && (u < 0.5) && (v > -0.5) && (v < 0.5)) {
- iStackP->m_t = t;
- iStackP->m_shape = data;
- iStackP->m_faceID = FACE_YPOS;
- iStackP++;
- }
- }
-
- // test intersection with y down face
- if (d[Y] != 0) {
- t = -((-P[Y]+0.5) / -d[Y]);
- u = P[X] + d[X]*t;
- v = P[Z] + d[Z]*t;
-
- if ((u > -0.5) && (u < 0.5) && (v > -0.5) && (v < 0.5)) {
- iStackP->m_t = t;
- iStackP->m_faceID = FACE_YNEG;
- iStackP->m_shape = data;
- iStackP++;
- }
- }
-
- // test intersection with x up face
- if (d[X] != 0) {
- t = -((P[X]+0.5) / d[X]);
- u = P[Z] + d[Z]*t;
- v = P[Y] + d[Y]*t;
-
- if ((u > -0.5) && (u < 0.5) && (v > -0.5) && (v < 0.5)) {
- iStackP->m_t = t;
- iStackP->m_faceID = FACE_XPOS;
- iStackP->m_shape = data;
- iStackP++;
- }
- }
-
- // test intersection with x down face
- if (d[X] != 0) {
- t = -((-P[X]+0.5) / -d[X]);
- u = P[Z] + d[Z]*t;
- v = P[Y] + d[Y]*t;
-
- if ((u > -0.5) && (u < 0.5) && (v > -0.5) && (v < 0.5)) {
- iStackP->m_t = t;
- iStackP->m_shape = data;
- iStackP->m_faceID = FACE_XNEG;
- iStackP++;
- }
- }
-
- return (int)(iStackP-iStack);
- }
- */