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

📄 cvmaterl.cpp

📁 Windows上的MUD客户端程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*----------------------------------------------------------------------------
                        _                              _ _       
        /\             | |                            | (_)      
       /  \   _ __   __| |_ __ ___  _ __ ___   ___  __| |_  __ _ 
      / /\ \ | '_ \ / _` | '__/ _ \| '_ ` _ \ / _ \/ _` | |/ _` |
     / ____ \| | | | (_| | | | (_) | | | | | |  __/ (_| | | (_| |
    /_/    \_\_| |_|\__,_|_|  \___/|_| |_| |_|\___|\__,_|_|\__,_|

    The contents of this file are subject to the Andromedia Public
	License Version 1.0 (the "License"); you may not use this file
	except in compliance with the License. You may obtain a copy of
	the License at http://www.andromedia.com/APL/

    Software distributed under the License is distributed on an
	"AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
	implied. See the License for the specific language governing
	rights and limitations under the License.

    The Original Code is Pueblo client code, released November 4, 1998.

    The Initial Developer of the Original Code is Andromedia Incorporated.
	Portions created by Andromedia are Copyright (C) 1998 Andromedia
	Incorporated.  All Rights Reserved.

	Andromedia Incorporated                         415.365.6700
	818 Mission Street - 2nd Floor                  415.365.6701 fax
	San Francisco, CA 94103

    Contributor(s):
	--------------------------------------------------------------------------
	   Chaco team:  Dan Greening, Glenn Crocker, Jim Doubek,
	                Coyote Lussier, Pritham Shetty.

					Wrote and designed original codebase.

------------------------------------------------------------------------------

	Implementation for the ChQvInstance class for  Intel 3DR.

----------------------------------------------------------------------------*/

// $Header: /home/cvs/chaco/modules/client/msw/ChGraphx/CvMaterl.cpp,v 2.26 1996/09/18 07:06:39 coyote Exp $

#include "grheader.h"

#include "CvInstnc.h"
#include <QvInfo.h>
#include <QvState.h>
#include "ChMaze.h"
#include "ChMazDep.h"
#include "CvTrnsfm.h"
#include "CvNormal.h"
#include "CvBound.h"
#include "CvMaterl.h"
#include "CvTextur.h"
#if (defined(CH_USE_D3D))
#include "ChRenderData.h"
#endif

#if (defined(CH_USE_RLAB)) || defined(CH_USE_D3D)
static const float maxShininess = 20.0;
#else
static const float maxShininess = 40.0;
#endif

float	ChMaterial::GetNativeShininess()
{
	return m_shininess * maxShininess;
};

bool ChMaterial::IsPrelit()
{
	return (m_diffuse.IsBlack() && m_ambient.IsBlack() && m_specular.IsBlack()); 
};

ChColor ChMaterial::GetBase()
{
	ChColor base = m_diffuse;

	float diffInt = m_diffuse.r() + m_diffuse.g() + m_diffuse.b();
	float ambInt = m_ambient.r() + m_ambient.g() + m_ambient.b();
	float emitInt = m_emissive.r() + m_emissive.g() + m_emissive.b();
	float specInt = m_specular.r() + m_specular.g() + m_specular.b();

	float multiplier = max(diffInt, ambInt);
	multiplier = max(multiplier,emitInt);
	//multiplier = max(multiplier,specInt);

	if(diffInt > 0)
	{
		// Scale the base color to be as bright as the brightest of  amb, emissive and diffuse
		// but with the same proportions as diffuse
		multiplier /= diffInt;

		float 	r =	base.r();
		float 	g =	base.g();
		float 	b =	base.b();

		if(multiplier > 1.0)
		{
			r =	base.r() * multiplier;
			g =	base.g() * multiplier;
			b =	base.b() * multiplier;
		}

		if(specInt > 0.)
		{
			// Blend in the specular color, depending upon shininess.
			// The shinier it is, the less we blend in.
			// Zero shininess means just add it - the  maxShininess / 2 factor is a hack

		#if (_MSC_VER > 900)

			float specularFactor = (float)pow( (double)2.7,
												(double)(-(GetShininess() *
															maxShininess / 2)) );

		#else
		
			float specularFactor = pow( 2.7,
										-(GetShininess() *
											maxShininess / 2) );

		#endif

			r += specularFactor * m_specular.r();
			g += specularFactor * m_specular.g();
			b += specularFactor * m_specular.b();
		}
		// No component > 1 svp ! - Try to keep the hue constant
		float big = max(r, max(g, b));
		big = max(big, 1);

		base.SetR( r / big );
		base.SetG( g / big );
		base.SetB( b / big );
	}
	else
	{
		base.SetR(max(max(m_diffuse.r(), m_emissive.r()), m_ambient.r()));
		base.SetG(max(max(m_diffuse.g(), m_emissive.g()), m_ambient.g()));
		base.SetB(max(max(m_diffuse.b(), m_emissive.b()), m_ambient.b()));
	}

	return base;

}

float ChQvMaterialMap::GetMaxTransparency()
{
	float transparency = 0;		  
	for(int i = 0; i < m_pMat->transparency.num; i++)
	{
		transparency=	max(transparency, m_pMat->transparency.values[i]);
	}
	return transparency;
}

#if defined(CH_USE_3DR)
void ChQvMaterialMap::SetMat( Dword_t  hRC, G3dHandle_t hGC, long index,  bool *pboolEmissive /*= 0*/)
{
	Fixed32_t wMattNum = 0;	  // for now always use material 0
	long i = index;

	if(i != m_lastI)
	{
		m_lastI = i;
		// Wrap indexing at array length 
		ColorF_t	ambient;	
		ColorFA_t	diffuse;	
		ColorF_t	specular;	
		ColorF_t	emit;		
		Qv2Native(m_pMat->ambientColor, i % m_pMat->ambientColor.num, ambient);
		Qv2Native(m_pMat->diffuseColor, i % m_pMat->diffuseColor.num, diffuse);
		Qv2Native(m_pMat->specularColor, i % m_pMat->specularColor.num, specular) ;
		Qv2Native(m_pMat->emissiveColor, i % m_pMat->emissiveColor.num, emit);

		Float_t		shine	=	maxShininess * 
								Float_t(m_pMat->shininess.values[i % m_pMat->shininess.num]);
								//  0 is opaque in vrml
								// alpha = 0.0, but color.a = 1.0 should be opaque in 3dr 
								// with typical blend functions
		Float_t		alpha	=	Float_t(m_pMat->transparency.values[i % m_pMat->transparency.num]);
		Float_t		cull	=	0.;
		diffuse.a = 1.- alpha;

		G3dSetMatt( hGC,  wMattNum, G3DM_AMBIENT,  (Float_t *)&ambient   );			
		G3dSetMatt( hGC,  wMattNum, G3DM_DIFFUSE,  (Float_t *)&diffuse   );			
		G3dSetMatt( hGC,  wMattNum, G3DM_SPECULAR, (Float_t *)&specular  );			
		G3dSetMatt( hGC,  wMattNum, G3DM_EMIT,     (Float_t *)&emit      );			
		G3dSetMatt( hGC,  wMattNum, G3DM_SHINE,    (Float_t *)&shine     );			
		G3dSetMatt( hGC,  wMattNum, G3DM_CULL,	   (Float_t *)&cull     );
		G3dSetMatt( hGC,  wMattNum, G3DM_ALPHA,    (Float_t *)&alpha     );

		G3dSetMatt( hGC,  wMattNum, G3DM_BACK_AMBIENT,  (Float_t *)&ambient   );			
		G3dSetMatt( hGC,  wMattNum, G3DM_BACK_DIFFUSE,  (Float_t *)&diffuse   );			
		G3dSetMatt( hGC,  wMattNum, G3DM_BACK_SPECULAR, (Float_t *)&specular  );			
		G3dSetMatt( hGC,  wMattNum, G3DM_BACK_EMIT,     (Float_t *)&emit      );			
		G3dSetMatt( hGC,  wMattNum, G3DM_BACK_SHINE,    (Float_t *)&shine     );			
		//G3dSetMatt( hGC,  wMattNum, G3DM_BACK_CULL,   	(Float_t *)&cull     );

		G3dSetCurrentMatt(hGC, wMattNum );	
		
		m_boolEmissive = IsBlack(ambient) && IsBlack(diffuse) && 
								IsBlack(specular);	// don't care whether emissive
									// is non zero - treat pure black as emissive
									// so i omitted this : !IsBlack(emit);		
		if(pboolEmissive)
		{
			*pboolEmissive 	= m_boolEmissive;	
		}
	}
	else if(pboolEmissive)
	{
		*pboolEmissive 	= 	m_boolEmissive;
	}
};
#else
void ChQvMaterialMap::SetMat(ChNrMesh mesh, ChNrFace face, int vertIndex, long index)
{
	long i = index;

	{
		m_lastI = i;
		ChColor	ambient;	
		ChColorA	diffuse;	
		ChColor	specular;	
		ChColor	emit;
		
		int iSpecular = m_pMat->specularColor.num ? i % m_pMat->specularColor.num : 0;		
		int iShininess = m_pMat->shininess.num ? i % m_pMat->shininess.num : 0;
				
		Qv2Native(m_pMat->ambientColor, i, ambient);
		Qv2Native(m_pMat->diffuseColor, i, diffuse);
		Qv2Native(m_pMat->specularColor, i, specular) ;
		Qv2Native(m_pMat->emissiveColor, i, emit);

		float	shine = 0;
		if(m_pMat->shininess.num)
		{
			shine = maxShininess * float(m_pMat->shininess.values[i % m_pMat->shininess.num]);
		}

								//  0 is opaque in vrml
								// alpha = 1.0, and color.a = 1.0 should be opaque in RL 
								// with typical blend functions
		float		alpha	=	1.;
		if(m_pMat->transparency.num)
		{
			alpha	=	1. - float(m_pMat->transparency.values[i % m_pMat->transparency.num]);
		}
		diffuse.SetAlpha(alpha);
		specular.SetAlpha(alpha);
		emit.SetAlpha(alpha);

		ChMaterial mat = GetMat(index);

		ChColor base = mat.GetBase();
		

		#if 0
		// This is quasi-official rule of how to handle; altho doc is ambiguous
		m_boolEmissive = IsBlack(ambient) && IsBlack(diffuse) && 
							IsBlack(specular) && !IsBlack(emit);
		#endif
 		//m_boolEmissive = (emit.r() + emit.g() + emit.b()) >= (diffuse.r() + diffuse.g() + diffuse.b());
		#if USE_FIRST_MOVING_WORLDS_PROPOSAL_DEFN
 		m_boolEmissive = m_pMat->emissiveColor.num > 0 && (emit.r() + emit.g() + emit.b()) > 0.0;
		#endif

		// This following is the VRML 1.0c defn, with the addition of completely ignoring ambient color and
		// as of 4/15/96, allowing black to act as empty

		bool boolEmissivePresent = (m_pMat->emissiveColor.num > 0 && (emit.r() + emit.g() + emit.b()) > 0.0);
		bool boolDiffusePresent = (m_pMat->diffuseColor.num > 0 && (diffuse.r() + diffuse.g() + diffuse.b()) > 0.0);
		bool boolSpecularPresent = (m_pMat->specularColor.num > 0 && (specular.r() + specular.g() + specular.b()) > 0.0);

 		m_boolEmissive = boolEmissivePresent && !boolDiffusePresent	&& !boolSpecularPresent;


		// Reality lab has no support for ambient, emissive, or specular colors
		// However, we can use the shine value for the power (like we do in 3dr), and make
		// an estiamte for the specular intensity ks by looking at the ratio
		// of specular to diffuse color intensities. First, if the surface is pure emissive,
		// revert to unlit for this mesh, and use emissive  for this color
		// Optimally, we'd look at all the materials for this mesh, but this is close
		// enough for now... Note that RL -doesn't- give us the option of just
		// making this face unlit; it's only as finegrained as a mesh.

		// Note that we also set the face color. THis means that if this mesh gets switched to
		// ColorByFace because of transparency or such, we are guaranteed each face is colored
		// to something reasonable
		#if 0 && defined(CH_USE_D3D)
		#else  
		if(m_boolEmissive)
		{
			ChNrMeshSetQuality(mesh, RenderUnlitFlat);
			ChNativeColor	emitColor = *emit.GetNative();
			if(vertIndex >= 0)
			{
				if(alpha >= 1.0)
				{
					ChNrMeshSetVertexColor(mesh, vertIndex, *emit.GetNative());
					ChNrFaceSetColor(face, *emit.GetNative());
				}
				else
				{
					ChNrMeshSetColorSource(mesh, ColorFromFace );
					ChNrFaceSetColor(face, *emit.GetNative());
				}
			}
			else
			{
				ChNrMeshSetColorSource(mesh, ColorFromFace );
				ChNrFaceSetColor(face, emitColor);
			}
		}
		else
		{
			if(vertIndex >= 0)
			{
				if(alpha >= 1.0)
				{
					ChNrFaceSetColor(face, *base.GetNative());
					ChNrMeshSetVertexColor(mesh, vertIndex, *base.GetNative());
				}
				else
				{
					ChNrMeshSetColorSource(mesh, ColorFromFace );
					ChNrFaceSetColor(face, *base.GetNative());
				}
			}
			else
			{
				ChNrFaceSetColor(face, *base.GetNative());
			}
		}

		if(!m_boolEmissive)
		{
								//Only look at first
								// vertex for the material - only one per face allowed
			float ks = 0;
			#if (defined(CH_USE_RLAB))

			ks =  (specular.r() + specular.g() + specular.b()) / 3.;

			if(ks > 0)				 // RL emissive doesn't matter
			#elif (defined(CH_USE_D3D))
			if(!specular.IsBlack() || !emit.IsBlack())	  // In d3d we can mix in emissive on a face
			#endif
			{
				ChNrMaterial material = 0;

				// Find the cached material if any
				#if (defined(CH_USE_RLAB))
				unsigned long lKey = (unsigned long)iSpecular | ((unsigned long)iShininess << 16);
				ChNrMaterial *pMaterial = m_materialCache.Find(lKey);
				if(pMaterial) material = *pMaterial;
				#elif (defined(CH_USE_D3D))
				// On D3D we cache on the material node's render data
				ChQvMaterialRenderData *pData = (ChQvMaterialRenderData *)(m_pMat->GetRenderData());
				material = pData->Find(index);
				#endif

				ChNrMaterial tmpMat = 0;
				if(face) ChNrFaceGetMaterial(face, &tmpMat);
				if((face && !tmpMat) || !face)
				{
					if(m_pRC && !material)
					{
						material = m_pRC->CreateMaterial(ks, shine);
						#if (defined(CH_USE_RLAB))
						m_materialCache.Insert(lKey, material);
						#elif (defined(CH_USE_D3D))
						// ks is ignored in d3d, but we can set colors
						material->SetEmissive(emit.r(), emit.g(), emit.b());
						material->SetSpecular(specular.r(), specular.g(), specular.b());
						pData->Add(index, material);
						#endif
					}
					if(face)
					{
		
						ChNrFaceSetMaterial(face, material);
					}
					else
					{
		
						ChNrMeshSetMaterial(mesh, material);
					}
				}
				D3DRelease(tmpMat);
			}
		}			
		#endif
	}
};
#endif

#if (defined(CH_USE_RLAB)) || defined(CH_USE_D3D)
ChMaterial ChQvMaterialMap::GetMat( long index )
{
	long i = index;
	ChMaterial mat;
	// Wrap indexing at array length 
	Qv2Native(m_pMat->ambientColor, i, mat.m_ambient);
	Qv2Native(m_pMat->diffuseColor, i, mat.m_diffuse);
	Qv2Native(m_pMat->specularColor, i, mat.m_specular) ;
	Qv2Native(m_pMat->emissiveColor, i, mat.m_emissive);

	if(m_pMat->shininess.num)
	{
		mat.m_shininess = float(m_pMat->shininess.values[i % m_pMat->shininess.num]);
	}
	else
	{
		mat.m_shininess = 0;
	}

							//  0 is opaque in vrml
							// alpha = 0.0, but color.a = 1.0 should be opaque in RL 
							// with typical blend functions
	if(m_pMat->transparency.num)
	{
		mat.m_transparency	=	float(m_pMat->transparency.values[i % m_pMat->transparency.num]);
	}
	else

⌨️ 快捷键说明

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