home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1992-1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- //////////////////////////////////////////////////////////////////////
- // Curve.c++ - definition of the curve class
- //
- // This class defines a curved stretch of road. It is
- // derived from the stretch abstract base class.
- //////////////////////////////////////////////////////////////////////
-
- #include <math.h>
- #include "Stretch.h"
- #include "Curve.h"
- #include "MiscMath.h"
-
- Curve::Curve(
- Stretch *prev, Stretch *next,
- float radius, float width, float turn_angle, float bank_angle)
- : Stretch(prev, next)
- {
- _type = CURVE;
- _step = 30.0;
-
- // specified in degrees, stored as radians
- // Right Hand Rules (!), so positive is curve to left
- _turn_angle = turn_angle*M_PI/180.0;
- _hill_angle = _hill_radius = 0.0;
- _bank_angle = bank_angle*M_PI/180.0;
-
- _turn_radius = radius;
- _width = width;
- _length = fabs(_turn_radius*_turn_angle);
-
- Stretch::compute_step();
- Stretch::allocate_data();
-
- // find the accumulated offset and orientation
- SbVec3f prev_offset;
- SbRotation prev_orientation;
- Stretch::find_previous(prev_offset, prev_orientation);
-
- make_curve(prev_offset,prev_orientation);
-
- // match up ends
- Stretch::match_ends();
-
- Stretch::init_scenery();
- }
-
-
- Curve::~Curve()
- {
- }
-
-
- void Curve::make_curve(SbVec3f prev_offset, SbRotation prev_orientation)
- {
- SbVec3f left, middle, right;
-
- // set initial values for x coordinates
- left.setValue(- _width/2.0,0.0,0.0);
- middle.setValue(0.0,0.0,0.0);
- right.setValue(_width/2.0,0.0,0.0);
-
- float bank_step = _bank_angle/(_length/_step);
- float bank = 0.0;
-
- float inside_radius = _turn_radius - _width/2.0;
- float outside_radius = _turn_radius + _width/2.0;
-
- float z = 0.0;
-
- for (int i = 0; i < _num_markers; i++)
- {
- if (_turn_angle > 0.0)
- {
- right[0] = outside_radius*fcos(_turn_angle * z/_length) -
- _turn_radius;
- left[0] = inside_radius*fcos(_turn_angle * z/_length) -
- _turn_radius;
-
- right[2] = - outside_radius * fsin(_turn_angle * z/_length);
- left[2] = - inside_radius * fsin(_turn_angle * z/_length);
- }
- else
- {
- left[0] = _turn_radius -
- outside_radius*fcos(_turn_angle * z/_length);
- right[0] = _turn_radius -
- inside_radius*fcos(_turn_angle * z/_length);
-
- left[2] = outside_radius * fsin(_turn_angle * z/_length);
- right[2] = inside_radius * fsin(_turn_angle * z/_length);
- }
-
- middle = (left + right)/2.0;
-
- // Compute the normal
- _data[i].normal.setValue(0.0,1.0,0.0);
-
- _data[i].left = left;
- _data[i].middle = middle;
- _data[i].right = right;
-
- // rotate the data and the normals about the center
- // of the road by bank radians counter clockwise
- rotate_bank(i,bank);
- bank += bank_step;
-
- z += _step;
- }
-
- Stretch::transform_data(prev_offset, prev_orientation);
-
- // find the "center" of the curve, the point which the road
- // radius rotates about
- SbVec3f side_vec;
- if (_turn_angle > 0.0)
- side_vec = this->get_side_direction(0,RIGHT);
- else
- side_vec = this->get_side_direction(0,LEFT);
-
- side_vec.normalize();
- side_vec = side_vec * _turn_radius;
- _center = _data[0].middle + side_vec;
-
- // find angle occupied between markers
- _marker_angle = fabs(_turn_angle)/(float)(_num_markers - 1);
-
- // find orientation from origin to end of this stretch
- SbVec3f up(0.0,1.0,0.0);
- SbRotation this_quat(_data[0].normal,_data[_num_markers-1].normal);
- SbRotation turn_quat(up, _turn_angle);
-
- _orientation = turn_quat * this_quat * prev_orientation;
- }
-
-
- // Returns offset, 0.0 - 1.0, indicating how far along position
- // is from given marker on this stretch
- Boolean Curve::get_marker_offset(
- int marker,
- const SbVec3f position,
- float &new_offset)
- {
- SbVec3f marker_vec = _data[marker].middle - _center;
- SbVec3f car_vec = position - _center;
-
- float angle = angle_between(marker_vec, car_vec);
-
- if (angle > _marker_angle)
- {
- new_offset = ((angle - _marker_angle)/_marker_angle);
- return TRUE;
- }
- else
- {
- new_offset = angle/_marker_angle;
- return FALSE;
- }
- }
-
-
-