예제 #1
0
	unsigned int getPixel(GCamera& camera, int x, int y, double* pZ)
	{
		// Compute the ray vector
		G3DVector ray;
		camera.computeRayDirection(x, y, &ray);

		// Compute the intersection with the billboard plane
		double denom = m_face.dotProduct(&ray);
		if(std::abs(denom) < 1e-12)
		{
			*pZ = -1e200;
			return 0; // ray runs parallel to the plane
		}
		G3DVector t(m_pCorners[0]);
		t.subtract(camera.lookFromPoint());
		double d = m_face.dotProduct(&t) / denom;
		*pZ = d;
		if(d < 0)
			return 0; // the intersection is behind the camera
		ray.multiply(d);
		ray.add(camera.lookFromPoint());
		ray.subtract(m_pCorners[0]);

		// Compute the image coordinates
		int xx = (int)floor(ray.dotProduct(&m_bb.m_x) * m_pixelsX / m_squaredMagX + 0.5);
		int yy = (int)floor(ray.dotProduct(&m_bb.m_y) * m_pixelsY / m_squaredMagY + 0.5);

		// Get the pixel
		if(xx < 0 || yy < 0 || xx >= m_pixelsX || yy >= m_pixelsY)
			return 0;
		return m_bb.m_pImage->pixel(xx % m_bb.m_pImage->width(), m_bb.m_pImage->height() - 1 - (yy % m_bb.m_pImage->height()));
	}
예제 #2
0
void GBillboardWorld::draw(GImage* pImage, double* pDepthMap, GCamera& camera)
{
	G3DVector coords[VERTEX_COUNT + 1];
	int coordMap[VERTEX_COUNT + 1];
	for(size_t i = 0; i < pImage->width() * pImage->height(); i++)
		pDepthMap[i] = 1e200;
	for(vector<GBillboard*>::iterator it = m_billboards.begin(); it != m_billboards.end(); it++)
	{
		// Project each of the corners onto the view
		GBBAugmented bb(**it);
		int gap = -1;
		int coordCount = 0;
		for(int i = 0; i < VERTEX_COUNT; i++)
		{
			camera.project(bb.m_pCorners[i], &coords[coordCount]);
			if(coords[coordCount].m_vals[2] > 0.0)
				coordMap[coordCount++] = i;
			else if(gap < 0)
			{
				gap = coordCount;
				coordCount = gap + 2;
			}
		}

		// Fudge the gap due to vertices that are behind the camera
		if(gap >= 0)
		{
			if(coordCount == 0)
				continue; // Nothing to draw

			// Fudge the vertex that follows the chain of valid vertices
			G3DVector tmp;
			G3DVector tmp2;
			int indexValid = coordMap[(gap + coordCount - 1) % coordCount]; // The corner just before the gap
			int indexFudge = (indexValid + 1) % VERTEX_COUNT; // The first corner that was behind the camera
			tmp.copy(bb.m_pCorners[indexValid]);
			tmp.subtract(bb.m_pCorners[indexFudge]);
			tmp2.copy(camera.lookFromPoint());
			tmp2.subtract(bb.m_pCorners[indexFudge]);
			double d = (1e-6 + tmp2.dotProduct(camera.lookDirection())) / tmp.dotProduct(camera.lookDirection());
			tmp.multiply(d);
			tmp.add(bb.m_pCorners[indexFudge]);
			camera.project(&tmp, &coords[gap]);

			// Fudge the vertex that precedes the chain of valid vertices
			indexValid = coordMap[(gap + 2) % coordCount]; // The corner just after the gap
			indexFudge = (indexValid + VERTEX_COUNT - 1) % VERTEX_COUNT; // The last corner that was behind the camera
			tmp.copy(bb.m_pCorners[indexValid]);
			tmp.subtract(bb.m_pCorners[indexFudge]);
			tmp2.copy(camera.lookFromPoint());
			tmp2.subtract(bb.m_pCorners[indexFudge]);
			d = (1e-6 + tmp2.dotProduct(camera.lookDirection())) / tmp.dotProduct(camera.lookDirection());
			tmp.multiply(d);
			tmp.add(bb.m_pCorners[indexFudge]);
			camera.project(&tmp, &coords[gap + 1]);
		}

		// Find the starting point (which is the lowest coordinate in the view)
		int a = 0;
		for(int i = 1; i < coordCount; i++)
		{
			if(coords[i].m_vals[1] < coords[a].m_vals[1])
				a = i;
		}
		int b = a;

		// Find the left and right order in which the corners will be visted (bottom to top)
		while(true)
		{
			int c = (b + 1) % coordCount;
			if(a == c)
				break;
			int d = (a + coordCount - 1) % coordCount;
			drawSection(pImage, pDepthMap, camera, bb, &coords[a], &coords[b], &coords[c], &coords[d]);
			if(coords[d].m_vals[1] < coords[c].m_vals[1])
				a = d;
			else
				b = c;
		}
	}
}