| 130 | } |
| 131 | |
| 132 | void MiniGL::drawCylinder(const Vector3r &a, const Vector3r &b, const float *color, const float radius, const unsigned int subdivisions, const bool lighting) |
| 133 | { |
| 134 | Vector3f diffcolor(color); |
| 135 | Vector3f speccolor(1.0, 1.0, 1.0); |
| 136 | |
| 137 | // To simplify computations, the cylinder of height v is generated |
| 138 | // along the z axis from z=0 to z=v and then transformed to the axis ab. |
| 139 | Vector3r ab = b - a; |
| 140 | Real v = ab.norm(); |
| 141 | Eigen::Transform<Real, 3, Eigen::Affine> transform = |
| 142 | Eigen::Translation<Real, 3>(a) * |
| 143 | Quaternionr::FromTwoVectors(Vector3r(0.0, 0.0, v), ab); |
| 144 | Vector3r xMid = transform * Vector3r(0.0, 0.0, 0.5 * v); |
| 145 | |
| 146 | // Both the lateral surface and the base disks are subdivided into n slices (cf. gluCylinder & gluDisk). |
| 147 | // For this purpose, the base circle is parametrized as a function of the angle theta. |
| 148 | // The lateral slices are again subdivided into two triangles each for rendering. |
| 149 | // Smooth normals are obtained by going outward from the midpoint. |
| 150 | unsigned int n = subdivisions; |
| 151 | VectorXr vertices((n+1) * 2 * 3); |
| 152 | VectorXr normals((n+1) * 2 * 3); |
| 153 | std::vector<unsigned int> faces; |
| 154 | unsigned int iMidBottom = 2 * n; |
| 155 | unsigned int iMidTop = 2 * n + 1; |
| 156 | for (unsigned int i = 0; i < n; i++) |
| 157 | { |
| 158 | Real theta = (Real)i / (Real)n * 2.0 * M_PI; |
| 159 | Vector3r x(radius * cos(theta), radius * sin(theta), 0.0); |
| 160 | Vector3r xBottom = transform * x; |
| 161 | x(2) = v; |
| 162 | Vector3r xTop = transform * x; |
| 163 | vertices.segment<3>(2 * 3 * i) = xBottom; |
| 164 | vertices.segment<3>(2 * 3 * i + 3) = xTop; |
| 165 | normals.segment<3>(2 * 3 * i) = (xBottom - xMid).normalized(); |
| 166 | normals.segment<3>(2 * 3 * i + 3) = (xTop - xMid).normalized(); |
| 167 | |
| 168 | // [TESSELLATION] |
| 169 | // iMidTop |
| 170 | // / \ |
| 171 | // iTop ---- iNextTop |
| 172 | // | \ | |
| 173 | // | \ | |
| 174 | // iBottom - iNextBottom |
| 175 | // \ / |
| 176 | // iMidBottom |
| 177 | unsigned int iBottom = 2 * i; |
| 178 | unsigned int iTop = 2 * i + 1; |
| 179 | unsigned int iNextBottom = (2 * (i+1)) % (2 * n); |
| 180 | unsigned int iNextTop = (2 * (i+1) + 1) % (2 * n); |
| 181 | faces.insert(faces.end(), {iTop, iNextTop, iMidTop}); |
| 182 | faces.insert(faces.end(), {iBottom, iNextBottom, iTop}); |
| 183 | faces.insert(faces.end(), {iTop, iNextBottom, iNextTop}); |
| 184 | faces.insert(faces.end(), {iBottom, iMidBottom, iNextBottom}); |
| 185 | } |
| 186 | Vector3r xMidBottom = transform * Vector3r(0.0, 0.0, 0.0); |
| 187 | Vector3r xMidTop = transform * Vector3r(0.0, 0.0, v); |
| 188 | vertices.segment<3>(3 * iMidBottom) = xMidBottom; |
| 189 | vertices.segment<3>(3 * iMidTop) = xMidTop; |
nothing calls this directly
no test coverage detected