⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 q3bsp.cpp

📁 Torus 3D Engine is an open-source OpenGL ES 3D Engine for creating your own games in BREW environmen
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	}

	DeletePtr(pTga);

	return TRUE;
}


//
// Load lightvols
//
boolean CQ3BSP::LoadLightvols(direntry* pEntry)
{
	m_dwLightvolCount = pEntry->iLength / sizeof(lightvol_lump);
	m_pLightvols = new lightvol_lump[m_dwLightvolCount];

	// read the lump
	m_pVfs->SeekTo(pEntry->iOffset);
	m_pVfs->Read(m_pLightvols, sizeof(lightvol_lump) * m_dwLightvolCount);

	return TRUE;
}


//
// Load visdata
//
boolean CQ3BSP::LoadVisdata(direntry* pEntry)
{
	// read the lump start
	m_pVfs->SeekTo(pEntry->iOffset);
	m_pVfs->Read(&m_Visdata, 2 * sizeof(int));

	m_dwVisdataCount = m_Visdata.iVectorCount * m_Visdata.iVectorSize;
	m_Visdata.pjVecs = new byte[m_dwVisdataCount];

	// read the rest of the lump
	m_pVfs->Read(m_Visdata.pjVecs, m_dwVisdataCount);

	return TRUE;
}


//
// Parse the mapinfo string
//
void CQ3BSP::ParseMapInfo(char *szInfo)
{
	#define TOKEN_SIZE		64
	#define MAX_CLASSES		20
	#define CLASS_LENGTH	128

	char* szClasses = new char[MAX_CLASSES * CLASS_LENGTH];
	memset(szClasses, 0, MAX_CLASSES * CLASS_LENGTH);
	WORD wClassCount = 0;

	char c = 0;												// current character
	DWORD p = 0;											// string position

	char szToken[TOKEN_SIZE];					// current token
	WORD t = 0;												// token length
	memset(szToken, 0, TOKEN_SIZE);		// clear token

	//
	// Convert the classes into the [MAX_CLASSES][128] format
	//

	while (szInfo[p])
	{
		c = szInfo[p];

		if (c == '{')
		{
			// new class
			p++;
			DWORD dwPos = wClassCount * CLASS_LENGTH;
			while (szInfo[p] != '}') szClasses[dwPos++] = szInfo[p++];
			wClassCount++;
		}

		p++;
	}

	//
	// Now scan each class and parses tokens and values
	//
	for (WORD n=0; n<wClassCount; n++)
	{

		char* pClass = &szClasses[n * CLASS_LENGTH];
		char *pSubClass = NULL;

		//
		//
		// Check for "info_player_start" and "info_player_deathmatch"
		//
		//
		
		if (STRSTR((const char*)pClass, "info_player_start") || STRSTR((const char*)pClass, "info_player_deathmatch"))
		{
			// player initial position
			pSubClass = STRSTR((const char*)pClass, "origin");
			if (pSubClass)
			{
				while (*pSubClass != ' ') pSubClass++;
				while (*pSubClass != '"') pSubClass++;
				pSubClass++;

				//
				// get the origin values
				//

				// get X
				t = 0;
				memset(szToken, 0, TOKEN_SIZE);
				while (*pSubClass != ' ' && *pSubClass != '"') szToken[t++] = *pSubClass++;
				m_Origin[0] = ITOX(ATOI(szToken));
				pSubClass++;

				// get Y
				t = 0;
				memset(szToken, 0, TOKEN_SIZE);
				while (*pSubClass != ' ' && *pSubClass != '"') szToken[t++] = *pSubClass++;
				m_Origin[2] = ITOX(-ATOI(szToken));
				pSubClass++;

				// get Z
				t = 0;
				memset(szToken, 0, TOKEN_SIZE);
				while (*pSubClass != ' ' && *pSubClass != '"') szToken[t++] = *pSubClass++;
				m_Origin[1] = ITOX(ATOI(szToken));
			}

			// try to get player's initial angle
			pSubClass = STRSTR((const char*)pClass, "angle");
			if (pSubClass)
			{
				while (*pSubClass != ' ') pSubClass++;
				while (*pSubClass != '"') pSubClass++;
				pSubClass++;

				t = 0;
				memset(szToken, 0, TOKEN_SIZE);
				while (*pSubClass != ' ' && *pSubClass != '"') szToken[t++] = *pSubClass++;
				m_iAngle = ITOX(ATOI(szToken) + 270);
			}
		}		// end if "info_player_start" || "info_player_deathmatch"

	}		// end for (wClassCount)

	DeletePtrArray(szClasses);
}


//
// Return the info_player_start
//
void CQ3BSP::GetInfoPlayerStart(vec3_t v)
{
	VectorCopy(m_Origin, v);
}


//
// return the player initial angle
//
int CQ3BSP::InfoPlayerStartAngle()
{
	return m_iAngle;
}


//
// Find leaf where the camera is
//
int CQ3BSP::FindLeaf(CCamera* pCam)
{
	node_lump* pNode;
	plane_lump* pPlane;
	int iIdx;
	float fDot;

	iIdx = 0;

	while (iIdx >= 0)				// if idx < 0 we have found a leaf.
	{
		pNode = &m_pNodes[iIdx];
		pPlane = m_pPlanes + pNode->iPlane;

		// ### definitely not optimal
		vec3f_t v =
		{
			XTOF(pCam->Position()[0]),
			XTOF(-pCam->Position()[2]),
			XTOF(pCam->Position()[1])
		};

		fDot = DotProductf(v, pPlane->vNormal) - pPlane->fDist;

		if (fDot >= 0.0f)
			iIdx = pNode->iChildren[0];		// front
		else
			iIdx = pNode->iChildren[1];		// back
	}

	return ~iIdx;
}


//
// Convert to opengl-es format
//
void CQ3BSP::ConvertToFast(void)
{
	DWORD f = 0;

	// allocate fast faces for the entire bsp
	m_FastBSP.pFaces = new fast_face[m_dwFaceCount];

	// allocate vertices for the entire bsp
	m_FastBSP.pVertices = new int[m_dwVertexCount * 3];
	m_FastBSP.pTexCoords = new dword[m_dwVertexCount * 2];
	m_FastBSP.pLitCoords = new dword[m_dwVertexCount * 2];
	m_FastBSP.pColValues = new dword[m_dwVertexCount * 4];

	// transfer the original faces to the fast faces
	for (f=0; f<m_dwFaceCount; f++)
	{
		// get a pointer to the face
		face_lump* pFace = &m_pFaces[f];

		// get a pointer to the first meshvert of this face
		meshvert_lump* pMeshVert = &m_pMeshVerts[pFace->iMeshVert];

		// calculate number of triangles that form this face polygon
		WORD wTriCount = pFace->iMeshVertCount / 3;

		// allocate triangles for the face polygon
		m_FastBSP.pFaces[f].iType = pFace->iType;
		m_FastBSP.pFaces[f].wTriCount = wTriCount;
		m_FastBSP.pFaces[f].iTextureIndex = pFace->iTexture;
		m_FastBSP.pFaces[f].iLightmapIndex = pFace->iLm;
		m_FastBSP.pFaces[f].pTris = new word[wTriCount * 3];
		m_FastBSP.pFaces[f].dwFrame = 0;

		// convert the polygon into triangles
		WORD wVert = 0;
		WORD wCurTri = 0;
		for (WORD t=0; t<wTriCount; t++)
		{
			m_FastBSP.pFaces[f].pTris[wCurTri + 2] = pFace->iVertex + pMeshVert[wVert++].iOffset;
			m_FastBSP.pFaces[f].pTris[wCurTri + 1] = pFace->iVertex + pMeshVert[wVert++].iOffset;
			m_FastBSP.pFaces[f].pTris[wCurTri + 0] = pFace->iVertex + pMeshVert[wVert++].iOffset;
			wCurTri += 3;
		}
	}

	// transfer the original vertices to the fast vertices
	DWORD dwVIndex = 0;
	DWORD dwTIndex = 0;
	DWORD dwCIndex = 0;
	for (f=0; f<m_dwVertexCount; f++)
	{
		vertex_lump* pVertex = &m_pVertices[f];

		// convert vertex
		m_FastBSP.pVertices[dwVIndex++] =  FTOX(pVertex->fPosition[0]);
		m_FastBSP.pVertices[dwVIndex++] =  FTOX(pVertex->fPosition[2]);
		m_FastBSP.pVertices[dwVIndex++] = -FTOX(pVertex->fPosition[1]);

		// convert main texture uv
		m_FastBSP.pTexCoords[dwTIndex+0] = FTOX(pVertex->fTexCoord[0][0]);
		m_FastBSP.pTexCoords[dwTIndex+1] = FTOX(pVertex->fTexCoord[0][1]);

		// convert lightmap uv
		m_FastBSP.pLitCoords[dwTIndex+0] = FTOX(pVertex->fTexCoord[1][0]);
		m_FastBSP.pLitCoords[dwTIndex+1] = FTOX(pVertex->fTexCoord[1][1]);

		// convert RGBA color
		m_FastBSP.pColValues[dwCIndex+0] = ITOX(pVertex->jColor[0]);
		m_FastBSP.pColValues[dwCIndex+1] = ITOX(pVertex->jColor[1]);
		m_FastBSP.pColValues[dwCIndex+2] = ITOX(pVertex->jColor[2]);
		m_FastBSP.pColValues[dwCIndex+3] = ITOX(pVertex->jColor[3]);

		dwTIndex += 2;
		dwCIndex += 4;
	}
}


//
//
//
boolean CQ3BSP::IsClusterVisible(int iFromLeaf, int iToLeaf)
{
	#if 0

		return TRUE;

	#else

		leaf_lump* pFromLeaf = &m_pLeafs[iFromLeaf];
		leaf_lump* pToLeaf = &m_pLeafs[iToLeaf];

		if (!m_Visdata.pjVecs || pFromLeaf->iCluster < 0)
			return TRUE;

		int i = (pFromLeaf->iCluster * m_Visdata.iVectorSize) + (pToLeaf->iCluster >> 3);
		byte jVisSet = m_Visdata.pjVecs[i];

		return (jVisSet & (1 << (pToLeaf->iCluster & 7))) != 0;

	#endif
}


//
//
//
void CQ3BSP::WalkTree(CCamera* pCam, int iNode, int iCamNode)
{
	if (iNode >= 0)
	{
		// node
		WalkTree(pCam, m_pNodes[iNode].iChildren[0], iCamNode);		// front node
		WalkTree(pCam, m_pNodes[iNode].iChildren[1], iCamNode);		// back node
	}
	else
	{
		// leaf
		int iLeaf = ~iNode;
		if (IsClusterVisible(iCamNode, iLeaf))
		{
			leaf_lump* pLeaf = &m_pLeafs[iLeaf];
			if (pCam->IsBoxVisible(pLeaf->iMin, pLeaf->iMax))
				RenderLeaf(iLeaf);
		}
	}
}


//
// Render BSP
//
void CQ3BSP::Render(CCamera* pCam)
{
	// load camera projection view matrix
	glMatrixMode(GL_PROJECTION);
	glLoadMatrixx(pCam->ProjectionMatrix().m);

	// switch back to model view matrix
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// rotate world in camera space
	vec3_t r; VectorCopy(pCam->Rotation(), r);
	glRotatex(-r[0], 1,0,0);
	glRotatex(-r[1], 0,1,0);
	glRotatex(-r[2], 0,0,1);

	// translate world in camera space
	vec3_t p; VectorCopy(pCam->Position(), p);
	glTranslatex(-p[0], -p[1], -p[2]);

	//
	// change states for rendering
	//

	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FIXED, 0, m_FastBSP.pVertices);

	glEnableClientState(GL_COLOR_ARRAY);
	glColorPointer(4, GL_FIXED, 0, m_FastBSP.pColValues);

	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	//
	// render current cluster
	//

	int iCamLeaf = FindLeaf(pCam);
	RenderLeaf(iCamLeaf);
	WalkTree(pCam, 0, iCamLeaf);

	m_dwFrame++;
}


//
// Render a leaf tree
//
void CQ3BSP::RenderLeaf(int iLeaf)
{
	//
	// render the specified leaf
	//

	leaf_lump* pLeaf = &m_pLeafs[iLeaf];

	DWORD dwStart = pLeaf->iLeafFace;
	DWORD dwEnd = dwStart + pLeaf->iLeafFaceCount;

	for (DWORD f=dwStart; f<dwEnd; f++)
	{
		fast_face* pFace = &m_FastBSP.pFaces[m_pLeafFaces[f].iFace];
		if (pFace->dwFrame == m_dwFrame) continue;
		pFace->dwFrame = m_dwFrame;
		word* pTri = pFace->pTris;

		#if 1

			//
			// render solid triangles
			//

			// face types: 1==polygon, 2==patch, 3==mesh, 4==billboard
			switch (pFace->iType)
			{
				case 1:		// polygon
				{
					// render polygon triangles
					glTexCoordPointer(2, GL_FIXED, 0, m_FastBSP.pTexCoords);
					glBindTexture(GL_TEXTURE_2D, m_pSurfaces[pFace->iTextureIndex].TexID());
					glDrawElements(GL_TRIANGLES, pFace->wTriCount*3, GL_UNSIGNED_SHORT, pTri);

					// render lightmap
					glEnable(GL_BLEND);
					glBlendFunc(GL_ZERO, GL_SRC_COLOR);
					glTexCoordPointer(2, GL_FIXED, 0, m_FastBSP.pLitCoords);
					CTexture* pLmTex = &m_pLightmapTextures[pFace->iLightmapIndex];
					glBindTexture(GL_TEXTURE_2D, pLmTex->TexID());
					glDrawElements(GL_TRIANGLES, pFace->wTriCount*3, GL_UNSIGNED_SHORT, pTri);
					glDisable(GL_BLEND);

					break;
				}

				case 3:		// mesh
				{
					// render polygon triangles
					glTexCoordPointer(2, GL_FIXED, 0, m_FastBSP.pTexCoords);
					glBindTexture(GL_TEXTURE_2D, m_pSurfaces[pFace->iTextureIndex].TexID());
					glDrawElements(GL_TRIANGLES, pFace->wTriCount*3, GL_UNSIGNED_SHORT, pTri);

					break;
				}
			}

		#else

			//
			// render wireframe triangles
			//

			glDisable(GL_TEXTURE_2D);
			glDrawElements(GL_LINES, pFace->wTriCount*3, GL_UNSIGNED_SHORT, pTri);

		#endif
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -