From 51c77e34ee760401a936ffecbd798fc21151f7ef Mon Sep 17 00:00:00 2001 From: aignacio_sf <> Date: Sat, 27 Jan 2007 00:58:53 +0000 Subject: [PATCH] Preliminary version. Still needs lots of work! --- direct/src/motiontrail/cMotionTrail.cxx | 652 ++++++++++++++++++++++++ direct/src/motiontrail/cMotionTrail.h | 140 +++++ 2 files changed, 792 insertions(+) create mode 100644 direct/src/motiontrail/cMotionTrail.cxx create mode 100644 direct/src/motiontrail/cMotionTrail.h diff --git a/direct/src/motiontrail/cMotionTrail.cxx b/direct/src/motiontrail/cMotionTrail.cxx new file mode 100644 index 0000000000..4a573faa7e --- /dev/null +++ b/direct/src/motiontrail/cMotionTrail.cxx @@ -0,0 +1,652 @@ + +#include "directbase.h" +#include "cMotionTrail.h" + + +// TypeHandle CMotionTrail::_type_handle; + +CMotionTrail:: +CMotionTrail ( ) { + + _active = true; + _enable = true; + + _pause = false; + _pause_time = 0.0f; + + _fade = false; + _fade_end = false; + _fade_time = 0.0f; + _fade_start_time = 0.0f; + _fade_color_scale = 1.0f; + + _vertex_array = 0; + _last_update_time = 0.0f; + + _use_texture = false; + + +// + +// + + + _calculate_relative_matrix = false; + + _playing = false; + + // default options + _continuous_motion_trail = true; + _color_scale = 1.0; + _time_window = 1.0; + _sampling_time = 0.0; + _square_t = true; + +// _task_transform = false; + +// root_node_path = None + + // node path states + _geom_node = 0; +// geom_node_path = + + _relative_to_render = false; + + // nurbs parameters + _use_nurbs = !false; + _resolution_distance = 0.5f; + + // real-time data + _vertex_index = 0; + _vertex_data = 0; + _triangles = 0; +} + +CMotionTrail:: +~CMotionTrail ( ) { + +} + +void CMotionTrail:: +reset ( ) { + _frame_list.clear ( ); +} + +void CMotionTrail:: +reset_vertex_list ( ) { + _vertex_list.clear ( ); +} + +void CMotionTrail:: +enable (int enable) { + _enable = enable; +} + +void CMotionTrail:: +set_geom_node (PT(GeomNode) geom_node) { + _geom_node = geom_node; +} + +void CMotionTrail:: +use_nurbs (int enable) { + _use_nurbs = enable; +} + +void CMotionTrail:: +use_texture (int enable) { + _use_texture = enable; +} + +void CMotionTrail:: +calculate_relative_matrix (int enable) { + _calculate_relative_matrix = enable; +} + +void CMotionTrail:: +add_vertex (LVector4f *vertex, LVector4f *start_color, LVector4f *end_color, float v) { + + CMotionTrailVertex motion_trail_vertex; + + motion_trail_vertex._vertex = *vertex; + motion_trail_vertex._start_color = *start_color; + motion_trail_vertex._end_color = *end_color; + motion_trail_vertex._v = v; + + motion_trail_vertex._nurbs_curve_evaluator = new NurbsCurveEvaluator ( ); + + _vertex_list.push_back (motion_trail_vertex); +} + +int CMotionTrail:: +check_for_update (float current_time) { + + int state; + + state = false; + if ((current_time - _last_update_time) >= _sampling_time) { + state = true; + } + if (_pause) { + state = false; + } + state = state && _enable; + + return state; +} + +float one_minus_x (float x) { + x = 1.0 - x; + if (x < 0.0) { + x = 0.0; + } + + return x; +} + +void CMotionTrail:: +begin_geometry ( ) { + + const GeomVertexFormat *format; + + _vertex_index = 0; + if (_use_texture) { + format = GeomVertexFormat::get_v3c4t2 ( ); + } + else { + format = GeomVertexFormat::get_v3c4 ( ); + } + + _vertex_data = new GeomVertexData ("vertices", format, Geom::UH_static); + _vertex_writer = GeomVertexWriter (_vertex_data, "vertex"); + _color_writer = GeomVertexWriter (_vertex_data, "color"); + if (_use_texture) { + _texture_writer = GeomVertexWriter (_vertex_data, "texcoord"); + } + + _triangles = new GeomTriangles (Geom::UH_static); +} + +void CMotionTrail:: +add_geometry_quad (LVector3f &v0, LVector3f &v1, LVector3f &v2, LVector3f &v3, LVector4f &c0, LVector4f &c1, LVector4f &c2, LVector4f &c3, LVector2f &t0, LVector2f &t1, LVector2f &t2, LVector2f &t3) { + + _vertex_writer.add_data3f (v0); + _vertex_writer.add_data3f (v1); + _vertex_writer.add_data3f (v2); + _vertex_writer.add_data3f (v3); + + _color_writer.add_data4f (c0); + _color_writer.add_data4f (c1); + _color_writer.add_data4f (c2); + _color_writer.add_data4f (c3); + + if (_use_texture) { + _texture_writer.add_data2f (t0); + _texture_writer.add_data2f (t1); + _texture_writer.add_data2f (t2); + _texture_writer.add_data2f (t3); + } + + int vertex_index; + vertex_index = _vertex_index; + + _triangles -> add_vertex (vertex_index + 0); + _triangles -> add_vertex (vertex_index + 1); + _triangles -> add_vertex (vertex_index + 2); + _triangles -> close_primitive ( ); + + _triangles -> add_vertex (vertex_index + 1); + _triangles -> add_vertex (vertex_index + 3); + _triangles -> add_vertex (vertex_index + 2); + _triangles -> close_primitive ( ); + + _vertex_index += 4; +} + +void CMotionTrail::end_geometry ( ) { + + PT(Geom) geometry; + + geometry = new Geom (_vertex_data); + geometry -> add_primitive (_triangles); + + if (_geom_node) { + _geom_node -> remove_all_geoms ( ); + _geom_node -> add_geom (geometry); + } +} + +void CMotionTrail:: +update_motion_trail (float current_time, LMatrix4f *transform) { + + int debug; + int total_frames; + + debug = true; + + total_frames = _frame_list.size ( ); + if (total_frames >= 1) { + list ::iterator frame_iterator; + CMotionTrailFrame motion_trail_frame; + + frame_iterator = _frame_list.begin ( ); + motion_trail_frame = *frame_iterator; + if (*transform == motion_trail_frame._transform) { + // duplicate transform + return; + } + } + + int total_vertices; + float color_scale; + LMatrix4f start_transform; + LMatrix4f end_transform; + LMatrix4f inverse_matrix; + + total_vertices = _vertex_list.size ( ); + color_scale = _color_scale; + if (_fade) + { + float elapsed_time; + + elapsed_time = current_time - _fade_start_time; + if (elapsed_time < 0.0) + { + elapsed_time = 0.0; + } + if (elapsed_time < _fade_time) + { + color_scale = (1.0f - (elapsed_time / _fade_time)) * color_scale; + } + else + { + color_scale = 0.0; + _fade_end = true; + } + } + + _last_update_time = current_time; + + // remove expired frames + float minimum_time; + + minimum_time = current_time - _time_window; + + int index; + int last_frame_index; + list ::iterator frame_iterator; + CMotionTrailFrame motion_trail_frame; + + index = 0; + last_frame_index = total_frames - 1; + frame_iterator = _frame_list.end ( ); + while (index <= last_frame_index) + { + frame_iterator--; + motion_trail_frame = *frame_iterator; + if (motion_trail_frame._time >= minimum_time) + { + break; + } + else + { + _frame_list.pop_back ( ); + } + + index += 1; + } + + // add new frame to beginning of list + { + CMotionTrailFrame motion_trail_frame; + + motion_trail_frame._time = current_time; + motion_trail_frame._transform = *transform; + + _frame_list.push_front (motion_trail_frame); + } + + // convert frames and vertices to geometry + total_frames = _frame_list.size ( ); + +if (debug) +{ + printf ("update_motion_trail, total_frames = %d, total_vertices = %d, nurbs = %d, _calculate_relative_matrix = %d \n", total_frames, total_vertices, _use_nurbs, _calculate_relative_matrix); +} + if ((total_frames >= 2) && (total_vertices >= 2)) + { + int total_segments; + float minimum_time; + float delta_time; + CMotionTrailFrame last_motion_trail_frame; + + list ::iterator vertex_iterator; + + // vertex list to vertex array + index = 0; + _vertex_array = new CMotionTrailVertex [total_vertices]; + for (vertex_iterator = _vertex_list.begin ( ); vertex_iterator != _vertex_list.end ( ); vertex_iterator++) + { + _vertex_array [index] = *vertex_iterator; + index++; + } + + // begin geometry + this -> begin_geometry ( ); + + total_segments = total_frames - 1; + + frame_iterator = _frame_list.end ( ); + frame_iterator--; + last_motion_trail_frame = *frame_iterator; + + minimum_time = last_motion_trail_frame._time; + delta_time = current_time - minimum_time; + +_calculate_relative_matrix = true; + + if (_calculate_relative_matrix) + { + inverse_matrix = *transform; + inverse_matrix.invert_in_place ( ); + } +// if (_use_nurbs && (total_frames >= 5)) + if ((total_frames >= 5)) + { + // nurbs version + +if (debug) +{ + printf ("nurbs\n"); +// __debugbreak(); +} + + float total_distance; + LVector3f vector; + LVector4f v; + LVector4f v0; + LVector4f v1; + LVector4f v2; + LVector4f v3; + + total_distance = 0.0f; + + int total_vertex_segments; + + total_vertex_segments = total_vertices - 1; + + // reset NurbsCurveEvaluators for each vertex (the starting point for the trail) + + for (index = 0; index < total_vertices; index++) + { + CMotionTrailVertex *motion_trail_vertex; + PT(NurbsCurveEvaluator) nurbs_curve_evaluator; + + motion_trail_vertex = &_vertex_array [index]; + nurbs_curve_evaluator = motion_trail_vertex -> _nurbs_curve_evaluator; + nurbs_curve_evaluator -> reset (total_segments); + } + + // add vertices to each NurbsCurveEvaluator + + int segment_index; + + segment_index = 0; + + frame_iterator = _frame_list.begin ( ); + while (segment_index < total_segments) + { + int vertex_segement_index; + CMotionTrailFrame motion_trail_frame_start; + CMotionTrailFrame motion_trail_frame_end; + + motion_trail_frame_start = *frame_iterator; + frame_iterator++; + motion_trail_frame_end = *frame_iterator; + + if (_calculate_relative_matrix) { + start_transform.multiply (motion_trail_frame_start._transform, inverse_matrix); + end_transform.multiply (motion_trail_frame_end._transform, inverse_matrix); + } + else { + start_transform = motion_trail_frame_start._transform; + end_transform = motion_trail_frame_end._transform; + } + + CMotionTrailVertex *motion_trail_vertex_start; + CMotionTrailVertex *motion_trail_vertex_end; + PT(NurbsCurveEvaluator) nurbs_curve_evaluator; + + motion_trail_vertex_start = &_vertex_array [0]; + + v0 = start_transform.xform (motion_trail_vertex_start -> _vertex); + v2 = end_transform.xform (motion_trail_vertex_start -> _vertex); + + nurbs_curve_evaluator = motion_trail_vertex_start -> _nurbs_curve_evaluator; + +// print "nurbs_curve_evaluator", nurbs_curve_evaluator, "index", (vertex_segement_index) + nurbs_curve_evaluator -> set_vertex (segment_index, v0); + + vertex_segement_index = 0; + while (vertex_segement_index < total_vertex_segments) + { + motion_trail_vertex_start = &_vertex_array [vertex_segement_index]; + motion_trail_vertex_end = &_vertex_array [vertex_segement_index + 1]; + + v1 = start_transform.xform (motion_trail_vertex_end -> _vertex); + v3 = end_transform.xform (motion_trail_vertex_end -> _vertex); + + nurbs_curve_evaluator = motion_trail_vertex_end -> _nurbs_curve_evaluator; + + +// print "nurbs_curve_evaluator", nurbs_curve_evaluator, "index", (vertex_segement_index + 1) + + + nurbs_curve_evaluator -> set_vertex (segment_index, v1); + +/* + + """ + print v0 + print v1 + print v2 + print v3 + """ +*/ + + if (vertex_segement_index == (total_vertex_segments - 1)) + { + float distance; + + v = v1 - v3; + vector.set (v[0], v[1], v[2]); + distance = vector.length(); + total_distance += distance; +// # print "DISTANCE", distance + } + + vertex_segement_index += 1; + } + +// print "TOTAL DISTANCE", total_distance, "SEGMENTS", total_distance / self.resolution_distance + + + segment_index += 1; + } + + // evaluate NurbsCurveEvaluator for each vertex + PT(NurbsCurveResult) *nurbs_curve_result_array; + + nurbs_curve_result_array = new PT(NurbsCurveResult) [total_vertices]; + + for (index = 0; index < total_vertices; index++) + { + CMotionTrailVertex *motion_trail_vertex; + PT(NurbsCurveEvaluator) nurbs_curve_evaluator; + PT(NurbsCurveResult) nurbs_curve_result; + + motion_trail_vertex = &_vertex_array [index]; + + nurbs_curve_evaluator = motion_trail_vertex -> _nurbs_curve_evaluator; + nurbs_curve_result = nurbs_curve_evaluator -> evaluate ( ); + nurbs_curve_result_array [index] = nurbs_curve_result; + + if (debug) + { + float nurbs_start_t; + float nurbs_end_t; + + nurbs_start_t = nurbs_curve_result -> get_start_t(); + nurbs_end_t = nurbs_curve_result -> get_end_t(); + + printf ("nurbs_start_t %f, nurbs_end_t %f \n", nurbs_start_t, nurbs_end_t); + } + } + + // create quads from NurbsCurveResult + float total_curve_segments; + + total_curve_segments = (total_distance / _resolution_distance); + if (total_curve_segments < total_segments) + { + total_curve_segments = total_segments; + } + + { + LVector3f v0; + LVector3f v1; + LVector3f v2; + LVector3f v3; + + LVector4f c0; + LVector4f c1; + LVector4f c2; + LVector4f c3; + + LVector2f t0; + LVector2f t1; + LVector2f t2; + LVector2f t3; + + LVector4f vertex_start_color; + LVector4f vertex_end_color; + + float curve_segment_index; + + curve_segment_index = 0.0; + while (curve_segment_index < total_curve_segments) + { + float st; + float et; + float start_t; + float end_t; + float color_start_t; + float color_end_t; + + int vertex_segement_index; + + CMotionTrailVertex *motion_trail_vertex_start; + CMotionTrailVertex *motion_trail_vertex_end; + PT(NurbsCurveResult) start_nurbs_curve_result; + PT(NurbsCurveResult) end_nurbs_curve_result; + + vertex_segement_index = 0; + + st = curve_segment_index / total_curve_segments; + et = (curve_segment_index + 1.0) / total_curve_segments; + + start_t = st; + end_t = et; + + if (_square_t) + { + start_t *= start_t; + end_t *= end_t; + } + + motion_trail_vertex_start = &_vertex_array [0]; + + vertex_start_color = motion_trail_vertex_start -> _end_color + (motion_trail_vertex_start -> _start_color - motion_trail_vertex_start -> _end_color); + + color_start_t = color_scale * start_t; + color_end_t = color_scale * end_t; + + c0 = vertex_start_color * one_minus_x (color_start_t); + c2 = vertex_start_color * one_minus_x (color_end_t); + + t0.set (one_minus_x (st), motion_trail_vertex_start -> _v); + t2.set (one_minus_x (et), motion_trail_vertex_start -> _v); + + while (vertex_segement_index < total_vertex_segments) + { + float start_nurbs_start_t; + float start_nurbs_end_t; + float end_nurbs_start_t; + float end_nurbs_end_t; + + motion_trail_vertex_start = &_vertex_array [vertex_segement_index]; + motion_trail_vertex_end = &_vertex_array [vertex_segement_index + 1]; + + start_nurbs_curve_result = nurbs_curve_result_array [vertex_segement_index]; + end_nurbs_curve_result = nurbs_curve_result_array [vertex_segement_index + 1]; + + start_nurbs_start_t = start_nurbs_curve_result -> get_start_t(); + start_nurbs_end_t = start_nurbs_curve_result -> get_end_t(); + end_nurbs_start_t = end_nurbs_curve_result -> get_start_t(); + end_nurbs_end_t = end_nurbs_curve_result -> get_end_t(); + + float start_delta_t; + float end_delta_t; + + start_delta_t = (start_nurbs_end_t - start_nurbs_start_t); + end_delta_t = (end_nurbs_end_t - end_nurbs_start_t); + + start_nurbs_curve_result -> eval_point (start_nurbs_start_t + (start_delta_t * st), v0); + end_nurbs_curve_result -> eval_point (end_nurbs_start_t + (end_delta_t * st), v1); + + start_nurbs_curve_result -> eval_point (start_nurbs_start_t + (start_delta_t * et), v2); + end_nurbs_curve_result -> eval_point (end_nurbs_start_t + (end_delta_t * et), v3); + + // color + vertex_end_color = motion_trail_vertex_end -> _end_color + (motion_trail_vertex_end -> _start_color - motion_trail_vertex_end -> _end_color); + + c1 = vertex_end_color * one_minus_x (color_start_t); + c3 = vertex_end_color * one_minus_x (color_end_t); + + // uv + t1.set (one_minus_x (st), motion_trail_vertex_end -> _v); + t3.set (one_minus_x (et), motion_trail_vertex_end -> _v); + + this -> add_geometry_quad (v0, v1, v2, v3, c0, c1, c2, c3, t0, t1, t2, t3); + + // reuse calculations + c0 = c1; + c2 = c3; + + t0 = t1; + t2 = t3; + + vertex_segement_index += 1; + } + + curve_segment_index += 1.0; + } + } + + delete nurbs_curve_result_array; + } + else + { + // non-nurbs version + + + } + + // end geometry + { + this -> end_geometry ( ); + } + + delete _vertex_array; + _vertex_array = 0; + } +} diff --git a/direct/src/motiontrail/cMotionTrail.h b/direct/src/motiontrail/cMotionTrail.h new file mode 100644 index 0000000000..5085a64ddb --- /dev/null +++ b/direct/src/motiontrail/cMotionTrail.h @@ -0,0 +1,140 @@ + +#ifndef CMOTIONTRAIL_H +#define CMOTIONTRAIL_H + +#include "directbase.h" + +#include "geomNode.h" +#include "geomVertexData.h" +#include "geomVertexWriter.h" +#include "geomTriangles.h" +#include "lmatrix4.h" +#include "nurbsCurveEvaluator.h" + +#include + +class CMotionTrailVertex { + +public: + LVector4f _vertex; + LVector4f _start_color; + LVector4f _end_color; + float _v; + + PT(NurbsCurveEvaluator) _nurbs_curve_evaluator; +}; + +class CMotionTrailFrame { + +public: + float _time; + LMatrix4f _transform; +}; + +class EXPCL_DIRECT CMotionTrail : public TypedReferenceCount { + +PUBLISHED: + + CMotionTrail ( ); + ~CMotionTrail ( ); + + void reset ( ); + void reset_vertex_list ( ); + + void enable (int enable); + void set_geom_node (PT(GeomNode) geom_node); + void use_nurbs (int enable); + void use_texture (int enable); + void calculate_relative_matrix (int enable); + void add_vertex (LVector4f *vertex, LVector4f *start_color, LVector4f *end_color, float v); + + int check_for_update (float current_time); + void update_motion_trail (float current_time, LMatrix4f *transform); + +public: + + void begin_geometry ( ); + void add_geometry_quad (LVector3f &v0, LVector3f &v1, LVector3f &v2, LVector3f &v3, LVector4f &c0, LVector4f &c1, LVector4f &c2, LVector4f &c3, LVector2f &t0, LVector2f &t1, LVector2f &t2, LVector2f &t3); + void end_geometry ( ); + + int _active; + int _enable; + + int _pause; + float _pause_time; + + int _fade; + int _fade_end; + float _fade_time; + float _fade_start_time; + float _fade_color_scale; + + CMotionTrailVertex *_vertex_array; + + float _last_update_time; + + int _use_texture; + + + list _vertex_list; + list _frame_list; + +// parent_node_path = parent_node_path + + int _calculate_relative_matrix; + + int _playing; + + // default options + int _continuous_motion_trail; + float _color_scale; + float _time_window; + float _sampling_time; + int _square_t; + +// int _task_transform; + +// root_node_path = None + + // node path states + PT(GeomNode) _geom_node; + +// geom_node_path = + + int _relative_to_render; + + // nurbs parameters + int _use_nurbs; + float _resolution_distance; + + + // real-time data + int _vertex_index; + PT(GeomVertexData) _vertex_data; + GeomVertexWriter _vertex_writer; + GeomVertexWriter _color_writer; + GeomVertexWriter _texture_writer; + PT(GeomTriangles) _triangles; + +/* +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + TypedReferenceCount::init_type(); + register_type(_type_handle, "CMotionTrail", + TypedReferenceCount::get_class_type()); + } + virtual TypeHandle get_type() const { + return get_class_type(); + } + virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + +private: + static TypeHandle _type_handle; +*/ + +}; + +#endif