mirror of
https://github.com/Gigaslav/HL2Overcharged.git
synced 2026-09-04 11:44:45 +03:00
602 lines
16 KiB
C++
602 lines
16 KiB
C++
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================
|
|
#include "cbase.h"
|
|
// identifier was truncated to '255' characters in the debug information
|
|
#pragma warning(disable: 4786)
|
|
|
|
#include "ProxyEntity.h"
|
|
#include "materialsystem/IMaterialVar.h"
|
|
#include "materialsystem/ITexture.h"
|
|
#include "bitmap/TGAWriter.h"
|
|
#include "bitmap/TGALoader.h"
|
|
#include "view.h"
|
|
#include "materialsystem/IMaterial.h"
|
|
//#include "cache_user.h"
|
|
#include "vtf/vtf.h"
|
|
|
|
|
|
class CCamoMaterialProxy;
|
|
|
|
class CCamoTextureRegen : public ITextureRegenerator
|
|
{
|
|
public:
|
|
CCamoTextureRegen(CCamoMaterialProxy *pProxy) : m_pProxy(pProxy) {}
|
|
virtual void RegenerateTextureBits(ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pSubRect);
|
|
virtual void Release() {}
|
|
|
|
private:
|
|
CCamoMaterialProxy *m_pProxy;
|
|
};
|
|
|
|
class CCamoMaterialProxy : public CEntityMaterialProxy
|
|
{
|
|
public:
|
|
CCamoMaterialProxy();
|
|
virtual ~CCamoMaterialProxy();
|
|
virtual bool Init(IMaterial *pMaterial, KeyValues *pKeyValues);
|
|
virtual void OnBind(C_BaseEntity *pC_BaseEntity);
|
|
virtual IMaterial *GetMaterial();
|
|
// Procedurally generates the camo texture...
|
|
void GenerateCamoTexture(ITexture* pTexture, IVTFTexture *pVTFTexture);
|
|
|
|
protected:
|
|
#if 0
|
|
virtual void SetInstanceDataSize(int size);
|
|
virtual void *FindInstanceData(C_BaseEntity *pEntity);
|
|
virtual void *AllocateInstanceData(C_BaseEntity *pEntity);
|
|
#endif
|
|
|
|
private:
|
|
void LoadCamoPattern(void);
|
|
void GenerateRandomPointsInNormalizedCube(void);
|
|
void GetColors(Vector &lighting, Vector &base, int index,
|
|
const Vector &boxMin, const Vector &boxExtents,
|
|
const Vector &forward, const Vector &right, const Vector &up,
|
|
const Vector& entityPosition);
|
|
// this needs to go in a base class
|
|
|
|
private:
|
|
#if 0
|
|
// stuff that needs to be in a base class.
|
|
struct InstanceData_t
|
|
{
|
|
C_BaseEntity *pEntity;
|
|
void *data;
|
|
struct InstanceData_s *next;
|
|
};
|
|
|
|
struct CamoInstanceData_t
|
|
{
|
|
int dummy;
|
|
};
|
|
#endif
|
|
|
|
unsigned char *m_pCamoPatternImage;
|
|
|
|
#if 0
|
|
int m_InstanceDataSize;
|
|
InstanceData_t *m_InstanceDataListHead;
|
|
#endif
|
|
|
|
IMaterial *m_pMaterial;
|
|
IMaterialVar *m_pCamoTextureVar;
|
|
IMaterialVar *m_pCamoPatternTextureVar;
|
|
Vector *m_pointsInNormalizedBox; // [m_CamoPatternNumColors]
|
|
|
|
int m_CamoPatternNumColors;
|
|
int m_CamoPatternWidth;
|
|
int m_CamoPatternHeight;
|
|
#if 0
|
|
cache_user_t m_camoImageDataCache;
|
|
#endif
|
|
unsigned char m_CamoPalette[256][3];
|
|
// these represent that part of the entitiy's bounding box that we
|
|
// want to cast rays through to get colors for the camo
|
|
Vector m_SubBoundingBoxMin; // normalized
|
|
Vector m_SubBoundingBoxMax; // normalized
|
|
|
|
CCamoTextureRegen m_TextureRegen;
|
|
C_BaseEntity *m_pEnt;
|
|
|
|
// VXP
|
|
ITexture *pCamoTexture; // VXP: Made this because of GetTextureValue cannot do shit at destructor
|
|
};
|
|
|
|
|
|
void CCamoTextureRegen::RegenerateTextureBits(ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pSubRect)
|
|
{
|
|
pVTFTexture->ConvertImageFormat(IMAGE_FORMAT_RGB888, false); // VXP: FIXME: May this decrease performance?
|
|
m_pProxy->GenerateCamoTexture(pTexture, pVTFTexture);
|
|
}
|
|
|
|
|
|
#pragma warning (disable:4355)
|
|
|
|
CCamoMaterialProxy::CCamoMaterialProxy() : m_TextureRegen(this)
|
|
{
|
|
#if 0
|
|
m_InstanceDataSize = 0;
|
|
#endif
|
|
#if 0
|
|
memset(&m_camoImageDataCache, 0, sizeof(m_camoImageDataCache));
|
|
#endif
|
|
m_pointsInNormalizedBox = NULL;
|
|
#if 0
|
|
m_InstanceDataListHead = NULL;
|
|
#endif
|
|
m_pCamoPatternImage = NULL;
|
|
m_pMaterial = NULL;
|
|
m_pCamoTextureVar = NULL;
|
|
m_pCamoPatternTextureVar = NULL;
|
|
m_pointsInNormalizedBox = NULL;
|
|
m_pEnt = NULL;
|
|
}
|
|
|
|
#pragma warning (default:4355)
|
|
|
|
CCamoMaterialProxy::~CCamoMaterialProxy()
|
|
{
|
|
#if 0
|
|
InstanceData_t *curr = m_InstanceDataListHead;
|
|
while (curr)
|
|
{
|
|
InstanceData_t *next;
|
|
next = curr->next;
|
|
delete curr;
|
|
curr = next;
|
|
}
|
|
m_InstanceDataListHead = NULL;
|
|
#endif
|
|
|
|
// Disconnect the texture regenerator...
|
|
if (m_pCamoTextureVar)
|
|
{
|
|
// ITexture *pCamoTexture = m_pCamoTextureVar->GetTextureValue();
|
|
if (pCamoTexture)
|
|
{
|
|
pCamoTexture->SetTextureRegenerator(NULL);
|
|
|
|
// VXP
|
|
pCamoTexture->DecrementReferenceCount();
|
|
pCamoTexture = NULL;
|
|
}
|
|
|
|
m_pCamoTextureVar = NULL; // VXP
|
|
}
|
|
|
|
if (m_pCamoPatternImage != NULL)
|
|
{
|
|
delete[] m_pCamoPatternImage; // VXP: Was w/o []
|
|
m_pCamoPatternImage = NULL;
|
|
}
|
|
|
|
if (m_pointsInNormalizedBox != NULL)
|
|
{
|
|
delete[] m_pointsInNormalizedBox; // VXP: Was w/o []
|
|
m_pointsInNormalizedBox = NULL;
|
|
}
|
|
}
|
|
|
|
IMaterial *CCamoMaterialProxy::GetMaterial()
|
|
{
|
|
return NULL;
|
|
}
|
|
#if 0
|
|
void CCamoMaterialProxy::SetInstanceDataSize(int size)
|
|
{
|
|
m_InstanceDataSize = size;
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
void *CCamoMaterialProxy::FindInstanceData(C_BaseEntity *pEntity)
|
|
{
|
|
InstanceData_t *curr = m_InstanceDataListHead;
|
|
while (curr)
|
|
{
|
|
if (pEntity == curr->pEntity)
|
|
{
|
|
return curr->data;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
void *CCamoMaterialProxy::AllocateInstanceData(C_BaseEntity *pEntity)
|
|
{
|
|
InstanceData_t *newData = new InstanceData_t;
|
|
newData->pEntity = pEntity;
|
|
newData->next = m_InstanceDataListHead;
|
|
m_InstanceDataListHead = newData;
|
|
newData->data = new unsigned char[m_InstanceDataSize];
|
|
return newData->data;
|
|
}
|
|
#endif
|
|
|
|
bool CCamoMaterialProxy::Init(IMaterial *pMaterial, KeyValues *pKeyValues)
|
|
{
|
|
// return false; // hack! Need to make sure that the TGA loader has a valid filesystem before trying
|
|
// to load the camo pattern.
|
|
|
|
#if 0
|
|
// set how big our instance data is.
|
|
SetInstanceDataSize(sizeof(CamoInstanceData_t));
|
|
#endif
|
|
// remember what material we belong to.
|
|
m_pMaterial = pMaterial;
|
|
// get pointers to material vars.
|
|
bool found;
|
|
m_pCamoTextureVar = m_pMaterial->FindVar("$baseTexture", &found);
|
|
if (!found)
|
|
{
|
|
m_pCamoTextureVar = NULL;
|
|
Warning("Cannot initialize Camo because of $baseTexture\n");
|
|
return false;
|
|
}
|
|
// ITexture *pCamoTexture = m_pCamoTextureVar->GetTextureValue();
|
|
pCamoTexture = m_pCamoTextureVar->GetTextureValue();
|
|
if (pCamoTexture)
|
|
pCamoTexture->SetTextureRegenerator(&m_TextureRegen);
|
|
|
|
// Need to get the palettized texture to create the procedural texture from
|
|
// somewhere.
|
|
m_pCamoPatternTextureVar = m_pMaterial->FindVar("$camoPatternTexture", &found);
|
|
if (!found)
|
|
{
|
|
m_pCamoTextureVar = NULL;
|
|
Warning("Cannot initialize Camo because of $camoPatternTexture\n");
|
|
return false;
|
|
}
|
|
|
|
IMaterialVar *subBoundingBoxMinVar, *subBoundingBoxMaxVar;
|
|
|
|
subBoundingBoxMinVar = m_pMaterial->FindVar("$camoBoundingBoxMin", &found, false);
|
|
if (!found)
|
|
{
|
|
m_SubBoundingBoxMin = Vector(0.0f, 0.0f, 0.0f);
|
|
}
|
|
else
|
|
{
|
|
subBoundingBoxMinVar->GetVecValue(m_SubBoundingBoxMin.Base(), 3);
|
|
}
|
|
|
|
subBoundingBoxMaxVar = m_pMaterial->FindVar("$camoBoundingBoxMax", &found, false);
|
|
if (!found)
|
|
{
|
|
m_SubBoundingBoxMax = Vector(1.0f, 1.0f, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
subBoundingBoxMaxVar->GetVecValue(m_SubBoundingBoxMax.Base(), 3);
|
|
}
|
|
|
|
LoadCamoPattern();
|
|
GenerateRandomPointsInNormalizedCube();
|
|
|
|
return true;
|
|
}
|
|
|
|
void CCamoMaterialProxy::GetColors(Vector &diffuseColor, Vector &baseColor, int index,
|
|
const Vector &boxMin, const Vector &boxExtents,
|
|
const Vector &forward, const Vector &right, const Vector &up,
|
|
const Vector& entityPosition)
|
|
{
|
|
Vector position, transformedPosition;
|
|
|
|
// hack
|
|
// m_pointsInNormalizedBox[index] = Vector( 0.5f, 0.5f, 1.0f );
|
|
|
|
position[0] = m_pointsInNormalizedBox[index][0] * boxExtents[0] + boxMin[0];
|
|
position[1] = m_pointsInNormalizedBox[index][1] * boxExtents[1] + boxMin[1];
|
|
position[2] = m_pointsInNormalizedBox[index][2] * boxExtents[2] + boxMin[2];
|
|
transformedPosition[0] = right[0] * position[0] + forward[0] * position[1] + up[0] * position[2];
|
|
transformedPosition[1] = right[1] * position[0] + forward[1] * position[1] + up[1] * position[2];
|
|
transformedPosition[2] = right[2] * position[0] + forward[2] * position[1] + up[2] * position[2];
|
|
transformedPosition = transformedPosition + entityPosition;
|
|
Vector direction = transformedPosition - CurrentViewOrigin();
|
|
VectorNormalize(direction);
|
|
direction = direction * (COORD_EXTENT * 1.74f);
|
|
Vector endPoint = position + direction;
|
|
|
|
// baseColor is already in gamma space
|
|
// engine->TraceLineMaterialAndLighting( g_vecInstantaneousRenderOrigin, endPoint, diffuseColor, baseColor );
|
|
engine->TraceLineMaterialAndLighting(transformedPosition, endPoint, diffuseColor, baseColor);
|
|
|
|
// hack - optimize! - convert from linear to gamma space - this should be hidden
|
|
diffuseColor[0] = pow(diffuseColor[0], 1.0f / 2.2f);
|
|
diffuseColor[1] = pow(diffuseColor[1], 1.0f / 2.2f);
|
|
diffuseColor[2] = pow(diffuseColor[2], 1.0f / 2.2f);
|
|
|
|
#if 0
|
|
Msg("%f %f %f\n",
|
|
diffuseColor[0],
|
|
diffuseColor[1],
|
|
diffuseColor[2]);
|
|
#endif
|
|
|
|
#if 0
|
|
float max;
|
|
max = diffuseColor[0];
|
|
if (diffuseColor[1] > max)
|
|
{
|
|
max = diffuseColor[1];
|
|
}
|
|
if (diffuseColor[2] > max)
|
|
{
|
|
max = diffuseColor[2];
|
|
}
|
|
if (max > 1.0f)
|
|
{
|
|
max = 1.0f / max;
|
|
diffuseColor = diffuseColor * max;
|
|
}
|
|
#else
|
|
if (diffuseColor[0] > 1.0f)
|
|
{
|
|
diffuseColor[0] = 1.0f;
|
|
}
|
|
if (diffuseColor[1] > 1.0f)
|
|
{
|
|
diffuseColor[1] = 1.0f;
|
|
}
|
|
if (diffuseColor[2] > 1.0f)
|
|
{
|
|
diffuseColor[2] = 1.0f;
|
|
}
|
|
#endif
|
|
// hack
|
|
//baseColor = Vector( 1.0f, 1.0f, 1.0f );
|
|
//diffuseColor = Vector( 1.0f, 1.0f, 1.0f );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Procedurally generates the camo texture...
|
|
//-----------------------------------------------------------------------------
|
|
void CCamoMaterialProxy::GenerateCamoTexture(ITexture* pTexture, IVTFTexture *pVTFTexture)
|
|
{
|
|
if (!m_pEnt)
|
|
return;
|
|
|
|
#if 0
|
|
CamoInstanceData_t *pInstanceData;
|
|
pInstanceData = (CamoInstanceData_t *)FindInstanceData(pEnt);
|
|
if (!pInstanceData)
|
|
{
|
|
pInstanceData = (CamoInstanceData_t *)AllocateInstanceData(pEnt);
|
|
if (!pInstanceData)
|
|
{
|
|
return;
|
|
}
|
|
// init the instance data
|
|
}
|
|
#endif
|
|
|
|
Vector entityPosition;
|
|
entityPosition = m_pEnt->GetAbsOrigin();
|
|
|
|
QAngle entityAngles;
|
|
entityAngles = m_pEnt->GetAbsAngles();
|
|
|
|
// Get the bounding box for the entity
|
|
Vector mins, maxs;
|
|
mins = m_pEnt->WorldAlignMins();
|
|
maxs = m_pEnt->WorldAlignMaxs();
|
|
|
|
Vector traceDirection;
|
|
Vector traceEnd;
|
|
trace_t traceResult;
|
|
|
|
Vector forward, right, up;
|
|
AngleVectors(entityAngles, &forward, &right, &up);
|
|
|
|
Vector position, transformedPosition;
|
|
Vector maxsMinusMins = maxs - mins;
|
|
|
|
Vector diffuseColor[256];
|
|
Vector baseColor;
|
|
|
|
unsigned char camoPalette[256][3];
|
|
// Calculate the camo palette
|
|
//Msg( "start of loop\n" );
|
|
int i;
|
|
for (i = 0; i < m_CamoPatternNumColors; i++)
|
|
{
|
|
GetColors(diffuseColor[i], baseColor, i,
|
|
mins, maxsMinusMins, forward, right, up, entityPosition);
|
|
#if 1
|
|
camoPalette[i][0] = diffuseColor[i][0] * baseColor[0] * 255.0f;
|
|
camoPalette[i][1] = diffuseColor[i][1] * baseColor[1] * 255.0f;
|
|
camoPalette[i][2] = diffuseColor[i][2] * baseColor[2] * 255.0f;
|
|
#endif
|
|
#if 0
|
|
camoPalette[i][0] = baseColor[0] * 255.0f;
|
|
camoPalette[i][1] = baseColor[1] * 255.0f;
|
|
camoPalette[i][2] = baseColor[2] * 255.0f;
|
|
#endif
|
|
#if 0
|
|
camoPalette[i][0] = diffuseColor[i][0] * 255.0f;
|
|
camoPalette[i][1] = diffuseColor[i][1] * 255.0f;
|
|
camoPalette[i][2] = diffuseColor[i][2] * 255.0f;
|
|
#endif
|
|
}
|
|
|
|
int width = pVTFTexture->Width();
|
|
int height = pVTFTexture->Height();
|
|
if (width != m_CamoPatternWidth || height != m_CamoPatternHeight)
|
|
{
|
|
Warning("Can't generate camo texture, wrong sizes\n");
|
|
return;
|
|
}
|
|
|
|
unsigned char *imageData = pVTFTexture->ImageData(0, 0, 0);
|
|
enum ImageFormat imageFormat = pVTFTexture->Format();
|
|
if (imageFormat != IMAGE_FORMAT_RGB888)
|
|
{
|
|
Warning("Can't generate camo texture, need to be RGB888\n");
|
|
return;
|
|
}
|
|
// optimize
|
|
#if 1
|
|
int x, y;
|
|
for (y = 0; y < height; y++)
|
|
{
|
|
for (x = 0; x < width; x++)
|
|
{
|
|
int offset = 3 * (x + y * width);
|
|
assert(offset < width * height * 3);
|
|
int paletteID = m_pCamoPatternImage[x + y * width];
|
|
assert(paletteID < 256);
|
|
#if 1
|
|
imageData[offset + 0] = camoPalette[paletteID][0];
|
|
imageData[offset + 1] = camoPalette[paletteID][1];
|
|
imageData[offset + 2] = camoPalette[paletteID][2];
|
|
#else
|
|
imageData[offset] = 255;
|
|
imageData[offset + 1] = 0;
|
|
imageData[offset + 2] = 0;
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Called when the texture is bound...
|
|
//-----------------------------------------------------------------------------
|
|
void CCamoMaterialProxy::OnBind(C_BaseEntity *pEntity)
|
|
{
|
|
if (!m_pCamoTextureVar)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_pEnt = pEntity;
|
|
// ITexture *pCamoTexture = m_pCamoTextureVar->GetTextureValue();
|
|
if (pCamoTexture)
|
|
pCamoTexture->Download();
|
|
|
|
// Mark it so it doesn't get regenerated on task switch
|
|
m_pEnt = NULL;
|
|
}
|
|
|
|
void CCamoMaterialProxy::LoadCamoPattern(void)
|
|
{
|
|
#if 0
|
|
// hack - need to figure out a name to attach that isn't too long.
|
|
m_pCamoPatternImage =
|
|
(unsigned char *)engineCache->FindByName(&m_camoImageDataCache, "camopattern");
|
|
|
|
if (m_pCamoPatternImage)
|
|
{
|
|
// is already in the cache.
|
|
return m_pCamoPatternImage;
|
|
}
|
|
#endif
|
|
|
|
enum ImageFormat indexImageFormat;
|
|
int indexImageSize;
|
|
float dummyGamma;
|
|
if (!TGALoader::GetInfo(m_pCamoPatternTextureVar->GetStringValue(),
|
|
&m_CamoPatternWidth, &m_CamoPatternHeight, &indexImageFormat, &dummyGamma))
|
|
{
|
|
//Warning( "Can't get tga info for hl2/materials/models/combine_elite/camo7paletted.tga for camo material\n" );
|
|
Warning("Can't get tga info for %s for camo material\n", m_pCamoPatternTextureVar->GetStringValue());
|
|
m_pCamoTextureVar = NULL;
|
|
return;
|
|
}
|
|
|
|
if (indexImageFormat != IMAGE_FORMAT_I8)
|
|
{
|
|
// Warning( "Camo material texture hl2/materials/models/combine_elite/camo7paletted.tga must be 8-bit greyscale\n" );
|
|
Warning("Camo material texture %s must be 8-bit greyscale\n", m_pCamoPatternTextureVar->GetStringValue());
|
|
m_pCamoTextureVar = NULL;
|
|
return;
|
|
}
|
|
|
|
indexImageSize = ImageLoader::GetMemRequired(m_CamoPatternWidth, m_CamoPatternHeight, 1, indexImageFormat, false);
|
|
DevMsg("indexImageSize = %i\n", indexImageSize);
|
|
#if 0
|
|
m_pCamoPatternImage = (unsigned char *)
|
|
engineCache->Alloc(&m_camoImageDataCache, indexImageSize, "camopattern");
|
|
#endif
|
|
m_pCamoPatternImage = (unsigned char *)new unsigned char[indexImageSize];
|
|
if (!m_pCamoPatternImage)
|
|
{
|
|
m_pCamoTextureVar = NULL;
|
|
Warning("Cannot read pattern from tga for Camo proxy\n");
|
|
return;
|
|
}
|
|
|
|
if (!TGALoader::Load(m_pCamoPatternImage, m_pCamoPatternTextureVar->GetStringValue(),
|
|
m_CamoPatternWidth, m_CamoPatternHeight, IMAGE_FORMAT_I8, dummyGamma, false))
|
|
{
|
|
// Warning( "camo texture hl2/materials/models/combine_elite/camo7paletted.tga must be grey-scale" );
|
|
Warning("camo texture %s must be grey-scale\n", m_pCamoPatternTextureVar->GetStringValue());
|
|
m_pCamoTextureVar = NULL;
|
|
return;
|
|
}
|
|
|
|
bool colorUsed[256];
|
|
int colorRemap[256];
|
|
// count the number of colors used in the image.
|
|
int i;
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
colorUsed[i] = false;
|
|
}
|
|
for (i = 0; i < indexImageSize; i++)
|
|
{
|
|
colorUsed[m_pCamoPatternImage[i]] = true;
|
|
}
|
|
m_CamoPatternNumColors = 0;
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
if (colorUsed[i])
|
|
{
|
|
colorRemap[i] = m_CamoPatternNumColors;
|
|
m_CamoPatternNumColors++;
|
|
}
|
|
}
|
|
// remap the color to the beginning of the palette.
|
|
for (i = 0; i < indexImageSize; i++)
|
|
{
|
|
m_pCamoPatternImage[i] = colorRemap[m_pCamoPatternImage[i]];
|
|
// hack
|
|
// m_pCamoPatternImage[i] = 0;
|
|
}
|
|
}
|
|
|
|
void CCamoMaterialProxy::GenerateRandomPointsInNormalizedCube(void)
|
|
{
|
|
if (m_CamoPatternNumColors <= 0)
|
|
{
|
|
Warning("Cannot generate random point for Camo proxy\n");
|
|
return;
|
|
}
|
|
|
|
m_pointsInNormalizedBox = new Vector[m_CamoPatternNumColors];
|
|
if (!m_pointsInNormalizedBox)
|
|
{
|
|
m_pCamoTextureVar = NULL;
|
|
return;
|
|
}
|
|
|
|
int i;
|
|
for (i = 0; i < m_CamoPatternNumColors; i++)
|
|
{
|
|
m_pointsInNormalizedBox[i][0] = random->RandomFloat(m_SubBoundingBoxMin[0], m_SubBoundingBoxMax[0]);
|
|
m_pointsInNormalizedBox[i][1] = random->RandomFloat(m_SubBoundingBoxMin[1], m_SubBoundingBoxMax[1]);
|
|
m_pointsInNormalizedBox[i][2] = random->RandomFloat(m_SubBoundingBoxMin[2], m_SubBoundingBoxMax[2]);
|
|
}
|
|
}
|
|
|
|
EXPOSE_INTERFACE(CCamoMaterialProxy, IMaterialProxy, "Camo" IMATERIAL_PROXY_INTERFACE_VERSION); |