Пример #1
0
bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*)
{
	size_t i;

	// only apply once per frame if the mesh is actually modified
	if(m_pMeshObject->MeshModified() &&
	   m_lastDeformUpdate != m_gameobj->GetLastFrame()) {
		// For each material
		for(list<RAS_MeshMaterial>::iterator mit= m_pMeshObject->GetFirstMaterial();
			mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
			if(!mit->m_slots[(void*)m_gameobj])
				continue;

			RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
			RAS_MeshSlot::iterator it;

			// for each array
			for(slot->begin(it); !slot->end(it); slot->next(it)) {
				//	For each vertex
				for(i=it.startvertex; i<it.endvertex; i++) {
					RAS_TexVert& v = it.vertex[i];
					v.SetXYZ(m_bmesh->mvert[v.getOrigIndex()].co);
				}
			}
		}

		m_lastDeformUpdate = m_gameobj->GetLastFrame();

		return true;
	}

	return false;
}
Пример #2
0
void KX_FontObject::AddMeshUser()
{
	m_meshUser = new RAS_TextUser(m_pClient_info);

	// set the part of the mesh slot that never change
	float *fl = GetOpenGLMatrixPtr()->getPointer();
	m_meshUser->SetMatrix(fl);

	RAS_BucketManager *bucketManager = GetScene()->GetBucketManager();
	bool created = false;
	RAS_MaterialBucket *bucket = bucketManager->FindBucket(GetTextMaterial(), created);

	// If the material bucket is just created then we add a new mesh slot.
	if (created) {
		RAS_TexVertFormat format;
		format.uvSize = 1;
		format.colorSize = 1;
		bucket->NewMesh(NULL, NULL, format);
	}

	/* We copy the original mesh slot which is at the begin of the list, if it's not the case it
	 * doesn't matter as the mesh slot are all similar exepted their mesh user pointer which is
	 * set to NULL in copy. By copying instead of adding a mesh slot we reuse the same display
	 * array bucket.
	 */
	RAS_MeshSlot *ms = bucket->CopyMesh(*bucket->msBegin());
	ms->SetMeshUser(m_meshUser);
	ms->SetDeformer(NULL);
	m_meshUser->AddMeshSlot(ms);
}
RAS_Polygon* RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts)
{
	RAS_MeshMaterial *mmat;
	RAS_Polygon *poly;
	RAS_MeshSlot *slot;

	/* find a mesh material */
	mmat = GetMeshMaterial(bucket->GetPolyMaterial());

	/* none found, create a new one */
	if (!mmat) {
		RAS_MeshMaterial meshmat;
		meshmat.m_bucket = bucket;
		meshmat.m_baseslot = meshmat.m_bucket->AddMesh(numverts);
		meshmat.m_baseslot->m_mesh = this;
		m_materials.push_back(meshmat);
		mmat = &m_materials.back();
	}

	/* add it to the bucket, this also adds new display arrays */
	slot = mmat->m_baseslot;
	slot->AddPolygon(numverts);

	/* create a new polygon */
	RAS_DisplayArray *darray = slot->CurrentDisplayArray();
	poly = new RAS_Polygon(bucket, darray, numverts);
	m_Polygons.push_back(poly);

	return poly;
}
Пример #4
0
void RAS_BucketManager::RenderSolidBuckets(
	const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools)
{
	BucketList::iterator bit;

	rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED);

	for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) {
#if 1
		RAS_MaterialBucket* bucket = *bit;
		RAS_MeshSlot* ms;
		// remove the mesh slot form the list, it culls them automatically for next frame
		while((ms = bucket->GetNextActiveMeshSlot()))
		{
			rendertools->SetClientObject(rasty, ms->m_clientObj);
			while (bucket->ActivateMaterial(cameratrans, rasty, rendertools))
				bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *ms);

			// make this mesh slot culled automatically for next frame
			// it will be culled out by frustrum culling
			ms->SetCulled(true);
		}
#else
		list<RAS_MeshSlot>::iterator mit;
		for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) {
			if (mit->IsCulled())
				continue;

			rendertools->SetClientObject(rasty, mit->m_clientObj);

			while ((*bit)->ActivateMaterial(cameratrans, rasty, rendertools))
				(*bit)->RenderMeshSlot(cameratrans, rasty, rendertools, *mit);

			// make this mesh slot culled automatically for next frame
			// it will be culled out by frustrum culling
			mit->SetCulled(true);
		}
#endif
	}
	
	/* this code draws meshes order front-to-back instead to reduce overdraw.
	 * it turned out slower due to much material state switching, a more clever
	 * algorithm might do better. */
#if 0
	vector<sortedmeshslot> slots;
	vector<sortedmeshslot>::iterator sit;

	OrderBuckets(cameratrans, m_SolidBuckets, slots, false);

	for(sit=slots.begin(); sit!=slots.end(); ++sit) {
		rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj);

		while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools))
			sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms));
	}
#endif
}
Пример #5
0
RAS_MeshSlot *RAS_MaterialBucket::NewMesh(RAS_MeshObject *mesh, RAS_MeshMaterial *meshmat, const RAS_TexVertFormat& format)
{
	RAS_MeshSlot *ms = new RAS_MeshSlot();
	ms->init(this, mesh, meshmat, format);

	m_meshSlots.push_back(ms);

	return ms;
}
Пример #6
0
void RAS_MeshObject::AddVertex(RAS_Polygon *poly, int i,
								const MT_Point3& xyz,
								const MT_Point2& uv,
								const MT_Point2& uv2,
								const MT_Vector4& tangent,
								const unsigned int rgba,
								const MT_Vector3& normal,
								bool flat,
								int origindex)
{
	RAS_TexVert texvert(xyz, uv, uv2, tangent, rgba, normal, flat, origindex);
	RAS_MeshMaterial *mmat;
	RAS_DisplayArray *darray;
	RAS_MeshSlot *slot;
	int offset;
	
	mmat = GetMeshMaterial(poly->GetMaterial()->GetPolyMaterial());
	slot = mmat->m_baseslot;
	darray = slot->CurrentDisplayArray();

	{ /* Shared Vertex! */
		/* find vertices shared between faces, with the restriction
		 * that they exist in the same display array, and have the
		 * same uv coordinate etc */
		vector<SharedVertex>& sharedmap = m_sharedvertex_map[origindex];
		vector<SharedVertex>::iterator it;

		for (it = sharedmap.begin(); it != sharedmap.end(); it++)
		{
			if (it->m_darray != darray)
				continue;
			if (!it->m_darray->m_vertex[it->m_offset].closeTo(&texvert))
				continue;

			/* found one, add it and we're done */
			if (poly->IsVisible())
				slot->AddPolygonVertex(it->m_offset);
			poly->SetVertexOffset(i, it->m_offset);
			return;
		}
	}

	/* no shared vertex found, add a new one */
	offset = slot->AddVertex(texvert);
	if (poly->IsVisible())
		slot->AddPolygonVertex(offset);
	poly->SetVertexOffset(i, offset);

	{ /* Shared Vertex! */
		SharedVertex shared;
		shared.m_darray = darray;
		shared.m_offset = offset;
		m_sharedvertex_map[origindex].push_back(shared);
	}
}
Пример #7
0
bool KX_SoftBodyDeformer::Apply(class RAS_IPolyMaterial *polymat)
{
	KX_BulletPhysicsController* ctrl = (KX_BulletPhysicsController*) m_gameobj->GetPhysicsController();
	if (!ctrl)
		return false;

	btSoftBody* softBody= ctrl->GetSoftBody();
	if (!softBody)
		return false;

	//printf("apply\n");
	RAS_MeshSlot::iterator it;
	RAS_MeshMaterial *mmat;
	RAS_MeshSlot *slot;
	size_t i;

	// update the vertex in m_transverts
	Update();

	// The vertex cache can only be updated for this deformer:
	// Duplicated objects with more than one ploymaterial (=multiple mesh slot per object)
	// share the same mesh (=the same cache). As the rendering is done per polymaterial
	// cycling through the objects, the entire mesh cache cannot be updated in one shot.
	mmat = m_pMeshObject->GetMeshMaterial(polymat);
	if(!mmat->m_slots[(void*)m_gameobj])
		return true;

	slot = *mmat->m_slots[(void*)m_gameobj];

	// for each array
	for(slot->begin(it); !slot->end(it); slot->next(it)) 
	{
		btSoftBody::tNodeArray&   nodes(softBody->m_nodes);

		int index = 0;
		for(i=it.startvertex; i<it.endvertex; i++,index++) {
			RAS_TexVert& v = it.vertex[i];
			btAssert(v.getSoftBodyIndex() >= 0);

			MT_Point3 pt (
				nodes[v.getSoftBodyIndex()].m_x.getX(),
				nodes[v.getSoftBodyIndex()].m_x.getY(),
				nodes[v.getSoftBodyIndex()].m_x.getZ());
			v.SetXYZ(pt);

			MT_Vector3 normal (
				nodes[v.getSoftBodyIndex()].m_n.getX(),
				nodes[v.getSoftBodyIndex()].m_n.getY(),
				nodes[v.getSoftBodyIndex()].m_n.getZ());
			v.SetNormal(normal);

		}
	}
	return true;
}
RAS_MeshSlot* RAS_MaterialBucket::AddMesh(int numverts)
{
	RAS_MeshSlot *ms;

	m_meshSlots.push_back(RAS_MeshSlot());
	
	ms = &m_meshSlots.back();
	ms->init(this, numverts);

	return ms;
}
void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba)
{
	RAS_MeshMaterial *mmat = GetMeshMaterial(mat);
	RAS_MeshSlot *slot = mmat->m_baseslot;
	RAS_MeshSlot::iterator it;
	size_t i;

	for (slot->begin(it); !slot->end(it); slot->next(it))
		for (i=it.startvertex; i<it.endvertex; i++)
			it.vertex[i].SetRGBA(rgba);
}
int RAS_MeshObject::NumVertices(RAS_IPolyMaterial* mat)
{
	RAS_MeshMaterial *mmat;
	RAS_MeshSlot *slot;
	RAS_MeshSlot::iterator it;
	size_t len = 0;

	mmat = GetMeshMaterial(mat);
	slot = mmat->m_baseslot;
	for (slot->begin(it); !slot->end(it); slot->next(it))
		len += it.endvertex - it.startvertex;
	
	return len;
}
void RAS_MeshObject::SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transform)
{
	// Limitations: sorting is quite simple, and handles many
	// cases wrong, partially due to polygons being sorted per
	// bucket.
	// 
	// a) mixed triangles/quads are sorted wrong
	// b) mixed materials are sorted wrong
	// c) more than 65k faces are sorted wrong
	// d) intersecting objects are sorted wrong
	// e) intersecting polygons are sorted wrong
	//
	// a) can be solved by making all faces either triangles or quads
	// if they need to be z-sorted. c) could be solved by allowing
	// larger buckets, b) and d) cannot be solved easily if we want
	// to avoid excessive state changes while drawing. e) would
	// require splitting polygons.

	RAS_MeshSlot::iterator it;
	size_t j;

	for (ms.begin(it); !ms.end(it); ms.next(it)) {
		unsigned int nvert = (int)it.array->m_type;
		unsigned int totpoly = it.totindex/nvert;

		if (totpoly <= 1)
			continue;
		if (it.array->m_type == RAS_DisplayArray::LINE)
			continue;

		// Extract camera Z plane...
		const MT_Vector3 pnorm(transform.getBasis()[2]);
		// unneeded: const MT_Scalar pval = transform.getOrigin()[2];

		vector<polygonSlot> poly_slots(totpoly);

		/* get indices and z into temporary array */
		for (j=0; j<totpoly; j++)
			poly_slots[j].get(it.vertex, it.index, j*nvert, nvert, pnorm);

		/* sort (stable_sort might be better, if flickering happens?) */
		std::sort(poly_slots.begin(), poly_slots.end(), backtofront());

		/* get indices from temporary array again */
		for (j=0; j<totpoly; j++)
			poly_slots[j].set(it.index, j*nvert, nvert);
	}
}
Пример #12
0
bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat)
{
	RAS_MeshSlot::iterator it;
	RAS_MeshMaterial *mmat;
	RAS_MeshSlot *slot;
	size_t i, nmat, imat;

	// update the vertex in m_transverts
	if (!Update())
		return false;

	if (m_transverts) {
		// the vertex cache is unique to this deformer, no need to update it
		// if it wasn't updated! We must update all the materials at once
		// because we will not get here again for the other material
		nmat = m_pMeshObject->NumMaterials();
		for (imat=0; imat<nmat; imat++) {
			mmat = m_pMeshObject->GetMeshMaterial(imat);
			if (!mmat->m_slots[(void*)m_gameobj])
				continue;

			slot = *mmat->m_slots[(void*)m_gameobj];

			// for each array
			for (slot->begin(it); !slot->end(it); slot->next(it)) {
				// for each vertex
				// copy the untransformed data from the original mvert
				for (i=it.startvertex; i<it.endvertex; i++) {
					RAS_TexVert& v = it.vertex[i];
					v.SetXYZ(m_transverts[v.getOrigIndex()]);
					if (m_copyNormals)
						v.SetNormal(m_transnors[v.getOrigIndex()]);
				}
			}
		}

		if (m_copyNormals)
			m_copyNormals = false;
	}
	return true;
}
Пример #13
0
void RAS_StorageVBO::IndexPrimitives(RAS_MeshSlot& ms)
{
	RAS_MeshSlot::iterator it;
	VBO *vbo;

	for (ms.begin(it); !ms.end(it); ms.next(it))
	{
		vbo = m_vbo_lookup[it.array];

		if (vbo == 0)
			m_vbo_lookup[it.array] = vbo = new VBO(it.array, it.totindex);

		// Update the vbo
		if (ms.m_mesh->MeshModified())
		{
			vbo->UpdateData();
		}

		vbo->Draw(*m_texco_num, m_texco, *m_attrib_num, m_attrib, m_attrib_layer);
	}
}
void RAS_MeshObject::AddMeshUser(void *clientobj, SG_QList *head, RAS_Deformer* deformer)
{
	list<RAS_MeshMaterial>::iterator it;
	list<RAS_MeshMaterial>::iterator mit;

	for (it = m_materials.begin();it!=m_materials.end();++it) {
		/* always copy from the base slot, which is never removed 
		 * since new objects can be created with the same mesh data */
		if (deformer && !deformer->UseVertexArray())
		{
			// HACK! 
			// this deformer doesn't use vertex array => derive mesh
			// we must keep only the mesh slots that have unique material id
			// this is to match the derived mesh drawing function
			// Need a better solution in the future: scan the derive mesh and create vertex array
			RAS_IPolyMaterial* curmat = it->m_bucket->GetPolyMaterial();
			if (curmat->GetFlag() & RAS_BLENDERGLSL) 
			{
				for (mit = m_materials.begin(); mit != it; ++mit)
				{
					RAS_IPolyMaterial* mat = mit->m_bucket->GetPolyMaterial();
					if ((mat->GetFlag() & RAS_BLENDERGLSL) && 
						mat->GetMaterialIndex() == curmat->GetMaterialIndex())
						// no need to convert current mesh slot
						break;
				}
				if (mit != it)
					continue;
			}
		}
		RAS_MeshSlot *ms = it->m_bucket->CopyMesh(it->m_baseslot);
		ms->m_clientObj = clientobj;
		ms->SetDeformer(deformer);
		it->m_slots.insert(clientobj, ms);
		head->QAddBack(ms);
	}
}
RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid,
									   unsigned int index)
{
	RAS_MeshMaterial *mmat;
	RAS_MeshSlot *slot;
	RAS_MeshSlot::iterator it;
	size_t len;

	mmat = GetMeshMaterial(matid);

	if (!mmat)
		return NULL;
	
	slot = mmat->m_baseslot;
	len = 0;
	for (slot->begin(it); !slot->end(it); slot->next(it)) {
		if (index >= len + it.endvertex - it.startvertex)
			len += it.endvertex - it.startvertex;
		else
			return &it.vertex[index - len];
	}
	
	return NULL;
}
Пример #16
0
bool KX_SoftBodyDeformer::Apply(RAS_IPolyMaterial *polymat, RAS_MeshMaterial *meshmat)
{
	CcdPhysicsController *ctrl = (CcdPhysicsController *)m_gameobj->GetPhysicsController();
	if (!ctrl)
		return false;

	btSoftBody *softBody = ctrl->GetSoftBody();
	if (!softBody)
		return false;

	// update the vertex in m_transverts
	Update();

	RAS_MeshSlot *slot = meshmat->m_slots[(void *)m_gameobj->getClientInfo()];
	if (!slot) {
		return false;
	}

	RAS_IDisplayArray *array = slot->GetDisplayArray();
	RAS_IDisplayArray *origarray = meshmat->m_baseslot->GetDisplayArray();

	btSoftBody::tNodeArray&   nodes(softBody->m_nodes);


	if (m_needUpdateAabb) {
		m_boundingBox->SetAabb(MT_Vector3(0.0f, 0.0f, 0.0f), MT_Vector3(0.0f, 0.0f, 0.0f));
		m_needUpdateAabb = false;
	}

	// AABB Box : min/max.
	MT_Vector3 aabbMin;
	MT_Vector3 aabbMax;

	for (unsigned int i = 0, size = array->GetVertexCount(); i < size; ++i) {
		RAS_ITexVert *v = array->GetVertex(i);
		const RAS_TexVertInfo& vinfo = origarray->GetVertexInfo(i);
		/* The physics converter write the soft body index only in the original
		 * vertex array because at this moment it doesn't know which is the
		 * game object. It didn't cause any issues because it's always the same
		 * vertex order.
		 */
		const unsigned int softbodyindex = vinfo.getSoftBodyIndex();

		MT_Vector3 pt(
		    nodes[softbodyindex].m_x.getX(),
		    nodes[softbodyindex].m_x.getY(),
		    nodes[softbodyindex].m_x.getZ());
		v->SetXYZ(pt);

		MT_Vector3 normal(
		    nodes[softbodyindex].m_n.getX(),
		    nodes[softbodyindex].m_n.getY(),
		    nodes[softbodyindex].m_n.getZ());
		v->SetNormal(normal);

		if (!m_gameobj->GetAutoUpdateBounds()) {
			continue;
		}

		const MT_Vector3& scale = m_gameobj->NodeGetWorldScaling();
		const MT_Vector3& invertscale = MT_Vector3(1.0f / scale.x(), 1.0f / scale.y(), 1.0f / scale.z());
		const MT_Vector3& pos = m_gameobj->NodeGetWorldPosition();
		const MT_Matrix3x3& rot = m_gameobj->NodeGetWorldOrientation();

		// Extract object transform from the vertex position.
		pt = (pt - pos) * rot * invertscale;
		// if the AABB need an update.
		if (i == 0) {
			aabbMin = aabbMax = pt;
		}
		else {
			aabbMin.x() = std::min(aabbMin.x(), pt.x());
			aabbMin.y() = std::min(aabbMin.y(), pt.y());
			aabbMin.z() = std::min(aabbMin.z(), pt.z());
			aabbMax.x() = std::max(aabbMax.x(), pt.x());
			aabbMax.y() = std::max(aabbMax.y(), pt.y());
			aabbMax.z() = std::max(aabbMax.z(), pt.z());
		}
	}

	array->UpdateFrom(origarray, origarray->GetModifiedFlag() &
					 (RAS_IDisplayArray::TANGENT_MODIFIED |
					  RAS_IDisplayArray::UVS_MODIFIED |
					  RAS_IDisplayArray::COLORS_MODIFIED));

	m_boundingBox->ExtendAabb(aabbMin, aabbMax);

	return true;
}
Пример #17
0
void RAS_StorageIM::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
{ 
	bool obcolor = ms.m_bObjectColor;
	bool wireframe = m_drawingmode <= RAS_IRasterizer::KX_WIREFRAME;
	MT_Vector4& rgba = ms.m_RGBAcolor;
	RAS_MeshSlot::iterator it;

	if (ms.m_pDerivedMesh) {
		// mesh data is in derived mesh, 
		current_bucket = ms.m_bucket;
		current_polymat = current_bucket->GetPolyMaterial();
		current_ms = &ms;
		current_mesh = ms.m_mesh;
		current_wireframe = wireframe;
		// MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); /* UNUSED */

		// handle two-side
		if (current_polymat->GetDrawingMode() & RAS_IRasterizer::KX_BACKCULL)
			this->SetCullFace(true);
		else
			this->SetCullFace(false);

		if (current_polymat->GetFlag() & RAS_BLENDERGLSL) {
			// GetMaterialIndex return the original mface material index, 
			// increment by 1 to match what derived mesh is doing
			current_blmat_nr = current_polymat->GetMaterialIndex()+1;
			// For GLSL we need to retrieve the GPU material attribute
			Material* blmat = current_polymat->GetBlenderMaterial();
			Scene* blscene = current_polymat->GetBlenderScene();
			if (!wireframe && blscene && blmat)
				GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), &current_gpu_attribs);
			else
				memset(&current_gpu_attribs, 0, sizeof(current_gpu_attribs));
			// DM draw can mess up blending mode, restore at the end
			int current_blend_mode = GPU_get_material_alpha_blend();
			ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
			GPU_set_material_alpha_blend(current_blend_mode);
		} else {
			//ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
			current_blmat_nr = current_polymat->GetMaterialIndex();
			current_image = current_polymat->GetBlenderImage();
			ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM, NULL, NULL, DM_DRAW_USE_ACTIVE_UV);
		}
		return;
	}
	// iterate over display arrays, each containing an index + vertex array
	for (ms.begin(it); !ms.end(it); ms.next(it)) {
		RAS_TexVert *vertex;
		size_t i, j, numvert;
		
		numvert = it.array->m_type;

		if (it.array->m_type == RAS_DisplayArray::LINE) {
			// line drawing
			glBegin(GL_LINES);

			for (i = 0; i < it.totindex; i += 2)
			{
				vertex = &it.vertex[it.index[i]];
				glVertex3fv(vertex->getXYZ());

				vertex = &it.vertex[it.index[i+1]];
				glVertex3fv(vertex->getXYZ());
			}

			glEnd();
		}
		else {
			// triangle and quad drawing
			if (it.array->m_type == RAS_DisplayArray::TRIANGLE)
				glBegin(GL_TRIANGLES);
			else
				glBegin(GL_QUADS);

			for (i = 0; i < it.totindex; i += numvert)
			{
				if (obcolor)
					glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);

				for (j = 0; j < numvert; j++) {
					vertex = &it.vertex[it.index[i+j]];

					if (!wireframe) {
						if (!obcolor)
							glColor4ubv((const GLubyte *)(vertex->getRGBA()));

						glNormal3fv(vertex->getNormal());

						if (multi)
							TexCoord(*vertex);
						else
							glTexCoord2fv(vertex->getUV(0));
					}

					glVertex3fv(vertex->getXYZ());
				}
			}

			glEnd();
		}
	}
}
void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms,
									class RAS_IPolyMaterial* polymat)
{ 
	bool obcolor = ms.m_bObjectColor;
	MT_Vector4& rgba = ms.m_RGBAcolor;
	RAS_MeshSlot::iterator it;

	const STR_String& mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");

	// handle object color
	if (obcolor) {
		glDisableClientState(GL_COLOR_ARRAY);
		glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
	}
	else
		glEnableClientState(GL_COLOR_ARRAY);

	for (ms.begin(it); !ms.end(it); ms.next(it)) {
		RAS_TexVert *vertex;
		size_t i, j, numvert;
		
		numvert = it.array->m_type;

		if (it.array->m_type == RAS_DisplayArray::LINE) {
			// line drawing, no text
			glBegin(GL_LINES);

			for (i=0; i<it.totindex; i+=2)
			{
				vertex = &it.vertex[it.index[i]];
				glVertex3fv(vertex->getXYZ());

				vertex = &it.vertex[it.index[i+1]];
				glVertex3fv(vertex->getXYZ());
			}

			glEnd();
		}
		else {
			// triangle and quad text drawing
			for (i=0; i<it.totindex; i+=numvert)
			{
				float v[4][3];
				int glattrib, unit;

				for (j=0; j<numvert; j++) {
					vertex = &it.vertex[it.index[i+j]];

					v[j][0] = vertex->getXYZ()[0];
					v[j][1] = vertex->getXYZ()[1];
					v[j][2] = vertex->getXYZ()[2];
				}

				// find the right opengl attribute
				glattrib = -1;
				if (GLEW_ARB_vertex_program)
					for (unit=0; unit<m_attrib_num; unit++)
						if (m_attrib[unit] == RAS_TEXCO_UV)
							glattrib = unit;

				GPU_render_text(polymat->GetMTFace(), polymat->GetDrawingMode(), mytext, mytext.Length(), polymat->GetMCol(), v[0], v[1], v[2], v[3], glattrib);

				ClearCachingInfo();
			}
		}
	}

	glDisableClientState(GL_COLOR_ARRAY);
}
Пример #19
0
void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms)
{
    static const GLsizei stride = sizeof(RAS_TexVert);
    bool wireframe = m_drawingmode <= KX_WIREFRAME;
    RAS_MeshSlot::iterator it;
    GLenum drawmode;

    if (ms.m_pDerivedMesh) {
        // cannot be handled here, pass to RAS_OpenGLRasterizer
        RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, true);
        return;
    }

    if(!wireframe)
        EnableTextures(true);

    // use glDrawElements to draw each vertexarray
    for(ms.begin(it); !ms.end(it); ms.next(it)) {
        if(it.totindex == 0)
            continue;

        // drawing mode
        if(it.array->m_type == RAS_DisplayArray::TRIANGLE)
            drawmode = GL_TRIANGLES;
        else if(it.array->m_type == RAS_DisplayArray::QUAD)
            drawmode = GL_QUADS;
        else
            drawmode = GL_LINES;

        // colors
        if (drawmode != GL_LINES && !wireframe) {
            if (ms.m_bObjectColor) {
                const MT_Vector4& rgba = ms.m_RGBAcolor;

                glDisableClientState(GL_COLOR_ARRAY);
                glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
            }
            else {
                glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
                glEnableClientState(GL_COLOR_ARRAY);
            }
        }
        else
            glColor4f(0.0f, 0.0f, 0.0f, 1.0f);

        glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ());
        glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal());
        if(!wireframe) {
            TexCoordPtr(it.vertex);
            if(glIsEnabled(GL_COLOR_ARRAY))
                glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA());
        }

        // here the actual drawing takes places
        glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index);
    }

    if(!wireframe) {
        glDisableClientState(GL_COLOR_ARRAY);
        EnableTextures(false);
    }
}
Пример #20
0
/**
 * @warning This function is expensive!
 */
void BL_MeshDeformer::RecalcNormals()
{
	/* We don't normalize for performance, not doing it for faces normals
	 * gives area-weight normals which often look better anyway, and use
	 * GL_NORMALIZE so we don't have to do per vertex normalization either
	 * since the GPU can do it faster */
	list<RAS_MeshMaterial>::iterator mit;
	RAS_MeshSlot::iterator it;
	size_t i;

	/* set vertex normals to zero */
	memset(m_transnors, 0, sizeof(float)*3*m_bmesh->totvert);

	/* add face normals to vertices. */
	for(mit = m_pMeshObject->GetFirstMaterial();
		mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
		if(!mit->m_slots[(void*)m_gameobj])
			continue;

		RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];

		for(slot->begin(it); !slot->end(it); slot->next(it)) {
			int nvert = (int)it.array->m_type;

			for(i=0; i<it.totindex; i+=nvert) {
				RAS_TexVert& v1 = it.vertex[it.index[i]];
				RAS_TexVert& v2 = it.vertex[it.index[i+1]];
				RAS_TexVert& v3 = it.vertex[it.index[i+2]];
				RAS_TexVert *v4 = NULL;

				const float *co1 = m_transverts[v1.getOrigIndex()];
				const float *co2 = m_transverts[v2.getOrigIndex()];
				const float *co3 = m_transverts[v3.getOrigIndex()];
				const float *co4 = NULL;
				
				/* compute face normal */
				float fnor[3], n1[3], n2[3];

				if(nvert == 4) {
					v4 = &it.vertex[it.index[i+3]];
					co4 = m_transverts[v4->getOrigIndex()];

					n1[0]= co1[0]-co3[0];
					n1[1]= co1[1]-co3[1];
					n1[2]= co1[2]-co3[2];

					n2[0]= co2[0]-co4[0];
					n2[1]= co2[1]-co4[1];
					n2[2]= co2[2]-co4[2];
				}
				else {
					n1[0]= co1[0]-co2[0];
					n2[0]= co2[0]-co3[0];
					n1[1]= co1[1]-co2[1];

					n2[1]= co2[1]-co3[1];
					n1[2]= co1[2]-co2[2];
					n2[2]= co2[2]-co3[2];
				}

				fnor[0]= n1[1]*n2[2] - n1[2]*n2[1];
				fnor[1]= n1[2]*n2[0] - n1[0]*n2[2];
				fnor[2]= n1[0]*n2[1] - n1[1]*n2[0];
				Normalize(fnor);

				/* add to vertices for smooth normals */
				float *vn1 = m_transnors[v1.getOrigIndex()];
				float *vn2 = m_transnors[v2.getOrigIndex()];
				float *vn3 = m_transnors[v3.getOrigIndex()];

				vn1[0] += fnor[0]; vn1[1] += fnor[1]; vn1[2] += fnor[2];
				vn2[0] += fnor[0]; vn2[1] += fnor[1]; vn2[2] += fnor[2];
				vn3[0] += fnor[0]; vn3[1] += fnor[1]; vn3[2] += fnor[2];

				if(v4) {
					float *vn4 = m_transnors[v4->getOrigIndex()];
					vn4[0] += fnor[0]; vn4[1] += fnor[1]; vn4[2] += fnor[2];
				}

				/* in case of flat - just assign, the vertices are split */
				if(v1.getFlag() & RAS_TexVert::FLAT) {
					v1.SetNormal(fnor);
					v2.SetNormal(fnor);
					v3.SetNormal(fnor);
					if(v4)
						v4->SetNormal(fnor);
				}
			}
		}
	}

	/* assign smooth vertex normals */
	for(mit = m_pMeshObject->GetFirstMaterial();
		mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
		if(!mit->m_slots[(void*)m_gameobj])
			continue;

		RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];

		for(slot->begin(it); !slot->end(it); slot->next(it)) {
			for(i=it.startvertex; i<it.endvertex; i++) {
				RAS_TexVert& v = it.vertex[i];

				if(!(v.getFlag() & RAS_TexVert::FLAT))
					v.SetNormal(m_transnors[v.getOrigIndex()]); //.safe_normalized()
			}
		}
	}
}
Пример #21
0
PyObject *KX_MeshProxy::PyTransform(PyObject *args, PyObject *kwds)
{
	int matindex;
	PyObject *pymat;
	bool ok = false;

	MT_Matrix4x4 transform;

	if (!PyArg_ParseTuple(args,"iO:transform", &matindex, &pymat) ||
	    !PyMatTo(pymat, transform))
	{
		return NULL;
	}

	MT_Matrix4x4 ntransform = transform.inverse().transposed();
	ntransform[0][3] = ntransform[1][3] = ntransform[2][3] = 0.0f;

	/* transform mesh verts */
	unsigned int mit_index = 0;
	for (list<RAS_MeshMaterial>::iterator mit = m_meshobj->GetFirstMaterial();
	     (mit != m_meshobj->GetLastMaterial());
	     ++mit, ++mit_index)
	{
		if (matindex == -1) {
			/* always transform */
		}
		else if (matindex == mit_index) {
			/* we found the right index! */
		}
		else {
			continue;
		}

		RAS_MeshSlot *slot = mit->m_baseslot;
		RAS_MeshSlot::iterator it;
		ok = true;

		for (slot->begin(it); !slot->end(it); slot->next(it)) {
			size_t i;
			for (i = it.startvertex; i < it.endvertex; i++) {
				RAS_TexVert *vert = &it.vertex[i];
				vert->Transform(transform, ntransform);
			}
		}

		/* if we set a material index, quit when done */
		if (matindex == mit_index) {
			break;
		}
	}

	if (ok == false) {
		PyErr_Format(PyExc_ValueError,
		             "mesh.transform(...): invalid material index %d", matindex);
		return NULL;
	}

	m_meshobj->SetMeshModified(true);

	Py_RETURN_NONE;
}
Пример #22
0
PyObject *KX_MeshProxy::PyTransformUV(PyObject *args, PyObject *kwds)
{
	int matindex;
	PyObject *pymat;
	int uvindex = -1;
	int uvindex_from = -1;
	bool ok = false;

	MT_Matrix4x4 transform;

	if (!PyArg_ParseTuple(args,"iO|iii:transformUV", &matindex, &pymat, &uvindex, &uvindex_from) ||
	    !PyMatTo(pymat, transform))
	{
		return NULL;
	}

	if (uvindex < -1 || uvindex > 1) {
		PyErr_Format(PyExc_ValueError,
		             "mesh.transformUV(...): invalid uv_index %d", uvindex);
		return NULL;
	}
	if (uvindex_from < -1 || uvindex_from > 1) {
		PyErr_Format(PyExc_ValueError,
		             "mesh.transformUV(...): invalid uv_index_from %d", uvindex);
		return NULL;
	}
	if (uvindex_from == uvindex) {
		uvindex_from = -1;
	}

	/* transform mesh verts */
	unsigned int mit_index = 0;
	for (list<RAS_MeshMaterial>::iterator mit = m_meshobj->GetFirstMaterial();
	     (mit != m_meshobj->GetLastMaterial());
	     ++mit, ++mit_index)
	{
		if (matindex == -1) {
			/* always transform */
		}
		else if (matindex == mit_index) {
			/* we found the right index! */
		}
		else {
			continue;
		}

		RAS_MeshSlot *slot = mit->m_baseslot;
		RAS_MeshSlot::iterator it;
		ok = true;

		for (slot->begin(it); !slot->end(it); slot->next(it)) {
			size_t i;

			for (i = it.startvertex; i < it.endvertex; i++) {
				RAS_TexVert *vert = &it.vertex[i];
				if (uvindex_from != -1) {
					if (uvindex_from == 0) vert->SetUV(1, vert->getUV(0));
					else                   vert->SetUV(0, vert->getUV(1));
				}

				switch (uvindex) {
					case 0:
						vert->TransformUV(0, transform);
						break;
					case 1:
						vert->TransformUV(1, transform);
						break;
					case -1:
						vert->TransformUV(0, transform);
						vert->TransformUV(1, transform);
						break;
				}
			}
		}

		/* if we set a material index, quit when done */
		if (matindex == mit_index) {
			break;
		}
	}

	if (ok == false) {
		PyErr_Format(PyExc_ValueError,
		             "mesh.transformUV(...): invalid material index %d", matindex);
		return NULL;
	}

	m_meshobj->SetMeshModified(true);

	Py_RETURN_NONE;
}