/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef __HSMATERIALCONVERTER_H
#define __HSMATERIALCONVERTER_H
#include "HeadSpin.h"
#include "hsTemplates.h"
#include "Max.h"
class Interface;
class hsStream;
class hsScene;
class hsGMaterial;
class plLayer;
class plLayerInterface;
class hsGBitmapClass;
class hsGQTLayer;
class hsGAVILayer;
class hsGBinkLayer;
class hsConverterUtils;
class hsGAnimLayer;
class plBitmap;
class plMipmap;
class plErrorMsg;
class Mtl;
class Texmap;
class plMaxNode;
class StdUVGen;
class BitmapTex;
class StdMat;
class TSTR;
class Animatable;
class Bitmap;
class plLocation;
class plLayerTex;
class plBitmapData;
class plCubicRenderTarget;
class plStaticEnvLayer;
class plDynamicEnvLayer;
class plDynamicTextLayer;
class plPassMtlBase;
class plClothingItem;
class plClothingMtl;
class hsBitVector;
class plExportMaterialData
{
public:
UInt32 fNumBlendChannels;
hsGMaterial *fMaterial;
};
class hsMaterialConverter
{
private:
hsMaterialConverter();
public:
~hsMaterialConverter();
static hsMaterialConverter& Instance();
void Init(hsBool save, plErrorMsg *msg);
void FreeMaterialCache(const char* path);
static void GetUsedMaterials(plMaxNode* node, hsBitVector& used);
static hsBool IsTwoSided(Mtl* m, int iFace);
static hsBool PreserveUVOffset(Mtl* m);
static hsBool IsMultiMat(Mtl *m);
static hsBool IsMultipassMat(Mtl *m);
static hsBool IsHsMaxMat(Mtl *m);
static hsBool IsDecalMat(Mtl *m);
static hsBool IsCompositeMat(Mtl *m);
static hsBool IsParticleMat(Mtl *m);
static hsBool IsHsEnvironMapMat(Mtl *m);
static hsBool IsClothingMat(Mtl *m);
// static hsBool IsPortalMat(Mtl *m);
static hsBool HasAnimatedTextures(Texmap* texMap);
static hsBool HasAnimatedMaterial(plMaxNode* node);
static hsBool IsAnimatedMaterial(Mtl* mtl);
static hsBool HasMaterialDiffuseOrOpacityAnimation(plMaxNode* node, Mtl* mtl=nil);
static hsBool HasEmissiveLayer(plMaxNode* node, Mtl* mtl=nil);
static hsBool IsWaterLayer(plMaxNode* node, Texmap* texMap);
static hsBool IsFireLayer(plMaxNode* node, Texmap* texMap);
static hsBool IsAVILayer(Texmap* texMap);
static hsBool IsQTLayer(Texmap* texMap);
static hsBool IsBinkLayer(Texmap* texMap);
// static hsBool IsEnvironMapped(plMaxNode *node);
// static hsBool IsPortal(plMaxNode* node);
static hsBool ForceNoUvsFlatten(plMaxNode* node);
// static hsBool IsRenderProc(Mtl* mtl);
static Mtl* GetBaseMtl(Mtl* mtl);
static Mtl* GetBaseMtl(plMaxNode* node);
static int GetCoordMapping(StdUVGen *uvgen);
static void GetNodesByMaterial(Mtl *mtl, hsTArray &out);
static UInt32 VertexChannelsRequestMask(plMaxNode* node, int iSubMtl, Mtl* mtl);
static UInt32 VertexChannelsRequiredMask(plMaxNode* node, int iSubMtl);
static int NumVertexOpacityChannelsRequired(plMaxNode* node, int iSubMtl);
static UInt32 ColorChannelsUseMask(plMaxNode* node, int iSubMtl);
static int MaxUsedUVWSrc(plMaxNode* node, Mtl* mtl);
static hsBool IsBumpLayer(Texmap* texMap);
static hsBool IsBumpMtl(Mtl* mtl);
static hsBool HasBumpLayer(plMaxNode* node, Mtl* mtl);
static BitmapTex* GetBumpLayer(plMaxNode* node, Mtl* mtl);
static hsBool HasVisDists(plMaxNode* node, Mtl* subMtl, hsScalar& minDist, hsScalar& maxDist);
static hsBool HasVisDists(plMaxNode* node, int iSubMtl, hsScalar& minDist, hsScalar& maxDist);
static hsBool IMustBeUniqueMaterial( Mtl *mtl );
static hsBool IMustBeUniqueLayer( Texmap *layer );
static Mtl* FindSubMtlByName(TSTR& name, Animatable* anim);
Mtl* FindSceneMtlByName(TSTR& name);
hsTArray *CreateMaterialArray(Mtl *maxMaterial, plMaxNode *node, UInt32 multiIndex);
// true if last material creation changed MAX time, invalidating current mesh
hsBool ChangedTimes() { return fChangedTimes; }
Texmap *GetUVChannelBase(plMaxNode *node, Mtl* mtl, int which);
hsBool ClearDoneMaterials(plMaxNode* node);
int GetMaterialArray(Mtl *mtl, plMaxNode* node, hsTArray& out, UInt32 multiIndex = 0 );
int GetMaterialArray(Mtl *mtl, hsTArray& out, UInt32 multiIndex = 0);
void CollectConvertedMaterials(Mtl *mtl, hsTArray &out);
plClothingItem *GenerateClothingItem(plClothingMtl *mtl, const plLocation &loc);
hsGMaterial* AlphaHackVersion(plMaxNode* node, Mtl* mtl, int subIndex); // used by DynamicDecals
hsGMaterial* NonAlphaHackVersion(plMaxNode* node, Mtl* mtl, int subIndex);
hsGMaterial* AlphaHackPrint(plMaxNode* node, Texmap* baseTex, UInt32 blendFlags);
hsGMaterial* NonAlphaHackPrint(plMaxNode* node, Texmap* baseTex, UInt32 blendFlags);
plMipmap* GetStaticColorTexture(Color c, plLocation &loc); // Creates a 4x4 texture of the specified solid color;
enum {
kColorRedBlack = 0x1,
kColorRedGrey = 0x2,
kColorRedWhite = 0x4,
kColorRed = kColorRedBlack | kColorRedGrey | kColorRedWhite,
kColorGreenBlack = 0x8,
kColorGreenGrey = 0x10,
kColorGreenWhite = 0x20,
kColorGreen = kColorGreenBlack | kColorGreenGrey | kColorGreenWhite,
kColorBlueBlack = 0x40,
kColorBlueGrey = 0x80,
kColorBlueWhite = 0x100,
kColorBlue = kColorBlueBlack | kColorBlueGrey | kColorBlueWhite,
kColor = kColorRed | kColorGreen | kColorBlue,
kIllumRedBlack = 0x200,
kIllumRedGrey = 0x400,
kIllumRedWhite = 0x800,
kIllumRed = kIllumRedBlack | kIllumRedGrey | kIllumRedWhite,
kIllumGreenBlack = 0x1000,
kIllumGreenGrey = 0x2000,
kIllumGreenWhite = 0x4000,
kIllumGreen = kIllumGreenBlack | kIllumGreenGrey | kIllumGreenWhite,
kIllumBlueBlack = 0x8000,
kIllumBlueGrey = 0x10000,
kIllumBlueWhite = 0x20000,
kIllumBlue = kIllumBlueBlack | kIllumBlueGrey | kIllumBlueWhite,
kIllum = kIllumRed | kIllumGreen | kIllumBlue,
kAlphaBlack = 0x40000,
kAlphaGrey = 0x80000,
kAlphaWhite = 0x100000,
kAlpha = kAlphaBlack | kAlphaGrey | kAlphaWhite,
kAllChannels = kColor | kIllum | kAlpha // Adjust if more channels added.
};
// All this to catch duplicate mats with same name. Sigh.
struct DoneMaterialData
{
DoneMaterialData() : fHsMaterial(nil), fMaxMaterial(nil), fNode(nil),
fSubMultiMat(false), fOwnedCopy(false) { }
hsGMaterial *fHsMaterial;
Mtl *fMaxMaterial;
plMaxNode *fNode;
hsBool fSubMultiMat;
hsBool fOwnedCopy;
hsBool fRuntimeLit;
UInt32 fSubMtlFlags;
int fNumUVChannels;
hsBool fMakeAlphaLayer;
};
private:
enum {
kWarnedNoMoreDub = 0x1,
kWarnedNoMoreMult = 0x2,
kWarnedNoMoreBitmapLoadErr = 0x4,
kWarnedSubMulti = 0x8,
kWarnedCompMtlBadBlend = 0x10,
kWarnedNoLayers = 0x20,
kWarnedTooManyUVs = 0x40,
kWarnedAlphaAddCombo = 0x80,
kWarnedNoBaseTexture = 0x100,
kWarnedNoUpperTexture = 0x200,
kWarnedUpperTextureMissing = 0x400,
kWarnedMissingClothingTexture = 0x800,
kWarnedBadAnimSDLVarName = 0x1000,
};
DoneMaterialData* IFindDoneMaterial(DoneMaterialData& done);
hsBool IClearDoneMaterial(Mtl* mtl, plMaxNode* node);
hsGMaterial *IAddDefaultMaterial(plMaxNode *node);
plMipmap *IGetUVTransTexture(plMaxNode *node, hsBool useU = true);
void IInsertSingleBlendLayer(plMipmap *texture, hsGMaterial *mat, plMaxNode *node,
int layerIdx, int UVChan);
hsGMaterial *ICreateMaterial(Mtl *mtl, plMaxNode *node, const char *name, int subIndex, int numUVChannels, hsBool makeAlphaLayer);
hsGMaterial *IProcessMaterial(Mtl *mtl, plMaxNode *node, const char *name, int UVChan, int subMtlFlags = 0);
// ... calls one of:
hsGMaterial *IProcessMultipassMtl(Mtl *mtl, plMaxNode *node, const char *name, int UVChan);
hsGMaterial *IProcessCompositeMtl(Mtl *mtl, plMaxNode *node, const char *name, int UVChan, int subMtlFlags);
hsGMaterial *IProcessParticleMtl(Mtl *mtl, plMaxNode *node, const char *name);
hsBool IProcessPlasmaMaterial(Mtl *mtl, plMaxNode *node, hsGMaterial *mat, const char* namePrefix);
hsGMaterial* IInsertDoneMaterial(Mtl *mtl, hsGMaterial *hMat, plMaxNode *node, hsBool isMultiMat,
hsBool forceCopy, hsBool runtimeLit, UInt32 subMtlFlags, int numUVChannels, hsBool makeAlphaLayer);
void IInsertBumpLayers(plMaxNode* node, hsGMaterial* mat, int bumpLayerIdx);
void IInsertBumpLayers(plMaxNode* node, hsGMaterial* mat);
plLayer* IMakeBumpLayer(plMaxNode* node, const char* nameBase, hsGMaterial* mat, UInt32 miscFlag);
plMipmap* IGetBumpLutTexture(plMaxNode* node);
hsBool IHasSubMtl(Mtl* base, Mtl* sub);
int IFindSubIndex(plMaxNode* node, Mtl* mtl);
// NOTE: each insert function potentially modifies the layers,
// so make sure you own the material copy before calling these
void IInsertAlphaBlendingLayers(Mtl *mtl, plMaxNode *node, hsGMaterial *mat, int UVChan,
hsBool makeAlphaLayer);
void IInsertMultipassBlendingLayers(Mtl *mtl, plMaxNode *node, hsGMaterial *mat, int UVChan,
hsBool makeAlphaLayer);
void IInsertCompBlendingLayers(Mtl *mtl, plMaxNode *node, hsGMaterial *mat, int subMtlFlags,
int UVChan, hsBool makeAlphaLayer);
void IAddLayerToMaterial(hsGMaterial *mat, plLayerInterface *layer);
#if 0 // Out for now...
void IInitAttrSurface(hsGLayer *hLay, StdMat *stdMtl, plMaxNode *node);
void IInitAttrTexture(plMaxNode *node, Mtl *mtl, hsGLayer* hLay, Texmap *texMap, char *nodeName);
void IInitAttrLayer(hsGLayer* hLay, Mtl *mtl, Texmap* layer, plMaxNode* node);
#endif
// ... and so forth
hsBool IUVGenHasDynamicScale(plMaxNode* node, StdUVGen *uvGen);
void IScaleLayerOpacity(plLayer* hLay, hsScalar scale);
hsGMaterial *ICheckForProjectedTexture(plMaxNode *node);
hsGMaterial *IWrapTextureInMaterial(Texmap *texMap, plMaxNode *node);
BMM_Color_64 ICubeSample(Bitmap *bitmap[6], double phi, double theta);
void IBuildSphereMap(Bitmap *bitmap[6], Bitmap *bm);
#if 0 // DEFER_ANIM_MAT
void IProcessAnimMaterial(BitmapTex *bitmapTex, hsGAnimLayer* at, UInt32 texFlags, UInt32 procFlags);
#endif // DEFER_ANIM_MAT
static hsBool ITextureTransformIsAnimated(Texmap *texmap);
static hsBool IHasAnimatedControllers(Animatable* anim);
static hsBool IIsAnimatedTexmap(Texmap* texmap);
static UInt32 ICheckPoints(const Point3& p0, const Point3& p1, const Point3& p2, const Point3& p3,
int chan,
UInt32 mBlack, UInt32 mGrey, UInt32 mWhite);
static UInt32 ICheckPoints(const Point3& p0, const Point3& p1, const Point3& p2,
int chan,
UInt32 mBlack, UInt32 mGrey, UInt32 mWhite);
void IAppendWetLayer(plMaxNode* node, hsGMaterial* mat);
static plBitmap* IGetFunkyRamp(plMaxNode* node, UInt32 funkyType);
static void IAppendFunkyLayer(plMaxNode* node, Texmap* texMap, hsGMaterial* mat);
static hsBool IHasFunkyOpacity(plMaxNode* node, Texmap* texMap);
static UInt32 IGetFunkyType(Texmap* texMap);
static UInt32 IGetOpacityRanges(plMaxNode* node, Texmap* texMap, hsScalar& tr0, hsScalar& op0, hsScalar& op1, hsScalar& tr1);
Interface *fInterface;
hsConverterUtils& fConverterUtils;
hsBool fSave;
plErrorMsg *fErrorMsg;
Int32 fSubIndex;
hsBool fChangedTimes;
char *fNodeName;
UInt32 fWarned;
DoneMaterialData fLastMaterial;
hsTArray fDoneMaterials;
hsBool IsMatchingDoneMaterial(DoneMaterialData *dmd,
Mtl *mtl, hsBool isMultiMat, UInt32 subMtlFlags, hsBool forceCopy, hsBool runtimeLit,
plMaxNode *node, int numUVChannels, hsBool makeAlphaLayer);
void ISortDoneMaterials(hsTArray& doneMats);
hsBool IEquivalent(DoneMaterialData* one, DoneMaterialData* two);
void IPrintDoneMat(hsStream* stream, const char* prefix, DoneMaterialData* doneMat);
void IPrintDoneMaterials(const char* path, hsTArray& doneMats);
void IGenMaterialReport(const char* path);
public:
// Apologies all around, but I need this list for dumping some export warnings. mf
const hsTArray& DoneMaterials() { return fDoneMaterials; }
//hsBool CheckValidityOfSDLVarAnim(plPassMtlBase *mtl, char *varName, plMaxNode *node);
};
extern hsMaterialConverter gMaterialConverter;
#endif