void mbChargeLattice::genEdge(mbLatticeCube *cube, int edgeIndex, int pointIndex, int pointIndex2) { mbLatticeEdge *edge = cube->edges[edgeIndex]; mbVector3D interpolationResult, normalResult; float *position = edge->position; if (edge->lastFrameVisited != currentFrame) { edge->lastFrameVisited = currentFrame; interpolationResult = interpolateEdge(cube->points[pointIndex], cube->points[pointIndex2], edge->axis); position[0] = interpolationResult.x; position[1] = interpolationResult.y; position[2] = interpolationResult.z; edge->vertexIndex = vertexCount; normalResult = calcNormal(interpolationResult); int realLocation = 3 * vertexCount; meshNormals[realLocation] = normalResult.x; meshVertices[realLocation] = interpolationResult.x; meshNormals[realLocation+1] = normalResult.y; meshVertices[realLocation+1] = interpolationResult.y; meshNormals[realLocation+2] = normalResult.z; meshVertices[realLocation+2] = interpolationResult.z; vertexCount++; } };
void ScanConverter::operator()(const acl::Object<> &object, const acl::Triangle<> &triangle) { // get triangle vertex positions const acl::Vertex<> &v1 = triangle.getVertex(object.getMesh(), 0); const acl::Vertex<> &v2 = triangle.getVertex(object.getMesh(), 1); const acl::Vertex<> &v3 = triangle.getVertex(object.getMesh(), 2); acl::Matrix<1, 4> vpos[] = { v1.getPositionInScreen(), v2.getPositionInScreen(), v3.getPositionInScreen() }; // clip triangle if behind the camera if(clip && (vpos[0][2] >= 0 || vpos[1][2] >= 0 || vpos[2][2] >= 0)) return; // perform perspective divide for(int i = 0; i < 3; i++) { vpos[i][0] /= vpos[i][3]; vpos[i][1] /= vpos[i][3]; } // sort vertices from lowest to highest by y coordinate int index[] = {0, 1, 2}; if(vpos[index[0]][1] > vpos[index[1]][1]) {std::swap(index[0], index[1]);} if(vpos[index[1]][1] > vpos[index[2]][1]) {std::swap(index[1], index[2]);} if(vpos[index[0]][1] > vpos[index[1]][1]) {std::swap(index[0], index[1]);} // clip triangle if less than one pixel tall const int yminscreen = std::max(static_cast<int>(vpos[index[0]][1]), 0); const int ymaxscreen = std::min(static_cast<int>(vpos[index[2]][1]), frameBuffer.height()); if(ymaxscreen <= yminscreen) return; // calculate triangle vertex lighting and set pixel properties acl::Color<> vertexColors[3]; calculateVertexLighting(object, triangle, vertexColors); const Pixel pixels[] = { {vpos[0], v1.getPositionInWorld(), v1.getNormalInWorld(), triangle.getVertexMaterial(object, 0), vertexColors[0]}, {vpos[1], v2.getPositionInWorld(), v2.getNormalInWorld(), triangle.getVertexMaterial(object, 1), vertexColors[1]}, {vpos[2], v3.getPositionInWorld(), v3.getNormalInWorld(), triangle.getVertexMaterial(object, 2), vertexColors[2]} }; // interpolate along edges edgePairs.resize(frameBuffer.height()); interpolateEdge(pixels[index[0]], pixels[index[2]], true); interpolateEdge(pixels[index[0]], pixels[index[1]], false); interpolateEdge(pixels[index[1]], pixels[index[2]], false); // scan convert and interpolate between x coordinate pairs for(int y = yminscreen; y < ymaxscreen; y++) { const EdgePair &edgePair = edgePairs[y]; const int xleft = static_cast<int>(edgePair.left.positionInScreen[0]); const int xright = static_cast<int>(edgePair.right.positionInScreen[0]); const int xleftscreen = std::max(xleft, 0); const int xrightscreen = std::min(xright, frameBuffer.width()); for(int x = xleftscreen; x < xrightscreen; x++) { const double t = static_cast<double>(x - xleft) / (xright - xleft); const Pixel interpPixel = edgePair.left.interpolate(edgePair.right, t, shading); const acl::Color<> color = (shading == Shading::Phong) ? calculateLighting(interpPixel) : interpPixel.color; frameBuffer.blendPixel(x, y, interpPixel.positionInScreen[2], color.alpha(), color); } } }