2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
14 * $Source: /cvs/cvsroot/d2x/main/editor/eobject.c,v $
17 * $Date: 2004-12-19 13:54:27 $
19 * Editor object functions.
21 * $Log: not supported by cvs2svn $
22 * Revision 1.1.1.1 1999/06/14 22:03:00 donut
23 * Import of d1x 1.37 source.
25 * Revision 2.0 1995/02/27 11:35:14 john
26 * Version 2.0! No anonymous unions, Watcom 10.0, with no need
29 * Revision 1.93 1995/02/22 15:09:04 allender
30 * remove anonymous unions from object structure
32 * Revision 1.92 1995/01/12 12:10:32 yuan
33 * Added coop object capability.
35 * Revision 1.91 1994/12/20 17:57:02 yuan
36 * Multiplayer object stuff.
38 * Revision 1.90 1994/11/27 23:17:49 matt
39 * Made changes for new mprintf calling convention
41 * Revision 1.89 1994/11/17 14:48:06 mike
42 * validation functions moved from editor to game.
44 * Revision 1.88 1994/11/14 11:40:03 mike
45 * fix default robot behavior.
47 * Revision 1.87 1994/10/25 10:51:31 matt
48 * Vulcan cannon powerups now contain ammo count
50 * Revision 1.86 1994/10/23 02:11:40 matt
51 * Got rid of obsolete hostage_info stuff
53 * Revision 1.85 1994/10/17 21:35:32 matt
54 * Added support for new Control Center/Main Reactor
56 * Revision 1.84 1994/10/10 17:23:13 mike
57 * Verify that not placing too many player objects.
59 * Revision 1.83 1994/09/24 14:15:35 mike
60 * Custom colored object support.
62 * Revision 1.82 1994/09/15 22:58:12 matt
63 * Made new objects be oriented to their segment
64 * Added keypad function to flip an object upside-down
66 * Revision 1.81 1994/09/01 10:58:41 matt
67 * Sizes for powerups now specified in bitmaps.tbl; blob bitmaps now plot
68 * correctly if width & height of bitmap are different.
70 * Revision 1.80 1994/08/25 21:58:14 mike
71 * Write ObjectSelectPrevInMine and something else, I think...
73 * Revision 1.79 1994/08/16 20:19:54 mike
74 * Make STILL default (from CHASE_OBJECT).
76 * Revision 1.78 1994/08/14 23:15:45 matt
77 * Added animating bitmap hostages, and cleaned up vclips a bit
79 * Revision 1.77 1994/08/13 14:58:43 matt
80 * Finished adding support for miscellaneous objects
82 * Revision 1.76 1994/08/12 22:24:58 matt
83 * Generalized polygon objects (such as control center)
85 * Revision 1.75 1994/08/09 16:06:11 john
86 * Added the ability to place players. Made old
87 * Player variable be ConsoleObject.
89 * Revision 1.74 1994/08/05 18:18:55 matt
90 * Made object rotation have 4x resolution, and SHIFT+rotate do old resolution.
92 * Revision 1.73 1994/08/01 13:30:56 matt
93 * Made fvi() check holes in transparent walls, and changed fvi() calling
94 * parms to take all input data in query structure.
100 static char rcsid[] = "$Id: eobject.c,v 1.1 2004-12-19 13:54:27 btb Exp $";
123 #include "3d.h" // For g3_point_to_vec
129 #include "medrobot.h"
133 #define OBJ_SCALE (F1_0/2)
134 #define OBJ_DEL_SIZE (F1_0/2)
136 #define ROTATION_UNIT (4096/4)
138 //segment *Cur_object_seg = -1;
140 void show_objects_in_segment(segment *sp)
144 mprintf((0,"Objects in segment #%i: ",sp-Segments));
147 while (objid != -1) {
148 mprintf((0,"%2i ",objid));
149 objid = Objects[objid].next;
154 //returns the number of the first object in a segment, skipping the player
155 int get_first_object(segment *seg)
161 if (id == (ConsoleObject-Objects))
162 id = Objects[id].next;
167 //returns the number of the next object in a segment, skipping the player
168 int get_next_object(segment *seg,int id)
170 if (id==-1 || (id=Objects[id].next)==-1)
171 return get_first_object(seg);
173 if (id == (ConsoleObject-Objects))
174 return get_next_object(seg,id);
180 //@@// ------------------------------------------------------------------------------------------------------
181 //@@// this should be called whenever the current segment may have changed
182 //@@// If Cur_object_seg != Cursegp, then update various variables.
183 //@@// this used to be called update_due_to_new_segment()
184 //@@void ObjectUpdateCurrent(void)
186 //@@ if (Cur_object_seg != Cursegp) {
187 //@@ Cur_object_seg = Cursegp;
188 //@@ Cur_object_index = get_first_object(Cur_object_seg);
189 //@@ Update_flags |= UF_WORLD_CHANGED;
194 // ------------------------------------------------------------------------------------
195 int place_object(segment *segp, vms_vector *object_pos, int object_type)
199 vms_matrix seg_matrix;
201 med_extract_matrix_from_segment(segp,&seg_matrix);
203 switch(ObjType[object_type]) {
207 objnum = obj_create(OBJ_HOSTAGE, -1,
208 segp-Segments,object_pos,&seg_matrix,HOSTAGE_SIZE,
209 CT_NONE,MT_NONE,RT_HOSTAGE);
214 obj = &Objects[objnum];
216 // Fill in obj->id and other hostage info
217 hostage_init_info( objnum );
219 obj->control_type = CT_POWERUP;
221 obj->rtype.vclip_info.vclip_num = Hostage_vclip_num[ObjId[object_type]];
222 obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].frame_time;
223 obj->rtype.vclip_info.framenum = 0;
229 objnum = obj_create(OBJ_ROBOT,ObjId[object_type],segp-Segments,object_pos,
230 &seg_matrix,Polygon_models[Robot_info[ObjId[object_type]].model_num].rad,
231 CT_AI,MT_PHYSICS,RT_POLYOBJ);
236 obj = &Objects[objnum];
238 //Set polygon-object-specific data
240 obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num;
241 obj->rtype.pobj_info.subobj_flags = 0;
245 obj->mtype.phys_info.mass = Robot_info[obj->id].mass;
246 obj->mtype.phys_info.drag = Robot_info[obj->id].drag;
248 obj->mtype.phys_info.flags |= (PF_LEVELLING);
250 obj->shields = Robot_info[obj->id].strength;
254 hide_segment = Markedsegp-Segments;
257 // robots which lunge forward to attack cannot have behavior type still.
258 if (Robot_info[obj->id].attack_type)
259 init_ai_object(obj-Objects, AIB_NORMAL, hide_segment);
261 init_ai_object(obj-Objects, AIB_STILL, hide_segment);
267 objnum = obj_create(OBJ_POWERUP,ObjId[object_type],
268 segp-Segments,object_pos,&seg_matrix,Powerup_info[ObjId[object_type]].size,
269 CT_POWERUP,MT_NONE,RT_POWERUP);
274 obj = &Objects[objnum];
276 //set powerup-specific data
278 obj->rtype.vclip_info.vclip_num = Powerup_info[obj->id].vclip_num;
279 obj->rtype.vclip_info.frametime = Vclip[obj->rtype.vclip_info.vclip_num].play_time/Vclip[obj->rtype.vclip_info.vclip_num].num_frames;
280 obj->rtype.vclip_info.framenum = 0;
282 if (obj->id == POW_VULCAN_WEAPON)
283 obj->ctype.powerup_info.count = VULCAN_WEAPON_AMMO_AMOUNT;
285 obj->ctype.powerup_info.count = 1;
290 case OL_CONTROL_CENTER:
292 int obj_type,control_type;
294 if (ObjType[object_type]==OL_CONTROL_CENTER) {
295 obj_type = OBJ_CNTRLCEN;
296 control_type = CT_CNTRLCEN;
299 obj_type = OBJ_CLUTTER;
300 control_type = CT_NONE;
303 objnum = obj_create(obj_type,object_type,segp-Segments,object_pos,
304 &seg_matrix,Polygon_models[ObjId[object_type]].rad,
305 control_type,MT_NONE,RT_POLYOBJ);
310 obj = &Objects[objnum];
312 obj->shields = ObjStrength[object_type];
314 //Set polygon-object-specific data
315 obj->shields = ObjStrength[object_type];
316 obj->rtype.pobj_info.model_num = ObjId[object_type];
317 obj->rtype.pobj_info.subobj_flags = 0;
323 objnum = obj_create(OBJ_PLAYER,ObjId[object_type],segp-Segments,object_pos,
324 &seg_matrix,Polygon_models[Player_ship->model_num].rad,
325 CT_NONE,MT_PHYSICS,RT_POLYOBJ);
330 obj = &Objects[objnum];
332 //Set polygon-object-specific data
334 obj->rtype.pobj_info.model_num = Player_ship->model_num;
335 obj->rtype.pobj_info.subobj_flags = 0;
336 //for (i=0;i<MAX_SUBMODELS;i++)
337 // vm_angvec_zero(&obj->rtype.pobj_info.anim_angles[i]);
341 vm_vec_zero(&obj->mtype.phys_info.velocity);
342 obj->mtype.phys_info.mass = Player_ship->mass;
343 obj->mtype.phys_info.drag = Player_ship->drag;
344 obj->mtype.phys_info.flags |= PF_TURNROLL | PF_LEVELLING | PF_WIGGLE;
345 obj->shields = i2f(100);
353 Cur_object_index = objnum;
354 //Cur_object_seg = Cursegp;
356 show_objects_in_segment(Cursegp); //mprintf the objects
358 Update_flags |= UF_WORLD_CHANGED;
363 // ------------------------------------------------------------------------------------------------------
364 // Count number of player objects, return value.
365 int compute_num_players(void)
369 for (i=0; i<=Highest_object_index; i++)
370 if (Objects[i].type == OBJ_PLAYER)
377 int ObjectMakeCoop(void)
379 Assert(Cur_object_index != -1);
380 Assert(Cur_object_index < MAX_OBJECTS);
381 // Assert(Objects[Cur_object_index.type == OBJ_PLAYER);
383 if (Objects[Cur_object_index].type == OBJ_PLAYER ) {
384 Objects[Cur_object_index].type = OBJ_COOP;
385 editor_status("You just made a player object COOPERATIVE");
387 editor_status("This is not a player object");
392 // ------------------------------------------------------------------------------------------------------
393 // Place current object at center of current segment.
394 int ObjectPlaceObject(void)
396 int old_cur_object_index;
399 vms_vector cur_object_loc;
402 if (ObjType[Cur_robot_type] == OL_PLAYER) {
403 int num_players = compute_num_players();
404 Assert(num_players <= MAX_PLAYERS);
405 if (num_players == MAX_PLAYERS) {
406 editor_status("Can't place player object. Already %i players.", MAX_PLAYERS);
413 if (ObjType[Cur_robot_type] == OL_PLAYER) {
414 int num_players = compute_num_players();
415 Assert(num_players <= MAX_MULTI_PLAYERS);
416 if (num_players > MAX_PLAYERS)
417 editor_status("You just placed a cooperative player object");
418 if (num_players == MAX_MULTI_PLAYERS) {
419 editor_status("Can't place player object. Already %i players.", MAX_MULTI_PLAYERS);
425 //update_due_to_new_segment();
426 compute_segment_center(&cur_object_loc, Cursegp);
428 old_cur_object_index = Cur_object_index;
429 rval = place_object(Cursegp, &cur_object_loc, Cur_robot_type);
431 if (old_cur_object_index != Cur_object_index)
432 Objects[Cur_object_index].rtype.pobj_info.tmap_override = -1;
438 // ------------------------------------------------------------------------------------------------------
439 // Place current object at center of current segment.
440 int ObjectPlaceObjectTmap(void)
442 int rval, old_cur_object_index;
443 vms_vector cur_object_loc;
445 //update_due_to_new_segment();
446 compute_segment_center(&cur_object_loc, Cursegp);
448 old_cur_object_index = Cur_object_index;
449 rval = place_object(Cursegp, &cur_object_loc, Cur_robot_type);
451 if ((Cur_object_index != old_cur_object_index) && (Objects[Cur_object_index].render_type == RT_POLYOBJ))
452 Objects[Cur_object_index].rtype.pobj_info.tmap_override = CurrentTexture;
454 editor_status("Unable to apply current texture map to this object.");
459 // ------------------------------------------------------------------------------------------------------
460 int ObjectSelectNextinSegment(void)
466 //update_due_to_new_segment();
468 //Assert(Cur_object_seg == Cursegp);
470 if (Cur_object_index == -1) {
472 Cur_object_index = objsegp->objects;
475 if (Objects[Cur_object_index].segnum != Cursegp-Segments)
476 Cur_object_index = objsegp->objects;
480 //Debug: make sure current object is in current segment
481 for (id=objsegp->objects;(id != Cur_object_index) && (id != -1);id=Objects[id].next);
482 Assert(id == Cur_object_index); //should have found object
484 // Select the next object, wrapping back to start if we are at the end of the linked list for this segment.
486 Cur_object_index = get_next_object(objsegp,Cur_object_index);
488 //mprintf((0,"Cur_object_index == %i\n", Cur_object_index));
490 Update_flags |= UF_WORLD_CHANGED;
496 //Moves to next object in the mine, skipping the player
497 int ObjectSelectNextInMine()
499 for (i=0;i<MAX_OBJECTS;i++) {
501 if (Cur_object_index>= MAX_OBJECTS ) Cur_object_index= 0;
503 if ((Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != (ConsoleObject-Objects)) ) {
504 Cursegp = &Segments[Objects[Cur_object_index ].segnum];
505 med_create_new_segment_from_cursegp();
506 //Cur_object_seg = Cursegp;
510 Cur_object_index = -1;
512 Update_flags |= UF_WORLD_CHANGED;
517 //Moves to next object in the mine, skipping the player
518 int ObjectSelectPrevInMine()
520 for (i=0;i<MAX_OBJECTS;i++) {
522 if (Cur_object_index < 0 )
523 Cur_object_index = MAX_OBJECTS-1;
525 if ((Objects[Cur_object_index ].type != OBJ_NONE) && (Cur_object_index != (ConsoleObject-Objects)) ) {
526 Cursegp = &Segments[Objects[Cur_object_index ].segnum];
527 med_create_new_segment_from_cursegp();
528 //Cur_object_seg = Cursegp;
532 Cur_object_index = -1;
534 Update_flags |= UF_WORLD_CHANGED;
539 // ------------------------------------------------------------------------------------------------------
540 // Delete current object, if it exists.
541 // If it doesn't exist, reformat Matt's hard disk, even if he is in Boston.
542 int ObjectDelete(void)
545 if (Cur_object_index != -1) {
548 delete_objnum = Cur_object_index;
550 ObjectSelectNextinSegment();
552 obj_delete(delete_objnum);
554 if (delete_objnum == Cur_object_index)
555 Cur_object_index = -1;
557 Update_flags |= UF_WORLD_CHANGED;
563 // -----------------------------------------------------------------------------------------------------------------
564 // Object has moved to another segment, (or at least poked through).
565 // If still in mine, that is legal, so relink into new segment.
566 // Return value: 0 = in mine, 1 = not in mine
567 int move_object_within_mine(object * obj, vms_vector *newpos )
571 for (segnum=0;segnum <= Highest_segment_index; segnum++) {
572 segmasks result = get_seg_masks(&obj->pos,segnum,0);
573 if (result.centermask == 0) {
578 // See if the radius pokes through any wall.
580 fq.startseg = obj->segnum;
584 fq.ignore_obj_list = NULL;
587 fate = find_vector_intersection(&fq,&hit_info);
589 if (fate != HIT_WALL) {
590 if ( segnum != obj->segnum )
591 obj_relink( obj-Objects, segnum);
595 //mprintf((0, "Hit wall seg:side = %i:%i\n", hit_info.hit_seg, hit_info.hit_side));
604 // Return 0 if object is in expected segment, else return 1
605 int verify_object_seg(object *objp, vms_vector *newpos)
607 segmasks result = get_seg_masks(newpos, objp->segnum, objp->size);
609 if (result.facemask == 0)
612 return move_object_within_mine(objp, newpos);
616 // ------------------------------------------------------------------------------------------------------
617 int ObjectMoveForward(void)
623 if (Cur_object_index == -1) {
624 editor_status("No current object, cannot move.");
628 obj = &Objects[Cur_object_index];
630 extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
631 vm_vec_normalize(&fvec);
633 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
635 if (!verify_object_seg(obj, &newpos))
638 Update_flags |= UF_WORLD_CHANGED;
643 // ------------------------------------------------------------------------------------------------------
644 int ObjectMoveBack(void)
650 if (Cur_object_index == -1) {
651 editor_status("No current object, cannot move.");
655 obj = &Objects[Cur_object_index];
657 extract_forward_vector_from_segment(&Segments[obj->segnum], &fvec);
658 vm_vec_normalize(&fvec);
660 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&fvec, OBJ_SCALE));
662 if (!verify_object_seg(obj, &newpos))
665 Update_flags |= UF_WORLD_CHANGED;
670 // ------------------------------------------------------------------------------------------------------
671 int ObjectMoveLeft(void)
677 if (Cur_object_index == -1) {
678 editor_status("No current object, cannot move.");
682 obj = &Objects[Cur_object_index];
684 extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
685 vm_vec_normalize(&rvec);
687 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
689 if (!verify_object_seg(obj, &newpos))
692 Update_flags |= UF_WORLD_CHANGED;
697 // ------------------------------------------------------------------------------------------------------
698 int ObjectMoveRight(void)
704 if (Cur_object_index == -1) {
705 editor_status("No current object, cannot move.");
709 obj = &Objects[Cur_object_index];
711 extract_right_vector_from_segment(&Segments[obj->segnum], &rvec);
712 vm_vec_normalize(&rvec);
714 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&rvec, OBJ_SCALE));
716 if (!verify_object_seg(obj, &newpos))
719 Update_flags |= UF_WORLD_CHANGED;
724 // ------------------------------------------------------------------------------------------------------
725 int ObjectSetDefault(void)
727 //update_due_to_new_segment();
729 if (Cur_object_index == -1) {
730 editor_status("No current object, cannot move.");
734 compute_segment_center(&Objects[Cur_object_index].pos, &Segments[Objects[Cur_object_index].segnum]);
736 Update_flags |= UF_WORLD_CHANGED;
742 // ------------------------------------------------------------------------------------------------------
743 int ObjectMoveUp(void)
749 if (Cur_object_index == -1) {
750 editor_status("No current object, cannot move.");
754 obj = &Objects[Cur_object_index];
756 extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
757 vm_vec_normalize(&uvec);
759 vm_vec_add(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
761 if (!verify_object_seg(obj, &newpos))
764 Update_flags |= UF_WORLD_CHANGED;
769 // ------------------------------------------------------------------------------------------------------
770 int ObjectMoveDown(void)
776 if (Cur_object_index == -1) {
777 editor_status("No current object, cannot move.");
781 obj = &Objects[Cur_object_index];
783 extract_up_vector_from_segment(&Segments[obj->segnum], &uvec);
784 vm_vec_normalize(&uvec);
786 vm_vec_sub(&newpos, &obj->pos, vm_vec_scale(&uvec, OBJ_SCALE));
788 if (!verify_object_seg(obj, &newpos))
791 Update_flags |= UF_WORLD_CHANGED;
796 // ------------------------------------------------------------------------------------------------------
797 int ObjectMakeSmaller(void)
801 //update_due_to_new_segment();
803 cur_size = Objects[Cur_object_index].size;
805 cur_size -= OBJ_DEL_SIZE;
806 if (cur_size < OBJ_DEL_SIZE)
807 cur_size = OBJ_DEL_SIZE;
809 Objects[Cur_object_index].size = cur_size;
811 Update_flags |= UF_WORLD_CHANGED;
816 // ------------------------------------------------------------------------------------------------------
817 int ObjectMakeLarger(void)
821 //update_due_to_new_segment();
823 cur_size = Objects[Cur_object_index].size;
825 cur_size += OBJ_DEL_SIZE;
827 Objects[Cur_object_index].size = cur_size;
829 Update_flags |= UF_WORLD_CHANGED;
834 // ------------------------------------------------------------------------------------------------------
836 int rotate_object(short objnum, int p, int b, int h)
838 object *obj = &Objects[objnum];
840 vms_matrix rotmat,tempm;
842 // vm_extract_angles_matrix( &ang,&obj->orient);
852 vm_angles_2_matrix(&rotmat, &ang);
853 vm_matrix_x_matrix(&tempm, &obj->orient, &rotmat);
856 // vm_angles_2_matrix(&obj->orient, &ang);
858 Update_flags |= UF_WORLD_CHANGED;
864 void reset_object(short objnum)
866 object *obj = &Objects[objnum];
868 med_extract_matrix_from_segment(&Segments[obj->segnum],&obj->orient);
874 int ObjectResetObject()
876 reset_object(Cur_object_index);
878 Update_flags |= UF_WORLD_CHANGED;
884 int ObjectFlipObject()
886 vms_matrix *m=&Objects[Cur_object_index].orient;
888 vm_vec_negate(&m->uvec);
889 vm_vec_negate(&m->rvec);
891 Update_flags |= UF_WORLD_CHANGED;
896 int ObjectDecreaseBank() {return rotate_object(Cur_object_index, 0, -ROTATION_UNIT, 0);}
897 int ObjectIncreaseBank() {return rotate_object(Cur_object_index, 0, ROTATION_UNIT, 0);}
898 int ObjectDecreasePitch() {return rotate_object(Cur_object_index, -ROTATION_UNIT, 0, 0);}
899 int ObjectIncreasePitch() {return rotate_object(Cur_object_index, ROTATION_UNIT, 0, 0);}
900 int ObjectDecreaseHeading() {return rotate_object(Cur_object_index, 0, 0, -ROTATION_UNIT);}
901 int ObjectIncreaseHeading() {return rotate_object(Cur_object_index, 0, 0, ROTATION_UNIT);}
903 int ObjectDecreaseBankBig() {return rotate_object(Cur_object_index, 0, -(ROTATION_UNIT*4), 0);}
904 int ObjectIncreaseBankBig() {return rotate_object(Cur_object_index, 0, (ROTATION_UNIT*4), 0);}
905 int ObjectDecreasePitchBig() {return rotate_object(Cur_object_index, -(ROTATION_UNIT*4), 0, 0);}
906 int ObjectIncreasePitchBig() {return rotate_object(Cur_object_index, (ROTATION_UNIT*4), 0, 0);}
907 int ObjectDecreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, -(ROTATION_UNIT*4));}
908 int ObjectIncreaseHeadingBig() {return rotate_object(Cur_object_index, 0, 0, (ROTATION_UNIT*4));}
910 // -----------------------------------------------------------------------------------------------------
911 // Move object around based on clicks in 2d screen.
912 // Slide an object parallel to the 2d screen, to a point on a vector.
913 // The vector is defined by a point on the 2d screen and the eye.
915 // V = vector from eye to 2d screen point.
917 // F = forward vector from eye
918 // O = 3-space location of object
920 // D = depth of object given forward vector F
921 // = (OE dot norm(F))
923 // Must solve intersection of:
924 // E + tV ( equation of vector from eye through point on 2d screen)
925 // Fs + D ( equation of plane parallel to 2d screen, at depth D)
926 // = Fx(Ex + tVx) + Fy(Ey + tVy) + Fz(Ez + tVz) + D = 0
928 // FxEx + FyEy + FzEz - D
929 // t = - ----------------------
930 // VxFx + VyFy + VzFz
933 //void print_vec(vms_vector *vec, char *text)
935 // mprintf((0, "%10s = %9.5f %9.5f %9.5f\n", text, f2fl(vec->x), f2fl(vec->y), f2fl(vec->z)));
938 // void solve(vms_vector *result, vms_vector *E, vms_vector *V, vms_vector *O, vms_vector *F)
941 // vms_vector Fnorm, Vnorm;
943 // // float test_plane;
945 // print_vec(E, "E");
946 // print_vec(V, "V");
947 // print_vec(O, "O");
948 // print_vec(F, "F");
950 // Fnorm = *F; vm_vec_normalize(&Fnorm);
951 // Vnorm = *V; vm_vec_normalize(&Vnorm);
953 // D = (fixmul(O->x, Fnorm.x) + fixmul(O->y, Fnorm.y) + fixmul(O->z, Fnorm.z));
954 // mprintf((0, "D = %9.5f\n", f2fl(D)));
956 // num = fixmul(Fnorm.x, E->x) + fixmul(Fnorm.y, E->y) + fixmul(Fnorm.z, E->z) - D;
957 // denom = vm_vec_dot(&Vnorm, &Fnorm);
960 // mprintf((0, "num = %9.5f, denom = %9.5f, t = %9.5f\n", f2fl(num), f2fl(denom), f2fl(t)));
962 // result->x = E->x + fixmul(t, Vnorm.x);
963 // result->y = E->y + fixmul(t, Vnorm.y);
964 // result->z = E->z + fixmul(t, Vnorm.z);
966 // print_vec(result, "result");
968 // // test_plane = fixmul(result->x, Fnorm.x) + fixmul(result->y, Fnorm.y) + fixmul(result->z, Fnorm.z) - D;
969 // // if (abs(test_plane) > .001)
970 // // printf("OOPS: test_plane = %9.5f\n", test_plane);
973 void move_object_to_position(int objnum, vms_vector *newpos)
975 object *objp = &Objects[objnum];
977 segmasks result = get_seg_masks(newpos, objp->segnum, objp->size);
979 if (result.facemask == 0) {
980 //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)));
983 if (verify_object_seg(&Objects[objnum], newpos)) {
986 object temp_viewer_obj;
989 vms_vector last_outside_pos;
990 vms_vector last_inside_pos;
992 temp_viewer_obj = *Viewer;
993 viewer_segnum = find_object_seg(&temp_viewer_obj);
994 temp_viewer_obj.segnum = viewer_segnum;
996 // If the viewer is outside the mine, get him in the mine!
997 if (viewer_segnum == -1) {
998 // While outside mine, move towards object
1000 while (viewer_segnum == -1) {
1001 vms_vector temp_vec;
1003 //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)));
1004 last_outside_pos = temp_viewer_obj.pos;
1006 vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, newpos);
1007 temp_viewer_obj.pos = temp_vec;
1008 viewer_segnum = find_object_seg(&temp_viewer_obj);
1009 temp_viewer_obj.segnum = viewer_segnum;
1012 editor_status("Unable to move object, can't get viewer in mine. Aborting");
1018 // While inside mine, move away from object.
1019 while (viewer_segnum != -1) {
1021 vms_vector temp_vec;
1023 //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)));
1024 last_inside_pos = temp_viewer_obj.pos;
1026 vm_vec_avg(&temp_vec, &temp_viewer_obj.pos, &last_outside_pos);
1027 temp_viewer_obj.pos = temp_vec;
1028 update_object_seg(&temp_viewer_obj);
1029 viewer_segnum = find_object_seg(&temp_viewer_obj);
1030 temp_viewer_obj.segnum = viewer_segnum;
1033 editor_status("Unable to move object, can't get viewer back out of mine. Aborting");
1039 fq.p0 = &temp_viewer_obj.pos;
1040 fq.startseg = temp_viewer_obj.segnum;
1042 fq.rad = temp_viewer_obj.size;
1044 fq.ignore_obj_list = NULL;
1047 fate = find_vector_intersection(&fq,&hit_info);
1048 if (fate == HIT_WALL) {
1051 //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)));
1052 objp->pos = hit_info.hit_pnt;
1053 new_segnum = find_object_seg(objp);
1054 Assert(new_segnum != -1);
1055 obj_relink(objp-Objects, new_segnum);
1056 //mprintf((0, "Object moved from segment %i to %i\n", old_segnum, objp->segnum));
1058 editor_status("Attempted to move object out of mine. Object not moved.");
1059 //mprintf((0,"Attempted to move object out of mine. Object not moved."));
1064 Update_flags |= UF_WORLD_CHANGED;
1067 void move_object_to_vector(vms_vector *vec_through_screen, fix delta_distance)
1071 vm_vec_scale_add(&result, &Viewer->pos, vec_through_screen, vm_vec_dist(&Viewer->pos,&Objects[Cur_object_index].pos)+delta_distance);
1073 move_object_to_position(Cur_object_index, &result);
1077 void move_object_to_mouse_click_delta(fix delta_distance)
1080 vms_vector vec_through_screen;
1082 if (Cur_object_index == -1) {
1083 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1087 xcrd = GameViewBox->b1_drag_x1;
1088 ycrd = GameViewBox->b1_drag_y1;
1090 med_point_2_vec(&_canv_editor_game, &vec_through_screen, xcrd, ycrd);
1092 //mprintf((0, "Mouse click at %i %i, vector = %7.3f %7.3f %7.3f\n", xcrd, ycrd, f2fl(vec_through_screen.x), f2fl(vec_through_screen.y), f2fl(vec_through_screen.z)));
1094 move_object_to_vector(&vec_through_screen, delta_distance);
1098 void move_object_to_mouse_click(void)
1100 move_object_to_mouse_click_delta(0);
1103 int ObjectMoveNearer(void)
1107 if (Cur_object_index == -1) {
1108 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1112 // move_object_to_mouse_click_delta(-4*F1_0); // Move four units closer to eye
1114 vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
1115 vm_vec_normalize(&result);
1116 move_object_to_vector(&result, -4*F1_0);
1121 int ObjectMoveFurther(void)
1125 if (Cur_object_index == -1) {
1126 editor_status("Cur_object_index == -1, cannot move that peculiar object...aborting!");
1130 // move_object_to_mouse_click_delta(+4*F1_0); // Move four units further from eye
1132 vm_vec_sub(&result, &Objects[Cur_object_index].pos, &Viewer->pos);
1133 vm_vec_normalize(&result);
1134 move_object_to_vector(&result, 4*F1_0);