OSP Code Optimisation Tidbit Tuesday: script_point_y_toward_position

Currently viewing this thread:

Probably the most useful utility I've written for M&B, this basic arc_* script goes a step further and rotates a position to point at another position. In M&B, pointing is done with the positive side of the y-axis (imagine that as the nose of an airplane) with the positive x-axis on the right. This script has moved a couple generations past the Brytenwalda version. It now works more efficiently with the atan2 function and rotates in three dimensions.

Code:
  # script_point_y_toward_position by motomataru
  # Input: from position, to position
  # Output: reg0 distance in cm
  # Basically, points the first position at the second, so then simple move_y will move back and forth and move_x side to side
  ("point_y_toward_position", [
	(store_script_param, ":from_position", 1),
	(store_script_param, ":to_position", 2),
	(assign, ":save_fpm", 1),
	(convert_to_fixed_point, ":save_fpm"),
	(set_fixed_point_multiplier, 100),  #to match cm returned by get_distance_between_positions
	
	#remove current rotation
	(position_get_x, ":from_x", ":from_position"),
	(position_get_y, ":from_y", ":from_position"),
	(position_get_z, ":from_z", ":from_position"),
	(init_position, ":from_position"),
	(position_set_x, ":from_position", ":from_x"),
	(position_set_y, ":from_position", ":from_y"),
	(position_set_z, ":from_position", ":from_z"),
	
	#horizontal rotation
	(position_get_x, ":change_in_x", ":to_position"),
	(val_sub, ":change_in_x", ":from_x"),
	(position_get_y, ":change_in_y", ":to_position"),
	(val_sub, ":change_in_y", ":from_y"),
	
	(try_begin),
		(this_or_next|neq, ":change_in_y", 0),
		(neq, ":change_in_x", 0),
		(store_atan2, ":theta", ":change_in_y", ":change_in_x"),
		(assign, ":ninety", 90),
		(convert_to_fixed_point, ":ninety"),
		(val_sub, ":theta", ":ninety"),	#point Y axis at to position
		(position_rotate_z_floating, ":from_position", ":theta"),
	(try_end),
	
	#vertical rotation
	(get_distance_between_positions, ":distance_between", ":from_position", ":to_position"),
	(try_begin),
		(gt, ":distance_between", 0),
		(position_get_z, ":dist_z_to_sine", ":to_position"),
		(val_sub, ":dist_z_to_sine", ":from_z"),
		(val_div, ":dist_z_to_sine", ":distance_between"),
		(store_asin, ":theta", ":dist_z_to_sine"),
		(position_rotate_x_floating, ":from_position", ":theta"),
	(try_end),
	
	(assign, reg0, ":distance_between"),
	(set_fixed_point_multiplier, ":save_fpm"),
  ]),

Applications are very easy:

1. Have one team's division attack an enemy division (I call the group identified by team and division a "battlegroup").

Code:
	(get_distance_between_positions, ":distance_to_move", ":bgposition", Enemy_Team_Pos),
	
	<lots of tweaking>
	
	(call_script, "script_point_y_toward_position", ":bgposition", Enemy_Team_Pos),
	(position_move_y, ":bgposition", ":distance_to_move"),

2. Pick the spot in a scene underneath the mouse.

Code:
 (mouse_get_world_projection, pos1, pos2),
 (call_script, "script_point_y_toward_position", pos1, pos2),
 (cast_ray, ":prop_id", pos3, pos1),

  <lot of stuff to handle anomalies at scene boundaries>
 

Vetrogor

Sergeant at Arms
There is a bug in the vertical X-rotation.
Python:
  # script_point_y_toward_position by motomataru
  # Input: from position, to position
  # Output: reg0 distance in cm
  # Basically, points the first position at the second, so then simple move_y
  # will move back and forth and move_x side to side
  # Things like cast_ray work with this as well
  ("point_y_toward_position", [
      (store_script_param, ":from_position", 1),
      (store_script_param, ":to_position", 2),
      (assign, ":save_fpm", 1),
      (convert_to_fixed_point, ":save_fpm"),
      (set_fixed_point_multiplier, 100),  #to match cm returned by get_distance_between_positions
    
      #remove current rotation
      (position_get_x, ":from_x", ":from_position"),
      (position_get_y, ":from_y", ":from_position"),
      (position_get_z, ":from_z", ":from_position"),
      (init_position, ":from_position"),
      (position_set_x, ":from_position", ":from_x"),
      (position_set_y, ":from_position", ":from_y"),
      (position_set_z, ":from_position", ":from_z"),
    
      #horizontal rotation - Yaw
      (position_get_x, ":change_in_x", ":to_position"),
      (val_sub, ":change_in_x", ":from_x"),
      (position_get_y, ":change_in_y", ":to_position"),
      (val_sub, ":change_in_y", ":from_y"),
    
      (try_begin),
        (this_or_next | neq, ":change_in_y", 0),
        (neq, ":change_in_x", 0),
        (store_atan2, ":theta", ":change_in_y", ":change_in_x"),
        (assign, ":ninety", 90),
        (convert_to_fixed_point, ":ninety"),
        (val_sub, ":theta", ":ninety"), #point Y axis at to position
        (position_rotate_z_floating, ":from_position", ":theta"),
      (try_end),
    
      #vertical rotation - Roll
      (get_distance_between_positions, ":distance_between", ":from_position", ":to_position"),
      (try_begin),
        (gt, ":distance_between", 0),
        (position_get_z, ":dist_z_to_sine", ":to_position"),
        (val_sub, ":dist_z_to_sine", ":from_z"),
        (val_mul, ":dist_z_to_sine", 100),
        (val_div, ":dist_z_to_sine", ":distance_between"),
        (store_asin, ":theta", ":dist_z_to_sine"),
        (position_rotate_x_floating, ":from_position", ":theta"),
      (try_end),
    
      (assign, reg0, ":distance_between"),
      (set_fixed_point_multiplier, ":save_fpm"),]),
 
Top Bottom