Revision: | 2.5 |

Committed: | Tue Mar 30 16:13:00 2004 UTC (19 years, 2 months ago) by schorsch |

Content type: | text/plain |

Branch: | MAIN |

CVS Tags: | rad3R7P2, rad5R0, rad4R2P2, rad4R2P1, rad3R7P1, rad4R2, rad4R1, rad4R0, rad3R6, rad3R6P1, rad3R8, rad3R9 |

Changes since 2.4: |
+1 -2 lines |

Log Message: | Continued ANSIfication. There are only bits and pieces left now. |

# | Content |
---|---|

1 | #ifndef lint |

2 | static const char RCSid[] = "$Id: sphere.c,v 2.4 2004/03/27 12:41:45 schorsch Exp $"; |

3 | #endif |

4 | /* |

5 | * sphere.c - routines for creating octrees for spheres. |

6 | * |

7 | * 7/28/85 |

8 | */ |

9 | |

10 | #include "standard.h" |

11 | |

12 | #include "octree.h" |

13 | |

14 | #include "object.h" |

15 | |

16 | #include "otypes.h" |

17 | |

18 | #define ROOT3 1.732050808 |

19 | |

20 | /* |

21 | * Regrettably, the algorithm for determining a cube's location |

22 | * with respect to a sphere is not simple. First, a quick test is |

23 | * made to determine if the sphere and the bounding sphere of the cube |

24 | * are disjoint. This of course means no intersection. Failing this, |

25 | * we determine if the cube lies inside the sphere. The cube is |

26 | * entirely inside if the bounding sphere on the cube is |

27 | * contained within our sphere. This means no intersection. Otherwise, |

28 | * if the cube radius is smaller than the sphere's and the cube center is |

29 | * inside the sphere, we assume intersection. If these tests fail, |

30 | * we proceed as follows. |

31 | * The sphere center is located in relation to the 6 cube faces, |

32 | * and one of four things is done depending on the number of |

33 | * planes the center lies between: |

34 | * |

35 | * 0: The sphere is closest to a cube corner, find the |

36 | * distance to that corner. |

37 | * |

38 | * 1: The sphere is closest to a cube edge, find this |

39 | * distance. |

40 | * |

41 | * 2: The sphere is closest to a cube face, find the distance. |

42 | * |

43 | * 3: The sphere has its center inside the cube. |

44 | * |

45 | * In cases 0-2, if the closest part of the cube is within |

46 | * the radius distance from the sphere center, we have intersection. |

47 | * If it is not, the cube must be outside the sphere. |

48 | * In case 3, there must be intersection, and no further |

49 | * tests are necessary. |

50 | */ |

51 | |

52 | |

53 | int |

54 | o_sphere( /* determine if sphere intersects cube */ |

55 | OBJREC *o, |

56 | register CUBE *cu |

57 | ) |

58 | { |

59 | FVECT v1; |

60 | double d1, d2; |

61 | register RREAL *fa; |

62 | register int i; |

63 | #define cent fa |

64 | #define rad fa[3] |

65 | /* get arguments */ |

66 | if (o->oargs.nfargs != 4) |

67 | objerror(o, USER, "bad # arguments"); |

68 | fa = o->oargs.farg; |

69 | if (rad < -FTINY) { |

70 | objerror(o, WARNING, "negative radius"); |

71 | o->otype = o->otype == OBJ_SPHERE ? |

72 | OBJ_BUBBLE : OBJ_SPHERE; |

73 | rad = -rad; |

74 | } else if (rad <= FTINY) |

75 | objerror(o, USER, "zero radius"); |

76 | |

77 | d1 = ROOT3/2.0 * cu->cusize; /* bounding radius for cube */ |

78 | |

79 | d2 = cu->cusize * 0.5; /* get distance between centers */ |

80 | for (i = 0; i < 3; i++) |

81 | v1[i] = cu->cuorg[i] + d2 - cent[i]; |

82 | d2 = DOT(v1,v1); |

83 | |

84 | if (d2 > (rad+d1+FTINY)*(rad+d1+FTINY)) /* quick test */ |

85 | return(O_MISS); /* cube outside */ |

86 | |

87 | /* check sphere interior */ |

88 | if (d1 < rad) { |

89 | if (d2 < (rad-d1-FTINY)*(rad-d1-FTINY)) |

90 | return(O_MISS); /* cube inside sphere */ |

91 | if (d2 < (rad+FTINY)*(rad+FTINY)) |

92 | return(O_HIT); /* cube center inside */ |

93 | } |

94 | /* find closest distance */ |

95 | for (i = 0; i < 3; i++) |

96 | if (cent[i] < cu->cuorg[i]) |

97 | v1[i] = cu->cuorg[i] - cent[i]; |

98 | else if (cent[i] > cu->cuorg[i] + cu->cusize) |

99 | v1[i] = cent[i] - (cu->cuorg[i] + cu->cusize); |

100 | else |

101 | v1[i] = 0; |

102 | /* final intersection check */ |

103 | if (DOT(v1,v1) <= (rad+FTINY)*(rad+FTINY)) |

104 | return(O_HIT); |

105 | else |

106 | return(O_MISS); |

107 | } |