Revision: | 2.6 |

Committed: | Wed Apr 20 18:51:35 2016 UTC (8 years, 6 months ago) by greg |

Content type: | text/plain |

Branch: | MAIN |

CVS Tags: | rad5R4, rad5R2, rad5R1, rad5R3, HEAD |

Changes since 2.5: |
+8 -6 lines |

Log Message: | Changed zero-radius sphere from error to warning |

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

1 | #ifndef lint |

2 | static const char RCSid[] = "$Id: sphere.c,v 2.5 2004/03/30 16:13:00 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 | CUBE *cu |

57 | ) |

58 | { |

59 | FVECT v1; |

60 | double d1, d2; |

61 | RREAL *fa; |

62 | 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, WARNING, "zero radius"); |

76 | return(O_MISS); |

77 | } |

78 | |

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

80 | |

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

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

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

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

85 | |

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

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

88 | |

89 | /* check sphere interior */ |

90 | if (d1 < rad) { |

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

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

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

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

95 | } |

96 | /* find closest distance */ |

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

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

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

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

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

102 | else |

103 | v1[i] = 0; |

104 | /* final intersection check */ |

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

106 | return(O_HIT); |

107 | else |

108 | return(O_MISS); |

109 | } |