Ejemplo n.º 1
0
void FixedRenderer::updateSkinning(Mesh * mesh, Armature * armature)
{
	unsigned int s;
	unsigned int sSize = mesh->getSubMeshsNumber();
	for(s=0; s<sSize; s++)
	{
		SubMesh * subMesh = &mesh->getSubMeshs()[s];

		// data
		Vector3 * vertices = subMesh->getVertices();

		if(! vertices)
			continue;

		SkinData * skinData = subMesh->getSkinData();
		if(armature && skinData)
		{
			unsigned int verticesSize = subMesh->getVerticesSize();
			Vector3 * skinVertices = getVertices(verticesSize);

			computeSkinning(armature, skinData, vertices, NULL, NULL, skinVertices, NULL, NULL);
			subMesh->getBoundingBox()->initFromPoints(skinVertices, verticesSize);
		}
	}

	mesh->updateBoundingBox();
}
Ejemplo n.º 2
0
static void createSubMesh(const aiScene * scene, const aiNode * nd, Mesh * mesh, SubMesh * subMeshs, unsigned int * count, const Matrix4x4 & parentMatrix)
{
	aiMatrix4x4 nodeMat = nd->mTransformation;
	aiTransposeMatrix4(&nodeMat);
	
	Matrix4x4 matrix = parentMatrix * Matrix4x4((float*)&nodeMat);
	
	
	unsigned int m;
	for(m=0; m<nd->mNumMeshes; m++)
	{
		unsigned int i;
		const aiMesh * nodeMesh = scene->mMeshes[nd->mMeshes[m]];
		if(nodeMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE)
			continue;
		
		
		// current sub mesh
		SubMesh * subMesh = &(subMeshs[*count]);
	
		
		// vertices
		Vector3 * vertices = subMesh->allocVertices(nodeMesh->mNumVertices);
		for(i=0; i<nodeMesh->mNumVertices; i++)
			vertices[i] = matrix * Vector3(nodeMesh->mVertices[i].x, nodeMesh->mVertices[i].y, nodeMesh->mVertices[i].z);
		
		// normals
		if(nodeMesh->mNormals)
		{
			Vector3 * normals = subMesh->allocNormals(nodeMesh->mNumVertices);
			for(i=0; i<nodeMesh->mNumVertices; i++)
				normals[i] = matrix.getRotatedVector3(Vector3(nodeMesh->mNormals[i].x, nodeMesh->mNormals[i].y, nodeMesh->mNormals[i].z)).getNormalized();
		}
		
		// tangents
		if(nodeMesh->mTangents)
		{
			Vector3 * tangents = subMesh->allocTangents(nodeMesh->mNumVertices);
			for(i=0; i<nodeMesh->mNumVertices; i++)
				tangents[i] = matrix.getRotatedVector3(Vector3(nodeMesh->mTangents[i].x, nodeMesh->mTangents[i].y, nodeMesh->mTangents[i].z)).getNormalized();
		}
		
		// colors
		if(nodeMesh->mColors[0])
		{
			Color * colors = subMesh->allocColors(nodeMesh->mNumVertices);
			for(i=0; i<nodeMesh->mNumVertices; i++)
				colors[i] = Color(nodeMesh->mColors[0][i].r, nodeMesh->mColors[0][i].g, nodeMesh->mColors[0][i].b, nodeMesh->mColors[0][i].a);
		}
		
		// uvcoords
		{
			unsigned int t, nb_texLayers = 0;
			for(t=0; t<AI_MAX_NUMBER_OF_TEXTURECOORDS; t++)
			{
				if(nodeMesh->mTextureCoords[t])
					nb_texLayers++;
			}
			
			Vector2 * uvCoords = subMesh->allocTexCoords(nodeMesh->mNumVertices*nb_texLayers);
	
			nb_texLayers = 0;
			for(t=0; t<AI_MAX_NUMBER_OF_TEXTURECOORDS; t++)
			{
				if(nodeMesh->mTextureCoords[t])
				{
					unsigned int offset = nodeMesh->mNumVertices*nb_texLayers;
					subMesh->setMapChannelOffset(t, offset);
					
					for(i=0; i<nodeMesh->mNumVertices; i++){
						uvCoords[offset+i] = Vector2(nodeMesh->mTextureCoords[t][i].x, 1-nodeMesh->mTextureCoords[t][i].y);
					}
					
					nb_texLayers++;
				}
			}
		}
		
		// indices
		{
			unsigned int f;
			
			if(nodeMesh->mNumVertices < 65536)
			{
				unsigned short * indices = (unsigned short *)subMesh->allocIndices(nodeMesh->mNumFaces*3, VAR_USHORT);
				for(f=0; f<nodeMesh->mNumFaces; f++)
				{
					aiFace * face = &nodeMesh->mFaces[f];
					for(i=0; i<3; i++){
						indices[f*3+i] = face->mIndices[i];
					}
				}
			}
			else	
			{
				unsigned int * indices = (unsigned int *)subMesh->allocIndices(nodeMesh->mNumFaces*3, VAR_UINT);
				for(f=0; f<nodeMesh->mNumFaces; f++)
				{
					aiFace * face = &nodeMesh->mFaces[f];
					for(i=0; i<3; i++){
						indices[f*3+i] = face->mIndices[i];
					}
				}
			}
		}
		
		
		// bones
		initBones(scene, nodeMesh, mesh, subMesh);
		
		
		// display
		subMesh->allocDisplays(1);
		MaterialDisplay * display = subMesh->addNewDisplay(PRIMITIVE_TRIANGLES, 0, subMesh->getIndicesSize());
		display->setMaterial(mesh->getMaterial(nodeMesh->mMaterialIndex));
		
		// cull mode
		int twosided = 0;
		aiMaterial * mtl = scene->mMaterials[nodeMesh->mMaterialIndex];
		if(AI_SUCCESS == aiGetMaterialInteger(mtl, AI_MATKEY_TWOSIDED, &twosided))
		{
			if(twosided != 0)
				display->setCullMode(CULL_NONE);
		}
		
		// bounding box
		subMesh->getBoundingBox()->initFromPoints(vertices, subMesh->getVerticesSize());
		
		(*count)++;
	}
	
	
	for(unsigned int n=0; n<nd->mNumChildren; n++)
		createSubMesh(scene, nd->mChildren[n], mesh, subMeshs, count, matrix);
}
Ejemplo n.º 3
0
void FixedRenderer::drawScene(Scene * scene, OCamera * camera)
{
	struct MEntityLight
	{
		Box3d lightBox;
		OLight * light;
	};

	struct MSubMeshPass
	{
		unsigned int subMeshId;
		unsigned int lightsNumber;
		Object3d * object;
		OLight * lights[4];
	};

	// sub objects
	#define MAX_TRANSP_SUBOBJ 4096
	static int transpList[MAX_TRANSP_SUBOBJ];
	static float transpZList[MAX_TRANSP_SUBOBJ];
	static MSubMeshPass transpSubObjs[MAX_TRANSP_SUBOBJ];

	// lights list
	#define MAX_ENTITY_LIGHTS 256
	static int entityLightsList[MAX_ENTITY_LIGHTS];
	static float entityLightsZList[MAX_ENTITY_LIGHTS];
	static MEntityLight entityLights[MAX_ENTITY_LIGHTS];


	// get render
	RenderingContext * render = NeoEngine::getInstance()->getRenderingContext();
	render->enableLighting();
	render->enableBlending();


	// make frustum
	Frustum * frustum = camera->getFrustum();
	frustum->makeVolume(camera);

	// update visibility
	updateVisibility(scene, camera);

	// fog
	enableFog(camera);

	// camera
	Vector3 cameraPos = camera->getTransformedPosition();


	// transp sub obj number
	unsigned int transpSubObsNumber = 0;

	// lights
	unsigned int l;
	unsigned int lSize = scene->getLightsNumber();

	// entities
	unsigned int i;
	unsigned int eSize = scene->getEntitiesNumber();
	for(i=0; i<eSize; i++)
	{
		// get entity
		OEntity * entity = scene->getEntityByIndex(i);
		Mesh * mesh = entity->getMesh();

		if(! entity->isActive())
			continue;

		if(! entity->isVisible())
		{
			if(mesh)
			{
				Armature * armature = mesh->getArmature();
				ArmatureAnim * armatureAnim = mesh->getArmatureAnim();
				if(armature)
				{
					// animate armature
					if(mesh->getArmature())
					{
						Armature * armature = mesh->getArmature();
						if(mesh->getArmatureAnim())
						{
							animateArmature(
								mesh->getArmature(),
								mesh->getArmatureAnim(),
								entity->getCurrentFrame()
							);
						}
						else
						{
							armature->processBonesLinking();
							armature->updateBonesSkinMatrix();
						}
					}

					// TODO : optimize and add a tag to desactivate it
					updateSkinning(mesh, armature);
					(*entity->getBoundingBox()) = (*mesh->getBoundingBox());
				}
			}

			continue;
		}

		// draw mesh
		if(mesh)
		{
			Vector3 scale = entity->getTransformedScale();
			Box3d * entityBox = entity->getBoundingBox();

			float minScale = scale.x;
			minScale = MIN(minScale, scale.y);
			minScale = MIN(minScale, scale.z);
			minScale = 1.0f / minScale;

			unsigned int entityLightsNumber = 0;
			for(l=0; l<lSize; l++)
			{
				// get entity
				OLight * light = scene->getLightByIndex(l);

				if(! light->isActive())
					continue;

				if(! light->isVisible())
					continue;

				// light box
				Vector3 lightPos = light->getTransformedPosition();
				Vector3 localPos = entity->getInversePosition(lightPos);

				float localRadius = light->getRadius() * minScale;

				Box3d lightBox(
								Vector3(localPos - localRadius),
								Vector3(localPos + localRadius)
								);

				if(! entityBox->isInCollisionWith(lightBox))
					continue;

				MEntityLight * entityLight = &entityLights[entityLightsNumber];
				entityLight->lightBox = lightBox;
				entityLight->light = light;

				entityLightsNumber++;
				if(entityLightsNumber == MAX_ENTITY_LIGHTS)
					break;
			}

			// animate armature
			if(mesh->getArmature())
			{
				Armature * armature = mesh->getArmature();
				if(mesh->getArmatureAnim())
				{
					animateArmature(
						mesh->getArmature(),
						mesh->getArmatureAnim(),
						entity->getCurrentFrame()
					);
				}
				else
				{
					armature->processBonesLinking();
					armature->updateBonesSkinMatrix();
				}
			}

			// animate textures
			if(mesh->getTexturesAnim())
				animateTextures(mesh, mesh->getTexturesAnim(), entity->getCurrentFrame());

			// animate materials
			if(mesh->getMaterialsAnim())
				animateMaterials(mesh, mesh->getMaterialsAnim(), entity->getCurrentFrame());

			unsigned int s;
			unsigned int sSize = mesh->getSubMeshsNumber();
			for(s=0; s<sSize; s++)
			{
				SubMesh * subMesh = &mesh->getSubMeshs()[s];
				Box3d * box = subMesh->getBoundingBox();

				// check if submesh visible
				if(sSize > 1)
				{
					Vector3 * min = &box->min;
					Vector3 * max = &box->max;

					Vector3 points[8] = {
						entity->getTransformedVector(Vector3(min->x, min->y, min->z)),
						entity->getTransformedVector(Vector3(min->x, max->y, min->z)),
						entity->getTransformedVector(Vector3(max->x, max->y, min->z)),
						entity->getTransformedVector(Vector3(max->x, min->y, min->z)),
						entity->getTransformedVector(Vector3(min->x, min->y, max->z)),
						entity->getTransformedVector(Vector3(min->x, max->y, max->z)),
						entity->getTransformedVector(Vector3(max->x, max->y, max->z)),
						entity->getTransformedVector(Vector3(max->x, min->y, max->z))
					};

					if(! frustum->isVolumePointsVisible(points, 8))
						continue;
				}

				// subMesh center
				Vector3 center = box->min + (box->max - box->min)*0.5f;
				center = entity->getTransformedVector(center);

				// sort entity lights
				unsigned int lightsNumber = 0;
				for(l=0; l<entityLightsNumber; l++)
				{
					MEntityLight * entityLight = &entityLights[l];
					if(! box->isInCollisionWith(entityLight->lightBox))
						continue;

					OLight * light = entityLight->light;

					float z = (center - light->getTransformedPosition()).getLength();
					entityLightsList[lightsNumber] = l;
					entityLightsZList[l] = (1.0f/z)*light->getRadius();
					lightsNumber++;
				}

				if(lightsNumber > 1)
					sortFloatList(entityLightsList, entityLightsZList, 0, (int)lightsNumber-1);

				// local lights
				if(lightsNumber > 4)
					lightsNumber = 4;

				for(l=0; l<lightsNumber; l++)
				{
					MEntityLight * entityLight = &entityLights[entityLightsList[l]];
					OLight * light = entityLight->light;

					// attenuation
					float quadraticAttenuation = (8.0f / light->getRadius());
					quadraticAttenuation = (quadraticAttenuation*quadraticAttenuation)*light->getIntensity();

					// color
					Vector3 color = light->getFinalColor();

					// set light
					render->enableLight(l);
					render->setLightPosition(l, light->getTransformedPosition());
					render->setLightDiffuse(l, Vector4(color));
					render->setLightSpecular(l, Vector4(color));
					render->setLightAmbient(l, Vector3(0, 0, 0));
					render->setLightAttenuation(l, 1, 0, quadraticAttenuation);

					// spot
					render->setLightSpotAngle(l, light->getSpotAngle());
					if(light->getSpotAngle() < 90){
						render->setLightSpotDirection(l, light->getRotatedVector(Vector3(0, 0, -1)).getNormalized());
						render->setLightSpotExponent(l, light->getSpotExponent());
					}
					else {
						render->setLightSpotExponent(l, 0.0f);
					}
				}

				for(l=lightsNumber; l<4; l++){
					render->disableLight(l);
				}

				render->pushMatrix();
				render->multMatrix(entity->getMatrix());

				// draw opaques
				drawOpaques(subMesh, mesh->getArmature());

				if(subMesh->hasTransparency())
				{
					if(transpSubObsNumber < MAX_TRANSP_SUBOBJ)
					{
						// transparent subMesh pass
						MSubMeshPass * subMeshPass = &transpSubObjs[transpSubObsNumber];

						// lights
						subMeshPass->lightsNumber = lightsNumber;
						for(l=0; l<lightsNumber; l++)
							subMeshPass->lights[l] = entityLights[entityLightsList[l]].light;

						// z distance to camera
						float z = getDistanceToCam(camera, center);

						// set values
						transpList[transpSubObsNumber] = transpSubObsNumber;
						transpZList[transpSubObsNumber] = z;
						subMeshPass->subMeshId = s;
						subMeshPass->object = entity;

						transpSubObsNumber++;
					}
				}

				render->popMatrix();
			}

			mesh->updateBoundingBox();
			(*entity->getBoundingBox()) = (*mesh->getBoundingBox());
		}
	}


	// texts
	unsigned int tSize = scene->getTextsNumber();
	for(i=0; i<tSize; i++)
	{
		OText * text = scene->getTextByIndex(i);
		if(text->isActive() && text->isVisible())
		{
			// transparent pass
			MSubMeshPass * subMeshPass = &transpSubObjs[transpSubObsNumber];

			// center
			Box3d * box = text->getBoundingBox();
			Vector3 center = box->min + (box->max - box->min)*0.5f;
			center = text->getTransformedVector(center);

			// z distance to camera
			float z = getDistanceToCam(camera, center);

			// set values
			transpList[transpSubObsNumber] = transpSubObsNumber;
			transpZList[transpSubObsNumber] = z;
			subMeshPass->object = text;

			transpSubObsNumber++;
		}
	}


	// sort transparent list
	if(transpSubObsNumber > 1)
		sortFloatList(transpList, transpZList, 0, (int)transpSubObsNumber-1);

	// draw transparents
	render->setDepthMask(0);
	
	for(i=0; i<transpSubObsNumber; i++)
	{
		MSubMeshPass * subMeshPass = &transpSubObjs[transpList[i]];
		Object3d * object = subMeshPass->object;

		// objects
		switch(object->getType())
		{
			case M_OBJECT3D_ENTITY:
			{
				OEntity * entity = (OEntity *)object;
				unsigned int subMeshId = subMeshPass->subMeshId;
				Mesh * mesh = entity->getMesh();
				SubMesh * subMesh = &mesh->getSubMeshs()[subMeshId];

				// animate armature
				if(mesh->getArmature())
				{
					Armature * armature = mesh->getArmature();
					if(mesh->getArmatureAnim())
					{
						animateArmature(
							mesh->getArmature(),
							mesh->getArmatureAnim(),
							entity->getCurrentFrame()
						);
					}
					else
					{
						armature->processBonesLinking();
						armature->updateBonesSkinMatrix();
					}
				}

				// animate textures
				if(mesh->getTexturesAnim())
					animateTextures(mesh, mesh->getTexturesAnim(), entity->getCurrentFrame());

				// animate materials
				if(mesh->getMaterialsAnim())
					animateMaterials(mesh, mesh->getMaterialsAnim(), entity->getCurrentFrame());

				// lights
				for(l=0; l<subMeshPass->lightsNumber; l++)
				{
					OLight * light = subMeshPass->lights[l];

					// attenuation
					float quadraticAttenuation = (8.0f / light->getRadius());
					quadraticAttenuation = (quadraticAttenuation*quadraticAttenuation)*light->getIntensity();

					// color
					Vector3 color = light->getFinalColor();

					// set light
					render->enableLight(l);
					render->setLightPosition(l, light->getTransformedPosition());
					render->setLightDiffuse(l, Vector4(color));
					render->setLightSpecular(l, Vector4(color));
					render->setLightAmbient(l, Vector3(0, 0, 0));
					render->setLightAttenuation(l, 1, 0, quadraticAttenuation);

					// spot
					render->setLightSpotAngle(l, light->getSpotAngle());
					if(light->getSpotAngle() < 90){
						render->setLightSpotDirection(l, light->getRotatedVector(Vector3(0, 0, -1)).getNormalized());
						render->setLightSpotExponent(l, light->getSpotExponent());
					}
					else {
						render->setLightSpotExponent(l, 0.0f);
					}
				}

				for(l=subMeshPass->lightsNumber; l<4; l++){
					render->disableLight(l);
				}

				render->pushMatrix();
				render->multMatrix(entity->getMatrix());
				drawTransparents(subMesh, mesh->getArmature());
				render->popMatrix();

				mesh->updateBoundingBox();
				(*entity->getBoundingBox()) = (*mesh->getBoundingBox());
			}
				break;

			case M_OBJECT3D_TEXT:
			{
				OText * text = (OText *)object;

				render->pushMatrix();
				render->multMatrix(text->getMatrix());
				drawText(text);
				render->popMatrix();
			}
				break;
		}
	}
	
	render->setDepthMask(1);

	render->disableLighting();
	render->disableFog();
}