1 | /* |
---|---|

2 | --------------------------------------------------------------------------- |

3 | Open Asset Import Library (assimp) |

4 | --------------------------------------------------------------------------- |

5 | |

6 | Copyright (c) 2006-2012, assimp team |

7 | |

8 | All rights reserved. |

9 | |

10 | Redistribution and use of this software in source and binary forms, |

11 | with or without modification, are permitted provided that the following |

12 | conditions are met: |

13 | |

14 | * Redistributions of source code must retain the above |

15 | copyright notice, this list of conditions and the |

16 | following disclaimer. |

17 | |

18 | * Redistributions in binary form must reproduce the above |

19 | copyright notice, this list of conditions and the |

20 | following disclaimer in the documentation and/or other |

21 | materials provided with the distribution. |

22 | |

23 | * Neither the name of the assimp team, nor the names of its |

24 | contributors may be used to endorse or promote products |

25 | derived from this software without specific prior |

26 | written permission of the assimp team. |

27 | |

28 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |

29 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |

30 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |

31 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |

32 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |

33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |

34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |

35 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |

36 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |

37 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |

38 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |

39 | --------------------------------------------------------------------------- |

40 | */ |

41 | |

42 | /** @file Generation of normal vectors basing on smoothing groups */ |

43 | |

44 | #ifndef AI_SMOOTHINGGROUPS_INL_INCLUDED |

45 | #define AI_SMOOTHINGGROUPS_INL_INCLUDED |

46 | |

47 | // internal headers |

48 | #include "SGSpatialSort.h" |

49 | |

50 | // CRT header |

51 | #include <algorithm> |

52 | |

53 | using namespace Assimp; |

54 | |

55 | // ------------------------------------------------------------------------------------------------ |

56 | template <class T> |

57 | void ComputeNormalsWithSmoothingsGroups(MeshWithSmoothingGroups<T>& sMesh) |

58 | { |

59 | // First generate face normals |

60 | sMesh.mNormals.resize(sMesh.mPositions.size(),aiVector3D()); |

61 | for( unsigned int a = 0; a < sMesh.mFaces.size(); a++) |

62 | { |

63 | T& face = sMesh.mFaces[a]; |

64 | |

65 | aiVector3D* pV1 = &sMesh.mPositions[face.mIndices[0]]; |

66 | aiVector3D* pV2 = &sMesh.mPositions[face.mIndices[1]]; |

67 | aiVector3D* pV3 = &sMesh.mPositions[face.mIndices[2]]; |

68 | |

69 | aiVector3D pDelta1 = *pV2 - *pV1; |

70 | aiVector3D pDelta2 = *pV3 - *pV1; |

71 | aiVector3D vNor = pDelta1 ^ pDelta2; |

72 | |

73 | for (unsigned int c = 0; c < 3;++c) |

74 | sMesh.mNormals[face.mIndices[c]] = vNor; |

75 | } |

76 | |

77 | // calculate the position bounds so we have a reliable epsilon to check position differences against |

78 | aiVector3D minVec( 1e10f, 1e10f, 1e10f), maxVec( -1e10f, -1e10f, -1e10f); |

79 | for( unsigned int a = 0; a < sMesh.mPositions.size(); a++) |

80 | { |

81 | minVec.x = std::min( minVec.x, sMesh.mPositions[a].x); |

82 | minVec.y = std::min( minVec.y, sMesh.mPositions[a].y); |

83 | minVec.z = std::min( minVec.z, sMesh.mPositions[a].z); |

84 | maxVec.x = std::max( maxVec.x, sMesh.mPositions[a].x); |

85 | maxVec.y = std::max( maxVec.y, sMesh.mPositions[a].y); |

86 | maxVec.z = std::max( maxVec.z, sMesh.mPositions[a].z); |

87 | } |

88 | const float posEpsilon = (maxVec - minVec).Length() * 1e-5f; |

89 | std::vector<aiVector3D> avNormals; |

90 | avNormals.resize(sMesh.mNormals.size()); |

91 | |

92 | // now generate the spatial sort tree |

93 | SGSpatialSort sSort; |

94 | for( typename std::vector<T>::iterator i = sMesh.mFaces.begin(); |

95 | i != sMesh.mFaces.end();++i) |

96 | { |

97 | for (unsigned int c = 0; c < 3;++c) |

98 | sSort.Add(sMesh.mPositions[(*i).mIndices[c]],(*i).mIndices[c],(*i).iSmoothGroup); |

99 | } |

100 | sSort.Prepare(); |

101 | |

102 | std::vector<bool> vertexDone(sMesh.mPositions.size(),false); |

103 | for( typename std::vector<T>::iterator i = sMesh.mFaces.begin(); |

104 | i != sMesh.mFaces.end();++i) |

105 | { |

106 | std::vector<unsigned int> poResult; |

107 | for (unsigned int c = 0; c < 3;++c) |

108 | { |

109 | unsigned int idx = (*i).mIndices[c]; |

110 | if (vertexDone[idx])continue; |

111 | |

112 | sSort.FindPositions(sMesh.mPositions[idx],(*i).iSmoothGroup, |

113 | posEpsilon,poResult); |

114 | |

115 | aiVector3D vNormals; |

116 | for (std::vector<unsigned int>::const_iterator |

117 | a = poResult.begin(); |

118 | a != poResult.end();++a) |

119 | { |

120 | vNormals += sMesh.mNormals[(*a)]; |

121 | } |

122 | vNormals.NormalizeSafe(); |

123 | |

124 | // write back into all affected normals |

125 | for (std::vector<unsigned int>::const_iterator |

126 | a = poResult.begin(); |

127 | a != poResult.end();++a) |

128 | { |

129 | idx = *a; |

130 | avNormals [idx] = vNormals; |

131 | vertexDone[idx] = true; |

132 | } |

133 | } |

134 | } |

135 | sMesh.mNormals = avNormals; |

136 | } |

137 | |

138 | #endif // !! AI_SMOOTHINGGROUPS_INL_INCLUDED |

139 |