static void debugDrawAllBatches(const btBatchedConstraints* bc, btConstraintArray* constraints, const btAlignedObjectArray<btSolverBody>& bodies) { BT_PROFILE("debugDrawAllBatches"); if (bc && bc->m_debugDrawer && bc->m_phases.size() > 0) { btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT); btVector3 bboxMax = -bboxMin; for (int iBody = 0; iBody < bodies.size(); ++iBody) { const btVector3& pos = bodies[iBody].getWorldTransform().getOrigin(); bboxMin.setMin(pos); bboxMax.setMax(pos); } btVector3 bboxExtent = bboxMax - bboxMin; btVector3 offsetBase = btVector3(0, bboxExtent.y() * 1.1f, 0); btVector3 offsetStep = btVector3(0, 0, bboxExtent.z() * 1.1f); int numPhases = bc->m_phases.size(); for (int iPhase = 0; iPhase < numPhases; ++iPhase) { float b = float(iPhase) / float(numPhases - 1); btVector3 color0 = btVector3(1, 0, b); btVector3 color1 = btVector3(0, 1, b); btVector3 offset = offsetBase + offsetStep * (float(iPhase) - float(numPhases - 1) * 0.5); debugDrawPhase(bc, constraints, bodies, iPhase, color0, color1, offset); } } }
void SoftwareRasterizer::rasterizeTriangle(const Vec4* tri) { ANKI_ASSERT(tri); const Vec2 windowSize(m_width, m_height); Array<Vec3, 3> ndc; Array<Vec2, 3> window; Vec2 bboxMin(MAX_F32), bboxMax(MIN_F32); for(U i = 0; i < 3; i++) { ndc[i] = tri[i].xyz() / tri[i].w(); window[i] = (ndc[i].xy() / 2.0 + 0.5) * windowSize; for(U j = 0; j < 2; j++) { bboxMin[j] = floor(min(bboxMin[j], window[i][j])); bboxMin[j] = clamp(bboxMin[j], 0.0f, windowSize[j]); bboxMax[j] = ceil(max(bboxMax[j], window[i][j])); bboxMax[j] = clamp(bboxMax[j], 0.0f, windowSize[j]); } } for(F32 y = bboxMin.y() + 0.5; y < bboxMax.y() + 0.5; y += 1.0) { for(F32 x = bboxMin.x() + 0.5; x < bboxMax.x() + 0.5; x += 1.0) { Vec2 p(x, y); Vec3 bc; if(!computeBarycetrinc(window[0], window[1], window[2], p, bc)) { const F32 z0 = ndc[0].z(); const F32 z1 = ndc[1].z(); const F32 z2 = ndc[2].z(); F32 depth = z0 * bc[0] + z1 * bc[1] + z2 * bc[2]; ANKI_ASSERT(depth >= 0.0 && depth <= 1.0); // Clamp it to a bit less that 1.0f because 1.0f will produce a 0 depthi depth = min(depth, 1.0f - EPSILON); // Store the min of the current value and new one const U32 depthi = depth * MAX_U32; m_zbuffer[U(y) * m_width + U(x)].min(depthi); } } } }
Bool SoftwareRasterizer::visibilityTestInternal(const Aabb& aabb) const { // Set the AABB points const Vec4& minv = aabb.getMin(); const Vec4& maxv = aabb.getMax(); Array<Vec4, 8> boxPoints; boxPoints[0] = minv.xyz1(); boxPoints[1] = Vec4(minv.x(), maxv.y(), minv.z(), 1.0f); boxPoints[2] = Vec4(minv.x(), maxv.y(), maxv.z(), 1.0f); boxPoints[3] = Vec4(minv.x(), minv.y(), maxv.z(), 1.0f); boxPoints[4] = maxv.xyz1(); boxPoints[5] = Vec4(maxv.x(), minv.y(), maxv.z(), 1.0f); boxPoints[6] = Vec4(maxv.x(), minv.y(), minv.z(), 1.0f); boxPoints[7] = Vec4(maxv.x(), maxv.y(), minv.z(), 1.0f); // Transform points for(Vec4& p : boxPoints) { p = m_mvp * p; } // Check of a point touches the near plane for(const Vec4& p : boxPoints) { if(p.w() <= 0.0f) { // Don't bother clipping. Just mark it as visible. return true; } } // Compute the min and max bounds Vec4 bboxMin(MAX_F32); Vec4 bboxMax(MIN_F32); for(Vec4& p : boxPoints) { // Perspecrive divide p /= p.w(); // To [0, 1] p *= Vec4(0.5f, 0.5f, 1.0f, 1.0f); p += Vec4(0.5f, 0.5f, 0.0f, 0.0f); // To [0, m_width|m_height] p *= Vec4(m_width, m_height, 1.0f, 1.0f); // Min bboxMin = bboxMin.min(p); // Max bboxMax = bboxMax.max(p); } // Fix the bounds bboxMin.x() = floorf(bboxMin.x()); bboxMin.x() = clamp(bboxMin.x(), 0.0f, F32(m_width)); bboxMax.x() = ceilf(bboxMax.x()); bboxMax.x() = clamp(bboxMax.x(), 0.0f, F32(m_width)); bboxMin.y() = floorf(bboxMin.y()); bboxMin.y() = clamp(bboxMin.y(), 0.0f, F32(m_height)); bboxMax.y() = ceilf(bboxMax.y()); bboxMax.y() = clamp(bboxMax.y(), 0.0f, F32(m_height)); // Loop the tiles F32 minZ = bboxMin.z(); for(U y = bboxMin.y(); y < bboxMax.y(); y += 1.0f) { for(U x = bboxMin.x(); x < bboxMax.x(); x += 1.0f) { U idx = U(y) * m_width + U(x); U32 depthi = m_zbuffer[idx].get(); F32 depthf = depthi / F32(MAX_U32); if(minZ < depthf) { return true; } } } return false; }
EGS_OCTREE_EXPORT EGS_BaseGeometry *createGeometry(EGS_Input *input) { EGS_Input *i; // check that we have an input if (!input) { egsWarning(eoctree_message1,eoctree_message2); return 0; } // read bounding boxes vector<EGS_Octree_bbox> vBox; while (i = input->takeInputItem(eoctree_key0)) { // read the bounding box minimum vector<EGS_Float> v; int err = i->getInput(eoctree_key1, v); if (err) { egsWarning(eoctree_message1, eoctree_message5); return 0; } if (v.size() != 3) { egsWarning(eoctree_message1, eoctree_message6); return 0; } EGS_Vector bboxMin(v[0],v[1],v[2]); // read the bounding box maximum err = i->getInput(eoctree_key2, v); if (err) { egsWarning(eoctree_message1, eoctree_message7); return 0; } if (v.size() != 3) { egsWarning(eoctree_message1, eoctree_message8); return 0; } EGS_Vector bboxMax(v[0],v[1],v[2]); // read the bounding box resolution vector<int> bboxRes; err = i->getInput(eoctree_key3, bboxRes); if (err) { egsWarning(eoctree_message1, eoctree_message9); return 0; } if (bboxRes.size() != 3) { egsWarning(eoctree_message1, eoctree_message10); return 0; } EGS_Octree_bbox box = EGS_Octree_bbox(bboxMin, bboxMax, bboxRes); vBox.push_back(box); } if (vBox.size() < 1) { egsWarning(eoctree_message1, eoctree_message15); return 0; } // read discard child option bool discardChild = true; string discard; if (input->getInputItem(eoctree_key5)) { int err = input->getInput(eoctree_key5, discard); if (err) { egsWarning(eoctree_message1, eoctree_message11); return 0; } if (discard.find("yes")==string::npos && discard.find("no")==string::npos) { egsWarning(eoctree_message1, eoctree_message12); return 0; } if (discard.find("no")!=string::npos) { discardChild = false; } } // read prune tree option bool pruneTree = true; string prune; if (input->getInputItem(eoctree_key6)) { int err = input->getInput(eoctree_key6, prune); if (err) { egsWarning(eoctree_message1, eoctree_message16); return 0; } if (prune.find("yes")==string::npos && prune.find("no")==string::npos) { egsWarning(eoctree_message1, eoctree_message17); return 0; } if (prune.find("no")!=string::npos) { pruneTree = false; } } // read and load the child geometry string gname; { int err = input->getInput(eoctree_key4, gname); if (err) { egsWarning(eoctree_message1, eoctree_message13); return 0; } } EGS_BaseGeometry *g = EGS_BaseGeometry::getGeometry(gname); if (!g) { egsWarning(eoctree_message1, eoctree_message14); return 0; } // create the octree geometry EGS_Octree *octree = new EGS_Octree(vBox, pruneTree, g); octree->setName(input); octree->setLabels(input); octree->printInfo(); if (discardChild) { delete g; } return octree; }