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;
}
Example #4
0
    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;
    }