2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 10:37:41 -04:00

Fix line endings and tabs

This commit is contained in:
Branan Purvine-Riley
2011-04-11 16:27:55 -07:00
parent d4250e19b5
commit 908aaeb6f6
2738 changed files with 702562 additions and 702562 deletions

View File

@ -1,92 +1,92 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
// StringTokenizer.cpp
#include "StringTokenizer.h"
#include "string.h"
// String Tokenizer routines
StringTokenizer::StringTokenizer() {
qAsTok = true;
inQuote = false;
this->string = this->seps = 0;
}
StringTokenizer::StringTokenizer(const char *string, const char *seps) {
qAsTok = true;
inQuote = false;
this->string = TRACKED_NEW char[strlen(string)+1];
strcpy(this->string,string);
numSeps = strlen(seps);
this->seps = TRACKED_NEW char[numSeps+1];
strcpy(this->seps,seps);
this->tok = this->string;
if (isSep(*tok)) next();
};
StringTokenizer::~StringTokenizer() {
delete string;
delete seps;
}
hsBool StringTokenizer::hasMoreTokens() {
return (*tok != '\0');
};
char *StringTokenizer::next() {
if (*tok == '\0') return NULL;
char *cur = tok;
while (*tok != '\0' && !isSep(*tok)) tok++;
if (*tok != '\0') {
*tok = '\0';
tok++;
}
while (*tok != '\0' && isSep(*tok)) tok++;
return cur;
};
hsBool StringTokenizer::isSep(char c) {
if (!qAsTok || !inQuote) {
for (Int32 i=0; i<numSeps; i++) {
if (seps[i] == c) return true;
}
}
if (qAsTok && c=='\"') {
inQuote = !inQuote;
return true;
}
return false;
};
void StringTokenizer::reset(const char *string, const char *seps) {
if (this->string) delete this->string;
this->string = TRACKED_NEW char[strlen(string)+1];
strcpy(this->string,string);
if (this->seps) delete this->seps;
numSeps = strlen(seps);
this->seps = TRACKED_NEW char[numSeps+1];
strcpy(this->seps,seps);
this->tok = this->string;
if (isSep(*tok)) next();
}
void StringTokenizer::ParseQuotes(hsBool qAsTok) {
this->qAsTok = qAsTok;
}
/*==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 <http://www.gnu.org/licenses/>.
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==*/
// StringTokenizer.cpp
#include "StringTokenizer.h"
#include "string.h"
// String Tokenizer routines
StringTokenizer::StringTokenizer() {
qAsTok = true;
inQuote = false;
this->string = this->seps = 0;
}
StringTokenizer::StringTokenizer(const char *string, const char *seps) {
qAsTok = true;
inQuote = false;
this->string = TRACKED_NEW char[strlen(string)+1];
strcpy(this->string,string);
numSeps = strlen(seps);
this->seps = TRACKED_NEW char[numSeps+1];
strcpy(this->seps,seps);
this->tok = this->string;
if (isSep(*tok)) next();
};
StringTokenizer::~StringTokenizer() {
delete string;
delete seps;
}
hsBool StringTokenizer::hasMoreTokens() {
return (*tok != '\0');
};
char *StringTokenizer::next() {
if (*tok == '\0') return NULL;
char *cur = tok;
while (*tok != '\0' && !isSep(*tok)) tok++;
if (*tok != '\0') {
*tok = '\0';
tok++;
}
while (*tok != '\0' && isSep(*tok)) tok++;
return cur;
};
hsBool StringTokenizer::isSep(char c) {
if (!qAsTok || !inQuote) {
for (Int32 i=0; i<numSeps; i++) {
if (seps[i] == c) return true;
}
}
if (qAsTok && c=='\"') {
inQuote = !inQuote;
return true;
}
return false;
};
void StringTokenizer::reset(const char *string, const char *seps) {
if (this->string) delete this->string;
this->string = TRACKED_NEW char[strlen(string)+1];
strcpy(this->string,string);
if (this->seps) delete this->seps;
numSeps = strlen(seps);
this->seps = TRACKED_NEW char[numSeps+1];
strcpy(this->seps,seps);
this->tok = this->string;
if (isSep(*tok)) next();
}
void StringTokenizer::ParseQuotes(hsBool qAsTok) {
this->qAsTok = qAsTok;
}

View File

@ -1,51 +1,51 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
// StringTokenizer.h
#ifndef _STRING_TOKENIZER_H_
#define _STRING_TOKENIZER_H_
#include "Headspin.h"
class StringTokenizer {
private:
char *seps;
char *tok;
hsBool isSep(char c);
Int32 numSeps;
hsBool qAsTok;
hsBool inQuote;
public:
StringTokenizer();
StringTokenizer(const char *string, const char *seps);
~StringTokenizer();
char *next();
hsBool hasMoreTokens();
void reset(const char *string, const char *seps);
void ParseQuotes(hsBool qAsTok);
char *string;
};
/*==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 <http://www.gnu.org/licenses/>.
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==*/
// StringTokenizer.h
#ifndef _STRING_TOKENIZER_H_
#define _STRING_TOKENIZER_H_
#include "Headspin.h"
class StringTokenizer {
private:
char *seps;
char *tok;
hsBool isSep(char c);
Int32 numSeps;
hsBool qAsTok;
hsBool inQuote;
public:
StringTokenizer();
StringTokenizer(const char *string, const char *seps);
~StringTokenizer();
char *next();
hsBool hasMoreTokens();
void reset(const char *string, const char *seps);
void ParseQuotes(hsBool qAsTok);
char *string;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,143 +1,143 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
// UserPropMgr
#ifndef _USERPROPMGR_H_
#define _USERPROPMGR_H_
#include "Max.h"
#include "hsTypes.h"
template <class T> class hsHashTable;
class UserPropMgr {
public:
enum
{
kMe = 0,
kParent,
kRoot
};
UserPropMgr(); // No Default Constructor!
UserPropMgr(Interface *ip);
~UserPropMgr();
NameMaker *nm;
void SetUserPropFlag(INode *node, const char *name, const BOOL setFlag, const Int32 hFlag=kMe);
void SelectUserPropFlagALL(INode *node, const char *name, const BOOL flag);
void ClearUserProp(INode *node, const char *name, const Int32 hFlag=kMe);
void ClearUserPropALL(const char *name, const Int32 hFlag=kMe);
void SetUserPropFlagALL(const char *name, const BOOL setFlag, const Int32 hFlag=kMe);
BOOL GetUserPropFlagALL(const char *name, BOOL &isSet, const Int32 hFlag=kMe);
BOOL GetUserProp(INode *node, const char *name, TSTR &value, const Int32 hFlag=kMe);
void SetUserProp(INode *node, const char *name, const char *value, const Int32 hFlag=kMe);
BOOL UserPropExists(INode *node, const char *name, const Int32 hFlag=kMe);
BOOL GetUserPropString(INode *node, const char *name, TSTR &value, const Int32 hFlag=kMe);
void SetUserPropString(INode *node, const char *name, const char *value, const Int32 hFlag=kMe);
BOOL GetUserPropFloat(INode *node, const char *name, float &value, const Int32 hFlag=kMe);
void SetUserPropFloat(INode *node, const char *name, const float value, const Int32 hFlag=kMe);
BOOL GetUserPropInt(INode *node, const char *name, int &value, const Int32 hFlag=kMe);
void SetUserPropInt(INode *node, const char *name, const int value, const Int32 hFlag=kMe);
BOOL GetUserPropStringList(INode *node, const char *name, int &num, TSTR list[]);
BOOL GetUserPropIntList(INode *node, const char *name, int &num, int list[]);
BOOL GetUserPropFloatList(INode *node, const char *name, int &num, float list[]);
BOOL GetUserPropStringALL(const char *name, TSTR &value, const Int32 hFlag=kMe);
void SetUserPropStringALL(const char *name, const char *value, const Int32 hFlag=kMe);
BOOL GetUserPropStringListALL(const char *name, int &num, TSTR list[]);
BOOL GetUserPropIntListALL(const char *name, int &num, int *list);
BOOL GetUserPropFloatListALL(const char *name, int &num, float *list);
BOOL GetNodeNameALL(TSTR &name);
void SetNodeNameALL(const char *name);
void LoadVirtualProps(BOOL reset=true);
void DestroyVirtualProps();
BOOL IsVirtual();
int GetSelNodeCount();
INode *GetSelNode(int i);
int GetUserPropCount(INode *node);
void GetUserPropBuffer(INode *node, TSTR &buf);
void SetUserPropBuffer(INode *node, const TSTR &buf);
BOOL IsAlike(INode *node, BOOL MatchAll=true);
int CountAlike(BOOL MatchAll=true);
void DeSelectUnAlike(INode *node=NULL);
Interface *GetInterface() { return ip; }
void OpenQuickTable();
void CloseQuickTable();
private:
INode* GetAncestorIfNeeded(INode* node, const Int32 hFlag);
void DeSelectWithOut(const char *name, const char *value);
void RecursiveSelectAll(INode *node = NULL);
int RecursiveCountAlike(INode *node = NULL, BOOL MatchAll=true);
BOOL IsMatch(const char *val1, const char *val2);
BOOL vProps;
TSTR vbuf;
TSTR vname;
class QuickPair
{
public:
static void SetBuffer(char* buf);
protected:
static char* fBuffer;
const char* fKey;
const char* fVal;
public:
QuickPair() : fKey(nil), fVal(nil) { }
~QuickPair() { }
void SetKey(const char* k) { fKey = k; }
void SetVal(const char* v) { fVal = v; }
UInt32 GetHash() const;
hsBool GetVal(TSTR& value);
bool operator==(const QuickPair& other) const;
};
hsHashTable<QuickPair>* fQuickTable;
static const UInt32 kQuickSize;
INode* fQuickNode;
void IBuildQuickTable(INode* node);
BOOL ICheckQuickEntry(const char *key, TSTR &value);
Interface *ip;
};
/*==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 <http://www.gnu.org/licenses/>.
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==*/
// UserPropMgr
#ifndef _USERPROPMGR_H_
#define _USERPROPMGR_H_
#include "Max.h"
#include "hsTypes.h"
template <class T> class hsHashTable;
class UserPropMgr {
public:
enum
{
kMe = 0,
kParent,
kRoot
};
UserPropMgr(); // No Default Constructor!
UserPropMgr(Interface *ip);
~UserPropMgr();
NameMaker *nm;
void SetUserPropFlag(INode *node, const char *name, const BOOL setFlag, const Int32 hFlag=kMe);
void SelectUserPropFlagALL(INode *node, const char *name, const BOOL flag);
void ClearUserProp(INode *node, const char *name, const Int32 hFlag=kMe);
void ClearUserPropALL(const char *name, const Int32 hFlag=kMe);
void SetUserPropFlagALL(const char *name, const BOOL setFlag, const Int32 hFlag=kMe);
BOOL GetUserPropFlagALL(const char *name, BOOL &isSet, const Int32 hFlag=kMe);
BOOL GetUserProp(INode *node, const char *name, TSTR &value, const Int32 hFlag=kMe);
void SetUserProp(INode *node, const char *name, const char *value, const Int32 hFlag=kMe);
BOOL UserPropExists(INode *node, const char *name, const Int32 hFlag=kMe);
BOOL GetUserPropString(INode *node, const char *name, TSTR &value, const Int32 hFlag=kMe);
void SetUserPropString(INode *node, const char *name, const char *value, const Int32 hFlag=kMe);
BOOL GetUserPropFloat(INode *node, const char *name, float &value, const Int32 hFlag=kMe);
void SetUserPropFloat(INode *node, const char *name, const float value, const Int32 hFlag=kMe);
BOOL GetUserPropInt(INode *node, const char *name, int &value, const Int32 hFlag=kMe);
void SetUserPropInt(INode *node, const char *name, const int value, const Int32 hFlag=kMe);
BOOL GetUserPropStringList(INode *node, const char *name, int &num, TSTR list[]);
BOOL GetUserPropIntList(INode *node, const char *name, int &num, int list[]);
BOOL GetUserPropFloatList(INode *node, const char *name, int &num, float list[]);
BOOL GetUserPropStringALL(const char *name, TSTR &value, const Int32 hFlag=kMe);
void SetUserPropStringALL(const char *name, const char *value, const Int32 hFlag=kMe);
BOOL GetUserPropStringListALL(const char *name, int &num, TSTR list[]);
BOOL GetUserPropIntListALL(const char *name, int &num, int *list);
BOOL GetUserPropFloatListALL(const char *name, int &num, float *list);
BOOL GetNodeNameALL(TSTR &name);
void SetNodeNameALL(const char *name);
void LoadVirtualProps(BOOL reset=true);
void DestroyVirtualProps();
BOOL IsVirtual();
int GetSelNodeCount();
INode *GetSelNode(int i);
int GetUserPropCount(INode *node);
void GetUserPropBuffer(INode *node, TSTR &buf);
void SetUserPropBuffer(INode *node, const TSTR &buf);
BOOL IsAlike(INode *node, BOOL MatchAll=true);
int CountAlike(BOOL MatchAll=true);
void DeSelectUnAlike(INode *node=NULL);
Interface *GetInterface() { return ip; }
void OpenQuickTable();
void CloseQuickTable();
private:
INode* GetAncestorIfNeeded(INode* node, const Int32 hFlag);
void DeSelectWithOut(const char *name, const char *value);
void RecursiveSelectAll(INode *node = NULL);
int RecursiveCountAlike(INode *node = NULL, BOOL MatchAll=true);
BOOL IsMatch(const char *val1, const char *val2);
BOOL vProps;
TSTR vbuf;
TSTR vname;
class QuickPair
{
public:
static void SetBuffer(char* buf);
protected:
static char* fBuffer;
const char* fKey;
const char* fVal;
public:
QuickPair() : fKey(nil), fVal(nil) { }
~QuickPair() { }
void SetKey(const char* k) { fKey = k; }
void SetVal(const char* v) { fVal = v; }
UInt32 GetHash() const;
hsBool GetVal(TSTR& value);
bool operator==(const QuickPair& other) const;
};
hsHashTable<QuickPair>* fQuickTable;
static const UInt32 kQuickSize;
INode* fQuickNode;
void IBuildQuickTable(INode* node);
BOOL ICheckQuickEntry(const char *key, TSTR &value);
Interface *ip;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,185 +1,185 @@
/*==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 <http://www.gnu.org/licenses/>.
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 __HSCONTROLCONVERTER_H
#define __HSCONTROLCONVERTER_H
#include <commdlg.h>
#include <math.h>
//#include "Max.h"
#include "stdmat.h"
#include "bmmlib.h"
#include "istdplug.h"
#include "texutil.h"
#include "../../../Sources/Plasma/PubUtilLib/plInterp/hsKeys.h"
#include "hsTemplates.h"
class plMaxNode;
enum ControllerType
{
ctrlTypeUnknown,
ctrlTypeFloat,
ctrlTypePoint3,
ctrlTypePosition,
ctrlTypeRotation,
ctrlTypeRotationX,
ctrlTypeRotationY,
ctrlTypeRotationZ,
ctrlTypeScale,
ctrlTypeTransform,
ctrlTypeEase,
ctrlTypeMult,
ctrlTypeVert, // CS Biped
ctrlTypeHoriz, // CS Biped
ctrlTypeTurn, // CS Biped
ctrlTypeRollAngle,
};
class plController;
class plLeafController;
class plCompoundController;
struct hsKeyFrame;
class hsConverterUtils;
class plSceneObject;
class hsControlConverter
{
private:
hsControlConverter();
public:
~hsControlConverter() { };
static hsControlConverter& Instance();
void Init(plErrorMsg* msg);
void DeInit();
// Used to pick correct controller by lights/materials
hsBool GetControllerByName(Animatable* anim, TSTR &name, Control* &ctl);
Control *GetControllerByID(IParamBlock2 *pblock, int paramID);
/////////////////////////////////////////////////////////////////////////
//
// Controller convert functions:
//
// All convert functions must call ISetSegRange(start, end) at the beginning.
// (ISetSegRange(-1, -1) will give you the entire anim.)
plLeafController* MakeMatrix44Controller(StdUVGen* uvGen, const char* nodeName);
plLeafController* MakeMatrix44Controller(Control* prsControl);
plLeafController* MakeScalarController(Control* control, plMaxNode* node, hsScalar start = -1, hsScalar end = -1);
plController* MakeColorController(Control* control, plMaxNode* node, hsScalar start = -1, hsScalar end = -1);
plController* MakePosController(Control* control, plMaxNode* node, hsScalar start = -1, hsScalar end = -1);
plController* MakeScaleController(Control* control, plMaxNode* node, hsScalar start = -1, hsScalar end = -1);
plController* MakeRotController(Control* control, plMaxNode* node, hsBool camRot = false, hsScalar start = -1, hsScalar end = -1);
plCompoundController* MakeTransformController(Control* control, plMaxNode* node, hsScalar start = -1, hsScalar end = -1);
// This last one was in tempAnim.cpp on its own for some time, apparently created
// as an initial attempt to get anims working in Max. It's still used, so I don't want
// to nuke it, but it made sense to move it here.
plController* ConvertTMAnim(plSceneObject *obj, plMaxNode *node, hsAffineParts *parts, hsScalar start = -1, hsScalar end = -1);
//
//
//////////////////////////////////////////////////////////////////////////
void Matrix3ToHsMatrix44(Matrix3* m3, hsMatrix44* hsM);
Matrix3 StdUVGenToMatrix3(StdUVGen* uvGen);
bool StdUVGenToHsMatrix44(hsMatrix44* hsMat, StdUVGen* uvGen, bool preserveOffset=false);
void MaxSampleAngles(const char* nodeName, Control* ctl, Tab<TimeValue>& kTimes, hsScalar maxRads);
void ScalePositionController(plController* ctl, hsScalar scale);
void ReduceKeys(Control *control, hsScalar threshold);
hsBool HasKeyTimes(Control* ctl);
UInt8 GetKeyType(Control* ctl, hsBool rotQuat = false);
plMaxNode* GetXformParent(plMaxNode* node);
hsBool ForceWorldSpace(plMaxNode* node);
hsBool ForceOrigin(plMaxNode* node);
hsBool ForceLocal(plMaxNode* node);
hsBool IsAnimated(plMaxNode* node);
hsBool OwnsMaterialCopy(plMaxNode* node);
hsBool HasFrameEvents(plMaxNode *node);
void CompositeKeyTimes(Control* ctl, Tab<TimeValue> &time);
int GetTicksPerFrame() { return fTicksPerFrame; }
int GetFrameRate() { return fFrameRate; }
int GetTicksPerSec() { return fTicksPerSec; }
int GetStartFrame() { return fStartFrame; }
int GetEndFrame() { return fEndFrame; }
int GetNumFrames() { return fNumFrames; }
float GetAnimLength() { return fAnimLength; }
private:
void ISetSegRange(hsScalar start, hsScalar end);
void IConvertSubTransform(Control *control, char *ctlName, plMaxNode *node, plCompoundController *tmc, hsScalar start, hsScalar end);
plLeafController* ICreateSimpleRotController(plMaxNode* node, Control* control, hsBool camRot = false);
plLeafController* ICreateSimpleScaleController(plMaxNode* node, Control* control);
plLeafController* ICreateQuatController(plMaxNode* node, Control* control, bool rotation = true, hsBool camRot = false);
plLeafController* ICreateScaleValueController(plMaxNode* node, Control* control);
plLeafController* ICreateScalarController(plMaxNode* node, Control* control);
plLeafController* ICreateSimplePosController(plMaxNode* node, Control* control);
void IEnableEaseCurves(Animatable* control, bool enable);
void IGetControlSampleTimes(Control* control, int iLo, int iHi, Tab<TimeValue>& kTimes, float maxRads);
int IAddPartsKeys(Control* control, hsTArray <hsG3DSMaxKeyFrame>* kfArray, plMaxNode* node);
Int32 ICreateHSInterpKey(Control* control, IKey* mKey, TimeValue keyTime, hsKeyFrame* baseKey, plMaxNode* node=nil, hsBool rotQuat = false);
Int32 IGetRangeCoverKeyIndices(char* nodeName, Control* cont, Int32 &start, Int32 &end);
ControllerType IGetControlType(TSTR ctrlName);
bool IIsKeyTimeInRange(TimeValue time);
bool IIsKeyInRange(IKey* key);
void IGetUnEasedLocalTM(plMaxNode* node, Control* control, hsMatrix44* out, TimeValue time);
Matrix3 IFlipY();
bool ISkinNode(plMaxNode* node);
void ISetForceLocal(bool f) { fForceLocal=f; }
hsBool IGetEditableMeshKeyTimes( plMaxNode *node, Tab<TimeValue> &times );
hsBool IGetGeomKeyTimes( plMaxNode *node, Tab<TimeValue> &times );
void IGetGeomKeyTimesRecur( Animatable *anim, Tab<TimeValue> &times );
hsBool IGetSubAnimByName( Animatable *anim, TSTR &name, Animatable *&subAnim );
void IExportAnimatedCameraFOV(plMaxNode* node, hsTArray <hsG3DSMaxKeyFrame>* kfArray);
Interface* fInterface;
hsConverterUtils& fConverterUtils;
plErrorMsg * fErrorMsg;
Int32 fTicksPerFrame;
Int32 fFrameRate;
Int32 fTicksPerSec;
Int32 fStartFrame;
Int32 fEndFrame;
Int32 fNumFrames;
hsScalar fAnimLength;
hsBool fWarned;
hsBool fForceLocal;
TimeValue fSegStart;
TimeValue fSegEnd;
};
/*==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 <http://www.gnu.org/licenses/>.
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 __HSCONTROLCONVERTER_H
#define __HSCONTROLCONVERTER_H
#include <commdlg.h>
#include <math.h>
//#include "Max.h"
#include "stdmat.h"
#include "bmmlib.h"
#include "istdplug.h"
#include "texutil.h"
#include "../../../Sources/Plasma/PubUtilLib/plInterp/hsKeys.h"
#include "hsTemplates.h"
class plMaxNode;
enum ControllerType
{
ctrlTypeUnknown,
ctrlTypeFloat,
ctrlTypePoint3,
ctrlTypePosition,
ctrlTypeRotation,
ctrlTypeRotationX,
ctrlTypeRotationY,
ctrlTypeRotationZ,
ctrlTypeScale,
ctrlTypeTransform,
ctrlTypeEase,
ctrlTypeMult,
ctrlTypeVert, // CS Biped
ctrlTypeHoriz, // CS Biped
ctrlTypeTurn, // CS Biped
ctrlTypeRollAngle,
};
class plController;
class plLeafController;
class plCompoundController;
struct hsKeyFrame;
class hsConverterUtils;
class plSceneObject;
class hsControlConverter
{
private:
hsControlConverter();
public:
~hsControlConverter() { };
static hsControlConverter& Instance();
void Init(plErrorMsg* msg);
void DeInit();
// Used to pick correct controller by lights/materials
hsBool GetControllerByName(Animatable* anim, TSTR &name, Control* &ctl);
Control *GetControllerByID(IParamBlock2 *pblock, int paramID);
/////////////////////////////////////////////////////////////////////////
//
// Controller convert functions:
//
// All convert functions must call ISetSegRange(start, end) at the beginning.
// (ISetSegRange(-1, -1) will give you the entire anim.)
plLeafController* MakeMatrix44Controller(StdUVGen* uvGen, const char* nodeName);
plLeafController* MakeMatrix44Controller(Control* prsControl);
plLeafController* MakeScalarController(Control* control, plMaxNode* node, hsScalar start = -1, hsScalar end = -1);
plController* MakeColorController(Control* control, plMaxNode* node, hsScalar start = -1, hsScalar end = -1);
plController* MakePosController(Control* control, plMaxNode* node, hsScalar start = -1, hsScalar end = -1);
plController* MakeScaleController(Control* control, plMaxNode* node, hsScalar start = -1, hsScalar end = -1);
plController* MakeRotController(Control* control, plMaxNode* node, hsBool camRot = false, hsScalar start = -1, hsScalar end = -1);
plCompoundController* MakeTransformController(Control* control, plMaxNode* node, hsScalar start = -1, hsScalar end = -1);
// This last one was in tempAnim.cpp on its own for some time, apparently created
// as an initial attempt to get anims working in Max. It's still used, so I don't want
// to nuke it, but it made sense to move it here.
plController* ConvertTMAnim(plSceneObject *obj, plMaxNode *node, hsAffineParts *parts, hsScalar start = -1, hsScalar end = -1);
//
//
//////////////////////////////////////////////////////////////////////////
void Matrix3ToHsMatrix44(Matrix3* m3, hsMatrix44* hsM);
Matrix3 StdUVGenToMatrix3(StdUVGen* uvGen);
bool StdUVGenToHsMatrix44(hsMatrix44* hsMat, StdUVGen* uvGen, bool preserveOffset=false);
void MaxSampleAngles(const char* nodeName, Control* ctl, Tab<TimeValue>& kTimes, hsScalar maxRads);
void ScalePositionController(plController* ctl, hsScalar scale);
void ReduceKeys(Control *control, hsScalar threshold);
hsBool HasKeyTimes(Control* ctl);
UInt8 GetKeyType(Control* ctl, hsBool rotQuat = false);
plMaxNode* GetXformParent(plMaxNode* node);
hsBool ForceWorldSpace(plMaxNode* node);
hsBool ForceOrigin(plMaxNode* node);
hsBool ForceLocal(plMaxNode* node);
hsBool IsAnimated(plMaxNode* node);
hsBool OwnsMaterialCopy(plMaxNode* node);
hsBool HasFrameEvents(plMaxNode *node);
void CompositeKeyTimes(Control* ctl, Tab<TimeValue> &time);
int GetTicksPerFrame() { return fTicksPerFrame; }
int GetFrameRate() { return fFrameRate; }
int GetTicksPerSec() { return fTicksPerSec; }
int GetStartFrame() { return fStartFrame; }
int GetEndFrame() { return fEndFrame; }
int GetNumFrames() { return fNumFrames; }
float GetAnimLength() { return fAnimLength; }
private:
void ISetSegRange(hsScalar start, hsScalar end);
void IConvertSubTransform(Control *control, char *ctlName, plMaxNode *node, plCompoundController *tmc, hsScalar start, hsScalar end);
plLeafController* ICreateSimpleRotController(plMaxNode* node, Control* control, hsBool camRot = false);
plLeafController* ICreateSimpleScaleController(plMaxNode* node, Control* control);
plLeafController* ICreateQuatController(plMaxNode* node, Control* control, bool rotation = true, hsBool camRot = false);
plLeafController* ICreateScaleValueController(plMaxNode* node, Control* control);
plLeafController* ICreateScalarController(plMaxNode* node, Control* control);
plLeafController* ICreateSimplePosController(plMaxNode* node, Control* control);
void IEnableEaseCurves(Animatable* control, bool enable);
void IGetControlSampleTimes(Control* control, int iLo, int iHi, Tab<TimeValue>& kTimes, float maxRads);
int IAddPartsKeys(Control* control, hsTArray <hsG3DSMaxKeyFrame>* kfArray, plMaxNode* node);
Int32 ICreateHSInterpKey(Control* control, IKey* mKey, TimeValue keyTime, hsKeyFrame* baseKey, plMaxNode* node=nil, hsBool rotQuat = false);
Int32 IGetRangeCoverKeyIndices(char* nodeName, Control* cont, Int32 &start, Int32 &end);
ControllerType IGetControlType(TSTR ctrlName);
bool IIsKeyTimeInRange(TimeValue time);
bool IIsKeyInRange(IKey* key);
void IGetUnEasedLocalTM(plMaxNode* node, Control* control, hsMatrix44* out, TimeValue time);
Matrix3 IFlipY();
bool ISkinNode(plMaxNode* node);
void ISetForceLocal(bool f) { fForceLocal=f; }
hsBool IGetEditableMeshKeyTimes( plMaxNode *node, Tab<TimeValue> &times );
hsBool IGetGeomKeyTimes( plMaxNode *node, Tab<TimeValue> &times );
void IGetGeomKeyTimesRecur( Animatable *anim, Tab<TimeValue> &times );
hsBool IGetSubAnimByName( Animatable *anim, TSTR &name, Animatable *&subAnim );
void IExportAnimatedCameraFOV(plMaxNode* node, hsTArray <hsG3DSMaxKeyFrame>* kfArray);
Interface* fInterface;
hsConverterUtils& fConverterUtils;
plErrorMsg * fErrorMsg;
Int32 fTicksPerFrame;
Int32 fFrameRate;
Int32 fTicksPerSec;
Int32 fStartFrame;
Int32 fEndFrame;
Int32 fNumFrames;
hsScalar fAnimLength;
hsBool fWarned;
hsBool fForceLocal;
TimeValue fSegStart;
TimeValue fSegEnd;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,135 +1,135 @@
/*==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 <http://www.gnu.org/licenses/>.
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 __HSCONVERTERUTILS_H
#define __HSCONVERTERUTILS_H
#include "Max.h"
#include "stdmat.h"
#include <commdlg.h>
#include "bmmlib.h"
#include "istdplug.h"
#include "texutil.h"
#include "Headspin.h"
class INode;
class Control;
class Interface;
template <class T> class hsHashTable;
class hsMaxLayerBase;
class plSimplePosController;
class plScalarController;
class plLeafController;
class hsGBitmapClass;
class hsGMipmapClass;
class plErrorMsg;
class hsKeyedObject;
class hsGRenderProcs;
class hsBaseRenderProc;
class hsConverterUtils
{
private:
hsConverterUtils();
public: // MSDEV bug
~hsConverterUtils() {}
public:
static hsConverterUtils& Instance();
static hsBool IsReservedKeyword(const char* nodeName);
void Init(hsBool save, plErrorMsg *msg);
hsBool IsEnvironHolder(INode *node);
hsBool AutoStartDynamics(INode *node);
hsBool RandomStartDynamics(INode *node);
TimeValue GetTime(Interface *gi);
void StripOffTail(char* path);
void StripOffPath(char* fileName);
INode* FindINodeFromKeyedObject(hsKeyedObject* obj);
INode* FindINodeFromMangledName(const char* mangName);
#if 0
void MangleRPRefs(hsBaseRenderProc* base, hsGRenderProcs* rp);
#endif
char* MangleReference(char *mangName, const char *nodeName, const char* defRoom="global");
char* MangleReference(char *mangName, INode *node, const char* defRoom="global");
char* MangleRefWithRoom(char *mangName, const char *nodeName, const char* roomName);
char* UnMangleReference(char *dest, const char *name);
hsBool IsMangled(const char *name);
Int32 FindNamedSelSetFromName(const char *name);
char* StripMangledReference(char* dest, const char* name);
hsBool IsInstanced(Object* maxObject);
void CreateNodeSearchCache();
void DestroyNodeSearchCache();
INode* GetINodeByName(const char* name, hsBool caseSensitive=false);
static const char fTagSeps[];
private:
void IBuildNodeSearchCacheRecur(INode* node);
INode* IGetINodeByNameRecur(INode* node, const char* wantName);
private:
enum {
kWarnedNoMoreBitmapLoadErr = 0x1
};
Interface *fInterface;
plErrorMsg *fErrorMsg;
hsBool fSuppressMangling;
UInt32 fWarned;
hsBool fSave;
struct CacheNode
{
private:
INode* fNode;
const char* fName;
hsBool fCaseSensitive;
public:
CacheNode(INode* node=nil) : fNode(node), fName(nil), fCaseSensitive(false) { }
CacheNode(const char* name) : fName(name), fNode(nil), fCaseSensitive(false) { }
~CacheNode() { }
INode* GetNode() { return fNode; }
const char* GetName() const { return fNode ? fNode->GetName() : fName; }
void SetCaseSensitive(hsBool b) { fCaseSensitive = b; }
hsBool GetCaseSensitive() { return fCaseSensitive; }
UInt32 GetHash() const;
bool operator==(const CacheNode& other) const;
};
hsHashTable<CacheNode>* fNodeSearchCache;
};
#endif
/*==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 <http://www.gnu.org/licenses/>.
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 __HSCONVERTERUTILS_H
#define __HSCONVERTERUTILS_H
#include "Max.h"
#include "stdmat.h"
#include <commdlg.h>
#include "bmmlib.h"
#include "istdplug.h"
#include "texutil.h"
#include "Headspin.h"
class INode;
class Control;
class Interface;
template <class T> class hsHashTable;
class hsMaxLayerBase;
class plSimplePosController;
class plScalarController;
class plLeafController;
class hsGBitmapClass;
class hsGMipmapClass;
class plErrorMsg;
class hsKeyedObject;
class hsGRenderProcs;
class hsBaseRenderProc;
class hsConverterUtils
{
private:
hsConverterUtils();
public: // MSDEV bug
~hsConverterUtils() {}
public:
static hsConverterUtils& Instance();
static hsBool IsReservedKeyword(const char* nodeName);
void Init(hsBool save, plErrorMsg *msg);
hsBool IsEnvironHolder(INode *node);
hsBool AutoStartDynamics(INode *node);
hsBool RandomStartDynamics(INode *node);
TimeValue GetTime(Interface *gi);
void StripOffTail(char* path);
void StripOffPath(char* fileName);
INode* FindINodeFromKeyedObject(hsKeyedObject* obj);
INode* FindINodeFromMangledName(const char* mangName);
#if 0
void MangleRPRefs(hsBaseRenderProc* base, hsGRenderProcs* rp);
#endif
char* MangleReference(char *mangName, const char *nodeName, const char* defRoom="global");
char* MangleReference(char *mangName, INode *node, const char* defRoom="global");
char* MangleRefWithRoom(char *mangName, const char *nodeName, const char* roomName);
char* UnMangleReference(char *dest, const char *name);
hsBool IsMangled(const char *name);
Int32 FindNamedSelSetFromName(const char *name);
char* StripMangledReference(char* dest, const char* name);
hsBool IsInstanced(Object* maxObject);
void CreateNodeSearchCache();
void DestroyNodeSearchCache();
INode* GetINodeByName(const char* name, hsBool caseSensitive=false);
static const char fTagSeps[];
private:
void IBuildNodeSearchCacheRecur(INode* node);
INode* IGetINodeByNameRecur(INode* node, const char* wantName);
private:
enum {
kWarnedNoMoreBitmapLoadErr = 0x1
};
Interface *fInterface;
plErrorMsg *fErrorMsg;
hsBool fSuppressMangling;
UInt32 fWarned;
hsBool fSave;
struct CacheNode
{
private:
INode* fNode;
const char* fName;
hsBool fCaseSensitive;
public:
CacheNode(INode* node=nil) : fNode(node), fName(nil), fCaseSensitive(false) { }
CacheNode(const char* name) : fName(name), fNode(nil), fCaseSensitive(false) { }
~CacheNode() { }
INode* GetNode() { return fNode; }
const char* GetName() const { return fNode ? fNode->GetName() : fName; }
void SetCaseSensitive(hsBool b) { fCaseSensitive = b; }
hsBool GetCaseSensitive() { return fCaseSensitive; }
UInt32 GetHash() const;
bool operator==(const CacheNode& other) const;
};
hsHashTable<CacheNode>* fNodeSearchCache;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,351 +1,351 @@
/*==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 <http://www.gnu.org/licenses/>.
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<plMaxNode*> &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<plExportMaterialData> *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<hsGMaterial*>& out, UInt32 multiIndex = 0 );
int GetMaterialArray(Mtl *mtl, hsTArray<hsGMaterial*>& out, UInt32 multiIndex = 0);
void CollectConvertedMaterials(Mtl *mtl, hsTArray<hsGMaterial *> &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<DoneMaterialData> fDoneMaterials;
hsBool IsMatchingDoneMaterial(DoneMaterialData *dmd,
Mtl *mtl, hsBool isMultiMat, UInt32 subMtlFlags, hsBool forceCopy, hsBool runtimeLit,
plMaxNode *node, int numUVChannels, hsBool makeAlphaLayer);
void ISortDoneMaterials(hsTArray<DoneMaterialData*>& doneMats);
hsBool IEquivalent(DoneMaterialData* one, DoneMaterialData* two);
void IPrintDoneMat(hsStream* stream, const char* prefix, DoneMaterialData* doneMat);
void IPrintDoneMaterials(const char* path, hsTArray<DoneMaterialData*>& doneMats);
void IGenMaterialReport(const char* path);
public:
// Apologies all around, but I need this list for dumping some export warnings. mf
const hsTArray<struct DoneMaterialData>& DoneMaterials() { return fDoneMaterials; }
//hsBool CheckValidityOfSDLVarAnim(plPassMtlBase *mtl, char *varName, plMaxNode *node);
};
extern hsMaterialConverter gMaterialConverter;
/*==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 <http://www.gnu.org/licenses/>.
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<plMaxNode*> &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<plExportMaterialData> *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<hsGMaterial*>& out, UInt32 multiIndex = 0 );
int GetMaterialArray(Mtl *mtl, hsTArray<hsGMaterial*>& out, UInt32 multiIndex = 0);
void CollectConvertedMaterials(Mtl *mtl, hsTArray<hsGMaterial *> &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<DoneMaterialData> fDoneMaterials;
hsBool IsMatchingDoneMaterial(DoneMaterialData *dmd,
Mtl *mtl, hsBool isMultiMat, UInt32 subMtlFlags, hsBool forceCopy, hsBool runtimeLit,
plMaxNode *node, int numUVChannels, hsBool makeAlphaLayer);
void ISortDoneMaterials(hsTArray<DoneMaterialData*>& doneMats);
hsBool IEquivalent(DoneMaterialData* one, DoneMaterialData* two);
void IPrintDoneMat(hsStream* stream, const char* prefix, DoneMaterialData* doneMat);
void IPrintDoneMaterials(const char* path, hsTArray<DoneMaterialData*>& doneMats);
void IGenMaterialReport(const char* path);
public:
// Apologies all around, but I need this list for dumping some export warnings. mf
const hsTArray<struct DoneMaterialData>& DoneMaterials() { return fDoneMaterials; }
//hsBool CheckValidityOfSDLVarAnim(plPassMtlBase *mtl, char *varName, plMaxNode *node);
};
extern hsMaterialConverter gMaterialConverter;
#endif

View File

@ -1,188 +1,188 @@
/*==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 <http://www.gnu.org/licenses/>.
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 __HSMAXLAYERBASE_H
#define __HSMAXLAYERBASE_H
#include "stdmat.h"
#define HSMAX_LAYER_CLASS_ID 0x41990fe7
const Class_ID hsMaxLayerClassID(HSMAX_LAYER_CLASS_ID, 0x72404998);
const Class_ID hsMaxMtlClassID(0x2f335902, 0x111d2ea7);
const Class_ID hsEnvironMapMtlClassID(0x98777b3, 0x5eb270dd);
class hsMaxLayerBase : public BitmapTex {
public:
enum hsMatBlendFlags {
kBlendTest = 0x1, // dev
// Rest of blends are mutually exclusive
kBlendAlpha = 0x2, // dev
kBlendMult = 0x4, // dev
kBlendAdd = 0x8, // dev
kBlendAddColorTimesAlpha = 0x10, // dev
kBlendAntiAlias = 0x20,
kBlendDetail = 0x40,
kBlendDetailAdd = 0x80,
kBlendMask = kBlendAlpha
| kBlendMult
| kBlendAdd
| kBlendAddColorTimesAlpha
| kBlendAntiAlias
| kBlendDetail
| kBlendDetailAdd,
kBlendInvertAlpha = 0x1000, // dev
kBlendInvertColor = 0x2000, // dev
kBlendAlphaMult = 0x4000,
kBlendAlphaAdd = 0x8000,
kBlendNoColor = 0x10000,
kBlendNoVtxAlpha = 0x20000
};
enum hsMatZFlags {
kZIncLayer = 0x1, // dev
kZOnlyZ = 0x2, // dev
kZClearZ = 0x4, // dev
kZNoZRead = 0x8, // dev
kZNoZWrite = 0x10,
kZMask = kZNoZWrite | kZClearZ | kZNoZRead,
kZLODBias = 0x20
};
enum hsMatShadeFlags {
kShadeSoftShadow = 0x1, // view, dev
kShadeNoProjectors = 0x2, // projector
kShadeVertexShade = 0x20, // dev
kShadeNoShade = 0x40, // view,dev
kShadeBlack = kShadeNoShade,
kShadeSpecular = 0x80, // view, dev
kShadeNoFog = 0x100, // dev
kShadeWhite = 0x200,
kShadeSpecularAlpha = 0x400,
kShadeSpecularColor = 0x800,
kShadeSpecularHighlight = 0x1000,
kShadeVertColShade = 0x2000,
kShadeInherit = 0x4000
};
enum hsMatMiscFlags {
kMiscWireFrame = 0x1, // dev (running out of bits)
kMiscDrawMeshOutlines = 0x2, // dev, currently unimplemented
kMiscTwoSided = 0x4, // view,dev
kMiscDrawAsSplats = 0x8, // dev? bwt
kMiscMipMap = 0x10,
kMiscUseBitmap = 0x20,
kMiscIntensityOnly = 0x40,
kMiscAutoStart = 0x80,
kMiscDetailBias = 0x100, // obsolete...
kMiscDetailMax = 0x200, // obsolete...
kMiscExplicitMipmap = 0x400,
kMiscAdjustPlane = 0x800,
kMiscAdjustCylinder = 0x1000,
kMiscAdjustSphere = 0x2000,
kMiscTroubledLoner = 0x4000,
kMiscBindSkip = 0x8000,
kMiscBindMask = 0x10000,
kMiscForceNonCompressed = 0x20000,
kMiscNoMaxSize = 0x40000,
kMiscHalfSize = 0x80000,
kMiscBindNext = 0x100000,
kMiscBindPrev = 0x200000,
kMiscReserved = 0x400000
};
enum ProcType {
kProcTypeDefault,
kProcTypeWater
};
enum hsMatUsage {
kUseNone = 0x0,
kUseBase = 0x1,
kUseDetail = 0x2,
kUseGrime = 0x4,
kUseTransition = 0x8,
kUseHighlight = 0x10,
kUseMask = 0x20,
kUseShadowLight = 0x40,
kUseHelper = 0x80,
kUseGuess = 0x10000000
};
public:
// For hsMaxMtl... Special case for higher layers. Sigh.
virtual void SetDirty(BOOL state) = 0;
virtual void SetBlendFlag(int i, BOOL state) = 0;
virtual void SetZFlag(int flag, BOOL state) = 0;
virtual void SetShadeFlag(int flag, BOOL state) = 0;
virtual void SetMiscFlag(int flag, BOOL state) = 0;
virtual void SetProcType(ProcType type) = 0;
virtual void SetUsage(hsMatUsage use) = 0;
virtual void GuessUsage() = 0;
// For interactive renderer
virtual Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE) = 0;
virtual Color GetColor(int mtlNum=0, BOOL backFace=FALSE) = 0;
virtual float GetShininess(int mtlNum=0, BOOL backFace=FALSE) = 0;
virtual float GetShinStr(int mtlNum=0, BOOL backFace=FALSE) = 0;
virtual float GetOpacity(int mtlNum=0, BOOL backFace=FALSE) = 0;
// For exporter
virtual Color GetAmbient(TimeValue t) const = 0;
virtual Color GetColor(TimeValue t) const = 0;
virtual float GetShininess(TimeValue t) const = 0;
virtual float GetShinStr(TimeValue t) const = 0;
virtual float GetMapPercent(TimeValue t) const = 0;
virtual float GetOpacity(TimeValue t) const = 0;
virtual float GetMipMapBlur(TimeValue t) const = 0;
virtual float GetLODBias(TimeValue t) const = 0;
virtual float GetDetailDropoffStart(TimeValue t) const = 0;
virtual float GetDetailDropoffStop(TimeValue t) const = 0;
virtual float GetDetailMax(TimeValue t) const = 0;
virtual float GetDetailMin(TimeValue t) const = 0;
virtual int GetEnvironMapSize(TimeValue t) const = 0;
virtual BOOL GetDirty() const = 0;
virtual ULONG GetBlendFlags() const = 0;
virtual ULONG GetZFlags() const = 0;
virtual ULONG GetShadeFlags() const = 0;
virtual ULONG GetMiscFlags() const = 0;
virtual ProcType GetProcType() const = 0;
virtual hsMatUsage GetUsage() const = 0;
virtual int GetNumExplicitMipmaps() const = 0;
virtual TCHAR *GetExplicitMipmapName(int i) const = 0;
virtual BOOL ExplicitMipmapEnabled(int i) const = 0;
virtual int GetExplicitMipmapLevel(int i) const = 0;
// KLUDGE - Had to do this to compile under MAX4 beta
virtual void fnReload() {};
virtual void fnViewImage() {};
};
#endif
/*==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 <http://www.gnu.org/licenses/>.
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 __HSMAXLAYERBASE_H
#define __HSMAXLAYERBASE_H
#include "stdmat.h"
#define HSMAX_LAYER_CLASS_ID 0x41990fe7
const Class_ID hsMaxLayerClassID(HSMAX_LAYER_CLASS_ID, 0x72404998);
const Class_ID hsMaxMtlClassID(0x2f335902, 0x111d2ea7);
const Class_ID hsEnvironMapMtlClassID(0x98777b3, 0x5eb270dd);
class hsMaxLayerBase : public BitmapTex {
public:
enum hsMatBlendFlags {
kBlendTest = 0x1, // dev
// Rest of blends are mutually exclusive
kBlendAlpha = 0x2, // dev
kBlendMult = 0x4, // dev
kBlendAdd = 0x8, // dev
kBlendAddColorTimesAlpha = 0x10, // dev
kBlendAntiAlias = 0x20,
kBlendDetail = 0x40,
kBlendDetailAdd = 0x80,
kBlendMask = kBlendAlpha
| kBlendMult
| kBlendAdd
| kBlendAddColorTimesAlpha
| kBlendAntiAlias
| kBlendDetail
| kBlendDetailAdd,
kBlendInvertAlpha = 0x1000, // dev
kBlendInvertColor = 0x2000, // dev
kBlendAlphaMult = 0x4000,
kBlendAlphaAdd = 0x8000,
kBlendNoColor = 0x10000,
kBlendNoVtxAlpha = 0x20000
};
enum hsMatZFlags {
kZIncLayer = 0x1, // dev
kZOnlyZ = 0x2, // dev
kZClearZ = 0x4, // dev
kZNoZRead = 0x8, // dev
kZNoZWrite = 0x10,
kZMask = kZNoZWrite | kZClearZ | kZNoZRead,
kZLODBias = 0x20
};
enum hsMatShadeFlags {
kShadeSoftShadow = 0x1, // view, dev
kShadeNoProjectors = 0x2, // projector
kShadeVertexShade = 0x20, // dev
kShadeNoShade = 0x40, // view,dev
kShadeBlack = kShadeNoShade,
kShadeSpecular = 0x80, // view, dev
kShadeNoFog = 0x100, // dev
kShadeWhite = 0x200,
kShadeSpecularAlpha = 0x400,
kShadeSpecularColor = 0x800,
kShadeSpecularHighlight = 0x1000,
kShadeVertColShade = 0x2000,
kShadeInherit = 0x4000
};
enum hsMatMiscFlags {
kMiscWireFrame = 0x1, // dev (running out of bits)
kMiscDrawMeshOutlines = 0x2, // dev, currently unimplemented
kMiscTwoSided = 0x4, // view,dev
kMiscDrawAsSplats = 0x8, // dev? bwt
kMiscMipMap = 0x10,
kMiscUseBitmap = 0x20,
kMiscIntensityOnly = 0x40,
kMiscAutoStart = 0x80,
kMiscDetailBias = 0x100, // obsolete...
kMiscDetailMax = 0x200, // obsolete...
kMiscExplicitMipmap = 0x400,
kMiscAdjustPlane = 0x800,
kMiscAdjustCylinder = 0x1000,
kMiscAdjustSphere = 0x2000,
kMiscTroubledLoner = 0x4000,
kMiscBindSkip = 0x8000,
kMiscBindMask = 0x10000,
kMiscForceNonCompressed = 0x20000,
kMiscNoMaxSize = 0x40000,
kMiscHalfSize = 0x80000,
kMiscBindNext = 0x100000,
kMiscBindPrev = 0x200000,
kMiscReserved = 0x400000
};
enum ProcType {
kProcTypeDefault,
kProcTypeWater
};
enum hsMatUsage {
kUseNone = 0x0,
kUseBase = 0x1,
kUseDetail = 0x2,
kUseGrime = 0x4,
kUseTransition = 0x8,
kUseHighlight = 0x10,
kUseMask = 0x20,
kUseShadowLight = 0x40,
kUseHelper = 0x80,
kUseGuess = 0x10000000
};
public:
// For hsMaxMtl... Special case for higher layers. Sigh.
virtual void SetDirty(BOOL state) = 0;
virtual void SetBlendFlag(int i, BOOL state) = 0;
virtual void SetZFlag(int flag, BOOL state) = 0;
virtual void SetShadeFlag(int flag, BOOL state) = 0;
virtual void SetMiscFlag(int flag, BOOL state) = 0;
virtual void SetProcType(ProcType type) = 0;
virtual void SetUsage(hsMatUsage use) = 0;
virtual void GuessUsage() = 0;
// For interactive renderer
virtual Color GetAmbient(int mtlNum=0, BOOL backFace=FALSE) = 0;
virtual Color GetColor(int mtlNum=0, BOOL backFace=FALSE) = 0;
virtual float GetShininess(int mtlNum=0, BOOL backFace=FALSE) = 0;
virtual float GetShinStr(int mtlNum=0, BOOL backFace=FALSE) = 0;
virtual float GetOpacity(int mtlNum=0, BOOL backFace=FALSE) = 0;
// For exporter
virtual Color GetAmbient(TimeValue t) const = 0;
virtual Color GetColor(TimeValue t) const = 0;
virtual float GetShininess(TimeValue t) const = 0;
virtual float GetShinStr(TimeValue t) const = 0;
virtual float GetMapPercent(TimeValue t) const = 0;
virtual float GetOpacity(TimeValue t) const = 0;
virtual float GetMipMapBlur(TimeValue t) const = 0;
virtual float GetLODBias(TimeValue t) const = 0;
virtual float GetDetailDropoffStart(TimeValue t) const = 0;
virtual float GetDetailDropoffStop(TimeValue t) const = 0;
virtual float GetDetailMax(TimeValue t) const = 0;
virtual float GetDetailMin(TimeValue t) const = 0;
virtual int GetEnvironMapSize(TimeValue t) const = 0;
virtual BOOL GetDirty() const = 0;
virtual ULONG GetBlendFlags() const = 0;
virtual ULONG GetZFlags() const = 0;
virtual ULONG GetShadeFlags() const = 0;
virtual ULONG GetMiscFlags() const = 0;
virtual ProcType GetProcType() const = 0;
virtual hsMatUsage GetUsage() const = 0;
virtual int GetNumExplicitMipmaps() const = 0;
virtual TCHAR *GetExplicitMipmapName(int i) const = 0;
virtual BOOL ExplicitMipmapEnabled(int i) const = 0;
virtual int GetExplicitMipmapLevel(int i) const = 0;
// KLUDGE - Had to do this to compile under MAX4 beta
virtual void fnReload() {};
virtual void fnViewImage() {};
};
#endif

View File

@ -1,441 +1,441 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// hsVertexShader Class Functions //
// //
//// Version History /////////////////////////////////////////////////////////
// //
// 5.9.2001 mcn - Updated to reflect the new (temporary) vertex color/ //
// lighting model. //
// //
//////////////////////////////////////////////////////////////////////////////
#include "HeadSpin.h"
#include "Max.h"
#include "stdmat.h"
#include "istdplug.h"
#include "dummy.h"
#include "notetrck.h"
#include "../MaxMain/plMaxNode.h"
#include "hsBitVector.h"
#include "hsMatrix44.h"
#include "hsTemplates.h"
#include "../plSurface/hsGMaterial.h"
#include "UserPropMgr.h"
#include "hsMaxLayerBase.h"
#include "hsVertexShader.h"
#include "hsConverterUtils.h"
#include "hsControlConverter.h"
#include "hsExceptionStack.h"
#include "../plSurface/hsGMaterial.h"
#include "../plSurface/plLayerInterface.h"
#include "../plDrawable/plGeometrySpan.h"
#include "plMaxLightContext.h"
#include "plRenderGlobalContext.h"
#include "plLightMapGen.h"
#define MF_NATIVE_MAX_LIGHT
#define MF_NO_RAY_SHADOW
extern UserPropMgr gUserPropMgr;
extern TimeValue GetTime(Interface *gi);
//===========================================================================
// hsVertexShader
//===========================================================================
hsVertexShader::hsVertexShader() :
fConverterUtils(hsConverterUtils::Instance()),
fInterface(nil),
fLightMapGen(nil),
fShaded(0)
{
hsGuardBegin("hsVertexShader::hsVertexShader");
fLocalToWorld.Reset();
hsGuardEnd;
}
hsVertexShader::~hsVertexShader()
{
hsGuardBegin("hsVertexShader::~hsVertexShader");
hsGuardEnd;
}
hsVertexShader& hsVertexShader::Instance()
{
hsGuardBegin("hsVertexShader::Instance");
static hsVertexShader instance;
return instance;
hsGuardEnd;
}
void hsVertexShader::Open()
{
hsGuardBegin("hsVertexShader::InitLights");
fLocalToWorld.Reset();
fInterface = ::GetCOREInterface();
fLightMapGen = &plLightMapGen::Instance();
hsGuardEnd;
}
void hsVertexShader::Close()
{
hsGuardBegin("hsVertexShader::DeInitLights");
fLightMapGen = nil;
hsGuardEnd;
}
//// ShadeNode ///////////////////////////////////////////////////////////////
// Same as the other ShadeNode, only this shades an array of plGeometrySpans.
void hsVertexShader::ShadeNode(INode* node, hsMatrix44& l2w, hsMatrix44& w2l, hsTArray<plGeometrySpan *> &spans)
{
// If we're flagged for WaterColor, our vertex colors are already done.
if( ((plMaxNodeBase*)node)->GetCalcEdgeLens() || node->UserPropExists("XXXWaterColor") )
return;
fLightMapGen->InitNode(node);
fLocalToWorld = l2w;
hsMatrix44 tempMatrix = w2l; // l2w's inverse
tempMatrix.GetTranspose( &fNormalToWorld ); // Inverse-transpose of the fLocalToWorld matrix,
int i;
for( i = 0; i < spans.GetCount(); i++ )
IShadeSpan( spans[ i ], node);
fLightMapGen->DeInitNode();
fShaded++;
}
//// IShadeSpan //////////////////////////////////////////////////////////////
// Shades a single plGeometrySpan.
// 5.9.2001 mcn - Updated to support the new (temporary) vertex color/lighting
// method.
void hsVertexShader::IShadeSpan( plGeometrySpan *span, INode* node )
{
hsColorRGBA preDiffuse, rtDiffuse, matAmbient;
hsBitVector dirtyVector;
int i;
hsBool translucent, shadeIt, addingIt;
plLayerInterface *layer = nil;
hsGuardBegin("hsVertexShader::ShadeSpan");
const char* dbgNodeName = node->GetName();
if( span->fNumVerts == 0 )
return;
fShadeColorTable = TRACKED_NEW hsColorRGBA[ span->fNumVerts ];
fIllumColorTable = TRACKED_NEW hsColorRGBA[ span->fNumVerts ];
translucent = IsTranslucent( span->fMaterial );
/// Get material layer #0
addingIt = false;
shadeIt = !( span->fProps & plGeometrySpan::kPropNoPreShade );
if( span->fMaterial->GetNumLayers() != 0 )
{
layer = span->fMaterial->GetLayer( 0 );
if( layer->GetShadeFlags() & hsGMatState::kShadeNoShade )
shadeIt = false;
if( layer->GetBlendFlags() & hsGMatState::kBlendAdd )
addingIt = true;
}
float opacity = 1.f;
for( i = 0; i < span->fMaterial->GetNumLayers(); i++ )
{
plLayerInterface* lay = span->fMaterial->GetLayer(i);
if( (lay->GetBlendFlags() & hsGMatState::kBlendAlpha)
&&
(
!i
||
(lay->GetMiscFlags() & hsGMatState::kMiscRestartPassHere)
)
)
{
opacity = span->fMaterial->GetLayer(i)->GetOpacity();
}
}
/// Generate color table
if( shadeIt )
IShadeVertices( span, &dirtyVector, node, translucent );
else
{
for( i = 0; i < span->fNumVerts; i++ )
{
/// This is good for the old way, but not sure about the new way. Test once new way is in again -mcn
// fShadeColorTable[ i ].Set( 1, 1, 1, 1 );
// fIllumColorTable[ i ].Set( 0, 0, 0, 1 );
hsPoint3 position;
hsVector3 normal;
hsColorRGBA color, illum;
span->ExtractVertex( i, &position, &normal, &color, &illum );
span->ExtractInitColor( i, &color, &illum );
fShadeColorTable[ i ].Set( color.r, color.g, color.b, color.a );
fIllumColorTable[ i ].Set( illum.r, illum.g, illum.b, 1 );
}
}
/// Get mat colors to modulate by
if( layer == nil )
{
preDiffuse.Set( 1, 1, 1, 1 );
rtDiffuse.Set( 1, 1, 1, 1 );
matAmbient.Set( 0, 0, 0, 0 );
}
else
{
if( layer->GetShadeFlags() & hsGMatState::kShadeWhite )
{
preDiffuse.Set( 1, 1, 1, 1 );
rtDiffuse.Set( 1, 1, 1, 1 );
matAmbient.Set( 0, 0, 0, 0 );
}
else
{
preDiffuse = layer->GetPreshadeColor(); // This is for vertex-based lighting, which basically ignores preshading
rtDiffuse = layer->GetRuntimeColor(); // This is for vertex-based lighting, which basically ignores preshading
matAmbient = layer->GetAmbientColor();
matAmbient.a = 0;
}
preDiffuse.a = opacity;
rtDiffuse.a = opacity;
}
#if 0
/// Multiply by the material color, and scale by opacity if we're additive blending
/// Apply colors now, multiplying by the material color as we go
for( i = 0; i < span->fNumVerts; i++ )
{
fShadeColorTable[ i ] *= matDiffuse;
fShadeColorTable[ i ] += matAmbient;
fIllumColorTable[ i ] *= matDiffuse;
fIllumColorTable[ i ] += matAmbient;
}
if( addingIt )
{
for( i = 0; i < span->fNumVerts; i++ )
{
float opacity = fShadeColorTable[ i ].a;
fShadeColorTable[ i ] *= opacity;
fIllumColorTable[ i ] *= opacity;
}
}
#else
/// Combine shade and illum together into the diffuse color
if( ( span->fProps & plGeometrySpan::kLiteMask ) != plGeometrySpan::kLiteMaterial )
{
/// The two vertex lighting formulas take in a vetex color pre-processed, i.e. in
/// the form of: vtxColor = ( maxVtxColor * materialDiffuse + maxIllumColor )
span->fProps |= plGeometrySpan::kDiffuseFoldedIn;
if( !shadeIt )
{
for( i = 0; i < span->fNumVerts; i++ )
{
fIllumColorTable[ i ].a = 0;
fShadeColorTable[ i ] = (fShadeColorTable[ i ] * rtDiffuse) + fIllumColorTable[ i ];
fIllumColorTable[ i ].Set( 0, 0, 0, 0 );
}
}
else
{
for( i = 0; i < span->fNumVerts; i++ )
{
fIllumColorTable[ i ].a = 1.f;
// Following needs to be changed to allow user input vertex colors to modulate
// the runtime light values.
// fShadeColorTable[ i ] = fIllumColorTable[ i ] * rtDiffuse;
fShadeColorTable[ i ] = fShadeColorTable[ i ] * fIllumColorTable[ i ] * rtDiffuse;
fIllumColorTable[ i ].Set( 0, 0, 0, 0 );
}
}
}
else
{
if( !shadeIt )
{
// Not shaded, so runtime lit, so we want BLACK vertex colors
for( i = 0; i < span->fNumVerts; i++ )
{
fShadeColorTable[ i ].Set( 0, 0, 0, 0 );
fIllumColorTable[ i ].Set( 0, 0, 0, 0 );
}
}
else
{
for( i = 0; i < span->fNumVerts; i++ )
{
fShadeColorTable[ i ] *= fIllumColorTable[ i ];
fIllumColorTable[ i ].Set( 0, 0, 0, 0 );
}
}
}
#endif
/// Loop and stuff
for( i = 0; i < span->fNumVerts; i++ )
span->StuffVertex( i, fShadeColorTable + i, fIllumColorTable + i );
delete [] fShadeColorTable;
delete [] fIllumColorTable;
hsGuardEnd;
}
//// IShadeVertices //////////////////////////////////////////////////////////
// Shades an array of vertices from a plGeometrySpan.
// 5.9.2001 mcn - Updated for the new lighting model. Now on runtime, we
// want the following properties on each vertex:
// diffuseColor = vertexColor * matDiffuse + matAmbient (including alpha)
// specularColor = ( illumniation + pre-shading ) * matDiffuse + matAmbient
// We do the mat modulation outside of this function, so we
// just gotta make sure the two arrays get the right values.
void hsVertexShader::IShadeVertices( plGeometrySpan *span, hsBitVector *dirtyVector, INode* node, hsBool translucent )
{
hsGuardBegin( "hsVertexShader::IShadeVertices" );
plMaxNode* maxNode = (plMaxNode*)node;
if( maxNode->CanConvert() && (nil != maxNode->GetLightMapComponent()) )
return;
int index;
hsPoint3 position;
hsVector3 normal;
hsColorRGBA color, illum;
plTmpVertex3 *vertices;
/// Allocate temp vertex array
vertices = TRACKED_NEW plTmpVertex3[ span->fNumVerts ];
for( index = 0; index < span->fNumVerts; index++ )
{
span->ExtractVertex( index, &position, &normal, &color, &illum );
span->ExtractInitColor( index, &color, &illum );
/// fShadeColorTable is the shaded portion. fIllumColorTable is the illuminated portion;
/// for more and less confusing details, see above.
fShadeColorTable[ index ].Set( color.r, color.g, color.b, color.a );
fIllumColorTable[ index ].Set( illum.r, illum.g, illum.b, 1 );
position = fLocalToWorld * position;
normal = fNormalToWorld * normal;
vertices[ index ].fLocalPos = position;
vertices[ index ].fNormal = normal;
vertices[ index ].fNormal.Normalize();
}
const char* dbgNodeName = node->GetName();
TimeValue t = fInterface->GetTime();
Box3 bbox;
node->EvalWorldState(t).obj->GetDeformBBox(t, bbox, &node->GetObjectTM(t));
plMaxLightContext ctx(bbox, t);
for( index = 0; index < span->fNumVerts; index++ )
INativeShadeVtx(fIllumColorTable[index], ctx, vertices[ index ], translucent);
// Delete temp arrays
delete [] vertices;
hsGuardEnd;
}
void hsVertexShader::INativeShadeVtx(hsColorRGBA& shade, plMaxLightContext& ctx, const plTmpVertex3& vtx, hsBool translucent)
{
ctx.SetPoint(vtx.fLocalPos, vtx.fNormal);
Color color = fLightMapGen->ShadePoint(ctx);
shade.r += color.r;
shade.g += color.g;
shade.b += color.b;
// To handle two-sided translucency here, we should compute the shade on each side and sum them.
if( translucent )
{
ctx.SetPoint(vtx.fLocalPos, -vtx.fNormal);
color = fLightMapGen->ShadePoint(ctx);
shade.r += color.r;
shade.g += color.g;
shade.b += color.b;
}
}
void hsVertexShader::INativeShadowVtx(hsColorRGBA& shade, plMaxLightContext& ctx, const plTmpVertex3& vtx, hsBool translucent)
{
ctx.SetPoint(vtx.fLocalPos, vtx.fNormal);
Color color = fLightMapGen->ShadowPoint(ctx);
shade.r += color.r;
shade.g += color.g;
shade.b += color.b;
}
hsBool hsVertexShader::IsTranslucent( hsGMaterial *material )
{
hsGuardBegin("hsVertexShader::IsTranslucent");
if( material )
{
plLayerInterface* layer = material->GetLayer(0);
if( layer && ( layer->GetShadeFlags() & hsGMatState::kShadeSoftShadow ) )
{
return true;
}
}
return false;
hsGuardEnd;
}
/*==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 <http://www.gnu.org/licenses/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// hsVertexShader Class Functions //
// //
//// Version History /////////////////////////////////////////////////////////
// //
// 5.9.2001 mcn - Updated to reflect the new (temporary) vertex color/ //
// lighting model. //
// //
//////////////////////////////////////////////////////////////////////////////
#include "HeadSpin.h"
#include "Max.h"
#include "stdmat.h"
#include "istdplug.h"
#include "dummy.h"
#include "notetrck.h"
#include "../MaxMain/plMaxNode.h"
#include "hsBitVector.h"
#include "hsMatrix44.h"
#include "hsTemplates.h"
#include "../plSurface/hsGMaterial.h"
#include "UserPropMgr.h"
#include "hsMaxLayerBase.h"
#include "hsVertexShader.h"
#include "hsConverterUtils.h"
#include "hsControlConverter.h"
#include "hsExceptionStack.h"
#include "../plSurface/hsGMaterial.h"
#include "../plSurface/plLayerInterface.h"
#include "../plDrawable/plGeometrySpan.h"
#include "plMaxLightContext.h"
#include "plRenderGlobalContext.h"
#include "plLightMapGen.h"
#define MF_NATIVE_MAX_LIGHT
#define MF_NO_RAY_SHADOW
extern UserPropMgr gUserPropMgr;
extern TimeValue GetTime(Interface *gi);
//===========================================================================
// hsVertexShader
//===========================================================================
hsVertexShader::hsVertexShader() :
fConverterUtils(hsConverterUtils::Instance()),
fInterface(nil),
fLightMapGen(nil),
fShaded(0)
{
hsGuardBegin("hsVertexShader::hsVertexShader");
fLocalToWorld.Reset();
hsGuardEnd;
}
hsVertexShader::~hsVertexShader()
{
hsGuardBegin("hsVertexShader::~hsVertexShader");
hsGuardEnd;
}
hsVertexShader& hsVertexShader::Instance()
{
hsGuardBegin("hsVertexShader::Instance");
static hsVertexShader instance;
return instance;
hsGuardEnd;
}
void hsVertexShader::Open()
{
hsGuardBegin("hsVertexShader::InitLights");
fLocalToWorld.Reset();
fInterface = ::GetCOREInterface();
fLightMapGen = &plLightMapGen::Instance();
hsGuardEnd;
}
void hsVertexShader::Close()
{
hsGuardBegin("hsVertexShader::DeInitLights");
fLightMapGen = nil;
hsGuardEnd;
}
//// ShadeNode ///////////////////////////////////////////////////////////////
// Same as the other ShadeNode, only this shades an array of plGeometrySpans.
void hsVertexShader::ShadeNode(INode* node, hsMatrix44& l2w, hsMatrix44& w2l, hsTArray<plGeometrySpan *> &spans)
{
// If we're flagged for WaterColor, our vertex colors are already done.
if( ((plMaxNodeBase*)node)->GetCalcEdgeLens() || node->UserPropExists("XXXWaterColor") )
return;
fLightMapGen->InitNode(node);
fLocalToWorld = l2w;
hsMatrix44 tempMatrix = w2l; // l2w's inverse
tempMatrix.GetTranspose( &fNormalToWorld ); // Inverse-transpose of the fLocalToWorld matrix,
int i;
for( i = 0; i < spans.GetCount(); i++ )
IShadeSpan( spans[ i ], node);
fLightMapGen->DeInitNode();
fShaded++;
}
//// IShadeSpan //////////////////////////////////////////////////////////////
// Shades a single plGeometrySpan.
// 5.9.2001 mcn - Updated to support the new (temporary) vertex color/lighting
// method.
void hsVertexShader::IShadeSpan( plGeometrySpan *span, INode* node )
{
hsColorRGBA preDiffuse, rtDiffuse, matAmbient;
hsBitVector dirtyVector;
int i;
hsBool translucent, shadeIt, addingIt;
plLayerInterface *layer = nil;
hsGuardBegin("hsVertexShader::ShadeSpan");
const char* dbgNodeName = node->GetName();
if( span->fNumVerts == 0 )
return;
fShadeColorTable = TRACKED_NEW hsColorRGBA[ span->fNumVerts ];
fIllumColorTable = TRACKED_NEW hsColorRGBA[ span->fNumVerts ];
translucent = IsTranslucent( span->fMaterial );
/// Get material layer #0
addingIt = false;
shadeIt = !( span->fProps & plGeometrySpan::kPropNoPreShade );
if( span->fMaterial->GetNumLayers() != 0 )
{
layer = span->fMaterial->GetLayer( 0 );
if( layer->GetShadeFlags() & hsGMatState::kShadeNoShade )
shadeIt = false;
if( layer->GetBlendFlags() & hsGMatState::kBlendAdd )
addingIt = true;
}
float opacity = 1.f;
for( i = 0; i < span->fMaterial->GetNumLayers(); i++ )
{
plLayerInterface* lay = span->fMaterial->GetLayer(i);
if( (lay->GetBlendFlags() & hsGMatState::kBlendAlpha)
&&
(
!i
||
(lay->GetMiscFlags() & hsGMatState::kMiscRestartPassHere)
)
)
{
opacity = span->fMaterial->GetLayer(i)->GetOpacity();
}
}
/// Generate color table
if( shadeIt )
IShadeVertices( span, &dirtyVector, node, translucent );
else
{
for( i = 0; i < span->fNumVerts; i++ )
{
/// This is good for the old way, but not sure about the new way. Test once new way is in again -mcn
// fShadeColorTable[ i ].Set( 1, 1, 1, 1 );
// fIllumColorTable[ i ].Set( 0, 0, 0, 1 );
hsPoint3 position;
hsVector3 normal;
hsColorRGBA color, illum;
span->ExtractVertex( i, &position, &normal, &color, &illum );
span->ExtractInitColor( i, &color, &illum );
fShadeColorTable[ i ].Set( color.r, color.g, color.b, color.a );
fIllumColorTable[ i ].Set( illum.r, illum.g, illum.b, 1 );
}
}
/// Get mat colors to modulate by
if( layer == nil )
{
preDiffuse.Set( 1, 1, 1, 1 );
rtDiffuse.Set( 1, 1, 1, 1 );
matAmbient.Set( 0, 0, 0, 0 );
}
else
{
if( layer->GetShadeFlags() & hsGMatState::kShadeWhite )
{
preDiffuse.Set( 1, 1, 1, 1 );
rtDiffuse.Set( 1, 1, 1, 1 );
matAmbient.Set( 0, 0, 0, 0 );
}
else
{
preDiffuse = layer->GetPreshadeColor(); // This is for vertex-based lighting, which basically ignores preshading
rtDiffuse = layer->GetRuntimeColor(); // This is for vertex-based lighting, which basically ignores preshading
matAmbient = layer->GetAmbientColor();
matAmbient.a = 0;
}
preDiffuse.a = opacity;
rtDiffuse.a = opacity;
}
#if 0
/// Multiply by the material color, and scale by opacity if we're additive blending
/// Apply colors now, multiplying by the material color as we go
for( i = 0; i < span->fNumVerts; i++ )
{
fShadeColorTable[ i ] *= matDiffuse;
fShadeColorTable[ i ] += matAmbient;
fIllumColorTable[ i ] *= matDiffuse;
fIllumColorTable[ i ] += matAmbient;
}
if( addingIt )
{
for( i = 0; i < span->fNumVerts; i++ )
{
float opacity = fShadeColorTable[ i ].a;
fShadeColorTable[ i ] *= opacity;
fIllumColorTable[ i ] *= opacity;
}
}
#else
/// Combine shade and illum together into the diffuse color
if( ( span->fProps & plGeometrySpan::kLiteMask ) != plGeometrySpan::kLiteMaterial )
{
/// The two vertex lighting formulas take in a vetex color pre-processed, i.e. in
/// the form of: vtxColor = ( maxVtxColor * materialDiffuse + maxIllumColor )
span->fProps |= plGeometrySpan::kDiffuseFoldedIn;
if( !shadeIt )
{
for( i = 0; i < span->fNumVerts; i++ )
{
fIllumColorTable[ i ].a = 0;
fShadeColorTable[ i ] = (fShadeColorTable[ i ] * rtDiffuse) + fIllumColorTable[ i ];
fIllumColorTable[ i ].Set( 0, 0, 0, 0 );
}
}
else
{
for( i = 0; i < span->fNumVerts; i++ )
{
fIllumColorTable[ i ].a = 1.f;
// Following needs to be changed to allow user input vertex colors to modulate
// the runtime light values.
// fShadeColorTable[ i ] = fIllumColorTable[ i ] * rtDiffuse;
fShadeColorTable[ i ] = fShadeColorTable[ i ] * fIllumColorTable[ i ] * rtDiffuse;
fIllumColorTable[ i ].Set( 0, 0, 0, 0 );
}
}
}
else
{
if( !shadeIt )
{
// Not shaded, so runtime lit, so we want BLACK vertex colors
for( i = 0; i < span->fNumVerts; i++ )
{
fShadeColorTable[ i ].Set( 0, 0, 0, 0 );
fIllumColorTable[ i ].Set( 0, 0, 0, 0 );
}
}
else
{
for( i = 0; i < span->fNumVerts; i++ )
{
fShadeColorTable[ i ] *= fIllumColorTable[ i ];
fIllumColorTable[ i ].Set( 0, 0, 0, 0 );
}
}
}
#endif
/// Loop and stuff
for( i = 0; i < span->fNumVerts; i++ )
span->StuffVertex( i, fShadeColorTable + i, fIllumColorTable + i );
delete [] fShadeColorTable;
delete [] fIllumColorTable;
hsGuardEnd;
}
//// IShadeVertices //////////////////////////////////////////////////////////
// Shades an array of vertices from a plGeometrySpan.
// 5.9.2001 mcn - Updated for the new lighting model. Now on runtime, we
// want the following properties on each vertex:
// diffuseColor = vertexColor * matDiffuse + matAmbient (including alpha)
// specularColor = ( illumniation + pre-shading ) * matDiffuse + matAmbient
// We do the mat modulation outside of this function, so we
// just gotta make sure the two arrays get the right values.
void hsVertexShader::IShadeVertices( plGeometrySpan *span, hsBitVector *dirtyVector, INode* node, hsBool translucent )
{
hsGuardBegin( "hsVertexShader::IShadeVertices" );
plMaxNode* maxNode = (plMaxNode*)node;
if( maxNode->CanConvert() && (nil != maxNode->GetLightMapComponent()) )
return;
int index;
hsPoint3 position;
hsVector3 normal;
hsColorRGBA color, illum;
plTmpVertex3 *vertices;
/// Allocate temp vertex array
vertices = TRACKED_NEW plTmpVertex3[ span->fNumVerts ];
for( index = 0; index < span->fNumVerts; index++ )
{
span->ExtractVertex( index, &position, &normal, &color, &illum );
span->ExtractInitColor( index, &color, &illum );
/// fShadeColorTable is the shaded portion. fIllumColorTable is the illuminated portion;
/// for more and less confusing details, see above.
fShadeColorTable[ index ].Set( color.r, color.g, color.b, color.a );
fIllumColorTable[ index ].Set( illum.r, illum.g, illum.b, 1 );
position = fLocalToWorld * position;
normal = fNormalToWorld * normal;
vertices[ index ].fLocalPos = position;
vertices[ index ].fNormal = normal;
vertices[ index ].fNormal.Normalize();
}
const char* dbgNodeName = node->GetName();
TimeValue t = fInterface->GetTime();
Box3 bbox;
node->EvalWorldState(t).obj->GetDeformBBox(t, bbox, &node->GetObjectTM(t));
plMaxLightContext ctx(bbox, t);
for( index = 0; index < span->fNumVerts; index++ )
INativeShadeVtx(fIllumColorTable[index], ctx, vertices[ index ], translucent);
// Delete temp arrays
delete [] vertices;
hsGuardEnd;
}
void hsVertexShader::INativeShadeVtx(hsColorRGBA& shade, plMaxLightContext& ctx, const plTmpVertex3& vtx, hsBool translucent)
{
ctx.SetPoint(vtx.fLocalPos, vtx.fNormal);
Color color = fLightMapGen->ShadePoint(ctx);
shade.r += color.r;
shade.g += color.g;
shade.b += color.b;
// To handle two-sided translucency here, we should compute the shade on each side and sum them.
if( translucent )
{
ctx.SetPoint(vtx.fLocalPos, -vtx.fNormal);
color = fLightMapGen->ShadePoint(ctx);
shade.r += color.r;
shade.g += color.g;
shade.b += color.b;
}
}
void hsVertexShader::INativeShadowVtx(hsColorRGBA& shade, plMaxLightContext& ctx, const plTmpVertex3& vtx, hsBool translucent)
{
ctx.SetPoint(vtx.fLocalPos, vtx.fNormal);
Color color = fLightMapGen->ShadowPoint(ctx);
shade.r += color.r;
shade.g += color.g;
shade.b += color.b;
}
hsBool hsVertexShader::IsTranslucent( hsGMaterial *material )
{
hsGuardBegin("hsVertexShader::IsTranslucent");
if( material )
{
plLayerInterface* layer = material->GetLayer(0);
if( layer && ( layer->GetShadeFlags() & hsGMatState::kShadeSoftShadow ) )
{
return true;
}
}
return false;
hsGuardEnd;
}

View File

@ -1,85 +1,85 @@
/*==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 <http://www.gnu.org/licenses/>.
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 __HSVERTEXSHADER_H
#define __HSVERTEXSHADER_H
class hsConverterUtils;
class hsBitVector;
class plMaxLightContext;
class plGeometrySpan;
struct hsColorRGBA;
class plLightMapGen;
class hsVertexShader
{
private:
hsVertexShader();
public:
virtual ~hsVertexShader();
static hsVertexShader& Instance();
void ShadeNode(INode* node, hsMatrix44& l2w, hsMatrix44& w2l, hsTArray<plGeometrySpan *> &spans);
void Open();
void Close();
private:
/// Temporary vertex class
class plTmpVertex3
{
public:
hsPoint3 fLocalPos;
hsVector3 fNormal;
};
hsBool ILightIncludesNode(LightObject* light, INode* node);
void INativeShadeVtx(hsColorRGBA& shade, plMaxLightContext& ctx, const plTmpVertex3& vtx, hsBool translucent);
void INativeShadowVtx(hsColorRGBA& shade, plMaxLightContext& ctx, const plTmpVertex3& vtx, hsBool translucent);
hsBool IsTranslucent( hsGMaterial *material );
void IShadeSpan( plGeometrySpan *span, INode* node );
void IShadeVertices( plGeometrySpan *span, hsBitVector *dirtyVector, INode* node, hsBool translucent );
private:
Interface *fInterface;
hsConverterUtils &fConverterUtils;
plLightMapGen* fLightMapGen;
hsMatrix44 fLocalToWorld, fNormalToWorld; // fN2W is inv-transpose of fL2W
int fShaded; // just record-keeping
hsColorRGBA *fShadeColorTable;
hsColorRGBA *fIllumColorTable;
};
/*==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 <http://www.gnu.org/licenses/>.
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 __HSVERTEXSHADER_H
#define __HSVERTEXSHADER_H
class hsConverterUtils;
class hsBitVector;
class plMaxLightContext;
class plGeometrySpan;
struct hsColorRGBA;
class plLightMapGen;
class hsVertexShader
{
private:
hsVertexShader();
public:
virtual ~hsVertexShader();
static hsVertexShader& Instance();
void ShadeNode(INode* node, hsMatrix44& l2w, hsMatrix44& w2l, hsTArray<plGeometrySpan *> &spans);
void Open();
void Close();
private:
/// Temporary vertex class
class plTmpVertex3
{
public:
hsPoint3 fLocalPos;
hsVector3 fNormal;
};
hsBool ILightIncludesNode(LightObject* light, INode* node);
void INativeShadeVtx(hsColorRGBA& shade, plMaxLightContext& ctx, const plTmpVertex3& vtx, hsBool translucent);
void INativeShadowVtx(hsColorRGBA& shade, plMaxLightContext& ctx, const plTmpVertex3& vtx, hsBool translucent);
hsBool IsTranslucent( hsGMaterial *material );
void IShadeSpan( plGeometrySpan *span, INode* node );
void IShadeVertices( plGeometrySpan *span, hsBitVector *dirtyVector, INode* node, hsBool translucent );
private:
Interface *fInterface;
hsConverterUtils &fConverterUtils;
plLightMapGen* fLightMapGen;
hsMatrix44 fLocalToWorld, fNormalToWorld; // fN2W is inv-transpose of fL2W
int fShaded; // just record-keeping
hsColorRGBA *fShadeColorTable;
hsColorRGBA *fIllumColorTable;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,113 +1,113 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#include "hsTypes.h"
#include "../pnKeyedObject/plKey.h"
class BitmapInfo;
class Bitmap;
class plBitmap;
class plMipmap;
class hsMaxLayerBase;
class plLocation;
class plErrorMsg;
class plBitmapData
{
public:
enum
{
kClampU = 0x01,
kClampV = 0x02
};
const char *fileName;
UInt32 texFlags;
UInt32 createFlags;
hsScalar detailDropoffStart;
hsScalar detailDropoffStop;
hsScalar detailMax;
hsScalar detailMin;
float sig;
hsBool isStaticCubicEnvMap;
hsBool invertAlpha;
const char *faceNames[ 6 ];
UInt32 maxDimension;
UInt8 clampFlags;
bool useJPEG;
plBitmapData()
{
fileName = nil;
texFlags = 0;
createFlags = 0;
detailDropoffStart = detailDropoffStop = 0.f;
detailMax = detailMin = 0.f;
sig = 0;
isStaticCubicEnvMap = false;
invertAlpha = false;
faceNames[ 0 ] = faceNames[ 1 ] = faceNames[ 2 ] = faceNames[ 3 ] = faceNames[ 4 ] = faceNames[ 5 ] = nil;
maxDimension = 0;
clampFlags = 0;
useJPEG = false;
}
};
class plRegistryKeyIterator;
class plBitmapCreator
{
public:
static plBitmapCreator &Instance();
plBitmap *CreateTexture( plBitmapData *bd, const plLocation &loc, int clipID = -1 );
plMipmap *CreateBlankMipmap( UInt32 width, UInt32 height, unsigned config, UInt8 numLevels, const char *keyName, const plLocation &keyLocation );
void Init( hsBool save, plErrorMsg *msg );
void DeInit( void );
void CleanUpMaps( void );
~plBitmapCreator();
// This will also set the key you pass in to nil, so be careful
void DeleteExportedBitmap( const plKey &key );
protected:
plErrorMsg *fErrorMsg;
plBitmapCreator();
plBitmap *ICreateTexture( plBitmapData *bd, const plLocation &loc, int clipID = -1 );
plMipmap *ICreateBitmap( plBitmapData *bd );
void ICheckOutBitmap( BitmapInfo *bInfo, Bitmap *bm, const char *fileName );
int IResampBitmap( Bitmap *bm, plMipmap &hBitmap );
int ICopyBitmap( Bitmap *bm, plMipmap &hBitmap );
int IInvertAlpha( plMipmap &hBitmap );
void IAddBitmap( plBitmap *bitmap, hsBool dontRef = false );
};
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#include "hsTypes.h"
#include "../pnKeyedObject/plKey.h"
class BitmapInfo;
class Bitmap;
class plBitmap;
class plMipmap;
class hsMaxLayerBase;
class plLocation;
class plErrorMsg;
class plBitmapData
{
public:
enum
{
kClampU = 0x01,
kClampV = 0x02
};
const char *fileName;
UInt32 texFlags;
UInt32 createFlags;
hsScalar detailDropoffStart;
hsScalar detailDropoffStop;
hsScalar detailMax;
hsScalar detailMin;
float sig;
hsBool isStaticCubicEnvMap;
hsBool invertAlpha;
const char *faceNames[ 6 ];
UInt32 maxDimension;
UInt8 clampFlags;
bool useJPEG;
plBitmapData()
{
fileName = nil;
texFlags = 0;
createFlags = 0;
detailDropoffStart = detailDropoffStop = 0.f;
detailMax = detailMin = 0.f;
sig = 0;
isStaticCubicEnvMap = false;
invertAlpha = false;
faceNames[ 0 ] = faceNames[ 1 ] = faceNames[ 2 ] = faceNames[ 3 ] = faceNames[ 4 ] = faceNames[ 5 ] = nil;
maxDimension = 0;
clampFlags = 0;
useJPEG = false;
}
};
class plRegistryKeyIterator;
class plBitmapCreator
{
public:
static plBitmapCreator &Instance();
plBitmap *CreateTexture( plBitmapData *bd, const plLocation &loc, int clipID = -1 );
plMipmap *CreateBlankMipmap( UInt32 width, UInt32 height, unsigned config, UInt8 numLevels, const char *keyName, const plLocation &keyLocation );
void Init( hsBool save, plErrorMsg *msg );
void DeInit( void );
void CleanUpMaps( void );
~plBitmapCreator();
// This will also set the key you pass in to nil, so be careful
void DeleteExportedBitmap( const plKey &key );
protected:
plErrorMsg *fErrorMsg;
plBitmapCreator();
plBitmap *ICreateTexture( plBitmapData *bd, const plLocation &loc, int clipID = -1 );
plMipmap *ICreateBitmap( plBitmapData *bd );
void ICheckOutBitmap( BitmapInfo *bInfo, Bitmap *bm, const char *fileName );
int IResampBitmap( Bitmap *bm, plMipmap &hBitmap );
int ICopyBitmap( Bitmap *bm, plMipmap &hBitmap );
int IInvertAlpha( plMipmap &hBitmap );
void IAddBitmap( plBitmap *bitmap, hsBool dontRef = false );
};

File diff suppressed because it is too large Load Diff

View File

@ -1,134 +1,134 @@
/*==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 <http://www.gnu.org/licenses/>.
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 plClusterUtil_inc
#define plClusterUtil_inc
#include "hsGeometry3.h"
#include "hsColorRGBA.h"
#include "../plDrawable/plSpanInstance.h"
class plMaxNode;
class plClusterGroup;
class plSpanTemplateB;
class hsBounds3Ext;
class plCluster;
class hsGMaterial;
class plDeformVert
{
public:
// Begin returns true if it's actually planning to do anything.
// If it returns false, End will still get called, but GetDel probably won't.
virtual hsBool Begin(INode* templNode, const hsBounds3Ext& wBnd) { return false; }
virtual void End() {}
hsVector3 GetDel(const hsPoint3& p) { return GetDel(Point3(p.fX, p.fY, p.fZ)); }
virtual hsVector3 GetDel(const Point3& p) { return hsVector3(0,0,0); }
};
class plShadeVert
{
public:
virtual hsBool Begin(INode* templNode, const hsBounds3Ext& wBnd) { return false; }
virtual void End() {}
Color GetShade(const hsPoint3& p, const hsVector3& n) { return GetShade(Point3(p.fX, p.fY, p.fZ), Point3(n.fX, n.fY, n.fZ)); }
virtual Color GetShade(const Point3& p, const Point3& n) { return Color(0,0,0); }
};
class plL2WTab : public Tab<Matrix3> {};
class plL2WTabTab : public Tab<plL2WTab*> {};
class plPoint3Tab : public Tab<hsVector3> {};
class plPoint3TabTab : public Tab<plPoint3Tab*> {};
class plColorTab : public Tab<UInt32> {};
class plColorTabTab : public Tab<plColorTab*> {};
class plSpanTemplTab : public Tab<plSpanTemplateB*> {};
class plClusterUtil
{
protected:
UInt32 fIdx;
plClusterGroup* fGroup;
plMaxNode* fTemplNode;
plSpanTemplateB* fTemplate;
int fMinFaces;
int fMaxFaces;
hsScalar fMinSize;
int fMinInsts;
int fMaxInsts;
plSpanEncoding ISelectEncoding(plPoint3TabTab& delPos, plColorTabTab& colors);
void IAllocPosAndColor(plSpanTemplateB* templ, const plL2WTab& insts,
plPoint3TabTab& delPos, plColorTabTab& colors);
void IDelPosAndColor(plSpanTemplateB* templ,
const plL2WTab& insts, plDeformVert* def, plShadeVert* shade,
plPoint3TabTab& delPos, plColorTabTab& colors);
void IAddInstsToCluster(plCluster* cluster, plSpanTemplateB* templ,
const plL2WTab& insts,
plPoint3TabTab& delPos,
plColorTabTab& colors);
void IFreePosAndColor(plPoint3TabTab& delPos, plColorTabTab& colors) const;
void IFreeClustersRecur(plL2WTabTab& dst) const;
void IFindClustersRecur(plSpanTemplateB* templ, plL2WTab& src, plL2WTabTab& dst);
hsBool ISplitCluster(plSpanTemplateB* templ, plL2WTab& src, plL2WTab& lo, plL2WTab& hi);
int ISelectAxis(const plL2WTab& src) const;
Box3 IBound(const plL2WTab& src) const;
Point3 ILength(const plL2WTab& src) const;
void ISortTemplate(plSpanTemplateB* templ) const;
plSpanTemplateB* IAddTemplate(plMaxNode* templNode, plGeometrySpan* geo);
void ITemplateFromGeo(plSpanTemplateB* templ, plGeometrySpan* geo);
void ISortTemplates(plSpanTemplTab& templs) const;
void IAddTemplates(plMaxNode* templNode, plSpanTemplTab& templs);
void ISetupGroupFromTemplate(plMaxNode* templ);
public:
plClusterUtil();
~plClusterUtil();
plSpanTemplTab MakeTemplates(INode* templNode);
plClusterGroup* CreateGroup(plMaxNode* node, const char* name);
plClusterGroup* SetupGroup(plClusterGroup* group, plMaxNode* node, plSpanTemplateB* templ);
plClusterGroup* GetGroup() const { return fGroup; }
void AddClusters(plL2WTab& insts, plDeformVert* def, plShadeVert* shade);
};
#endif // plClusterUtil_inc
/*==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 <http://www.gnu.org/licenses/>.
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 plClusterUtil_inc
#define plClusterUtil_inc
#include "hsGeometry3.h"
#include "hsColorRGBA.h"
#include "../plDrawable/plSpanInstance.h"
class plMaxNode;
class plClusterGroup;
class plSpanTemplateB;
class hsBounds3Ext;
class plCluster;
class hsGMaterial;
class plDeformVert
{
public:
// Begin returns true if it's actually planning to do anything.
// If it returns false, End will still get called, but GetDel probably won't.
virtual hsBool Begin(INode* templNode, const hsBounds3Ext& wBnd) { return false; }
virtual void End() {}
hsVector3 GetDel(const hsPoint3& p) { return GetDel(Point3(p.fX, p.fY, p.fZ)); }
virtual hsVector3 GetDel(const Point3& p) { return hsVector3(0,0,0); }
};
class plShadeVert
{
public:
virtual hsBool Begin(INode* templNode, const hsBounds3Ext& wBnd) { return false; }
virtual void End() {}
Color GetShade(const hsPoint3& p, const hsVector3& n) { return GetShade(Point3(p.fX, p.fY, p.fZ), Point3(n.fX, n.fY, n.fZ)); }
virtual Color GetShade(const Point3& p, const Point3& n) { return Color(0,0,0); }
};
class plL2WTab : public Tab<Matrix3> {};
class plL2WTabTab : public Tab<plL2WTab*> {};
class plPoint3Tab : public Tab<hsVector3> {};
class plPoint3TabTab : public Tab<plPoint3Tab*> {};
class plColorTab : public Tab<UInt32> {};
class plColorTabTab : public Tab<plColorTab*> {};
class plSpanTemplTab : public Tab<plSpanTemplateB*> {};
class plClusterUtil
{
protected:
UInt32 fIdx;
plClusterGroup* fGroup;
plMaxNode* fTemplNode;
plSpanTemplateB* fTemplate;
int fMinFaces;
int fMaxFaces;
hsScalar fMinSize;
int fMinInsts;
int fMaxInsts;
plSpanEncoding ISelectEncoding(plPoint3TabTab& delPos, plColorTabTab& colors);
void IAllocPosAndColor(plSpanTemplateB* templ, const plL2WTab& insts,
plPoint3TabTab& delPos, plColorTabTab& colors);
void IDelPosAndColor(plSpanTemplateB* templ,
const plL2WTab& insts, plDeformVert* def, plShadeVert* shade,
plPoint3TabTab& delPos, plColorTabTab& colors);
void IAddInstsToCluster(plCluster* cluster, plSpanTemplateB* templ,
const plL2WTab& insts,
plPoint3TabTab& delPos,
plColorTabTab& colors);
void IFreePosAndColor(plPoint3TabTab& delPos, plColorTabTab& colors) const;
void IFreeClustersRecur(plL2WTabTab& dst) const;
void IFindClustersRecur(plSpanTemplateB* templ, plL2WTab& src, plL2WTabTab& dst);
hsBool ISplitCluster(plSpanTemplateB* templ, plL2WTab& src, plL2WTab& lo, plL2WTab& hi);
int ISelectAxis(const plL2WTab& src) const;
Box3 IBound(const plL2WTab& src) const;
Point3 ILength(const plL2WTab& src) const;
void ISortTemplate(plSpanTemplateB* templ) const;
plSpanTemplateB* IAddTemplate(plMaxNode* templNode, plGeometrySpan* geo);
void ITemplateFromGeo(plSpanTemplateB* templ, plGeometrySpan* geo);
void ISortTemplates(plSpanTemplTab& templs) const;
void IAddTemplates(plMaxNode* templNode, plSpanTemplTab& templs);
void ISetupGroupFromTemplate(plMaxNode* templ);
public:
plClusterUtil();
~plClusterUtil();
plSpanTemplTab MakeTemplates(INode* templNode);
plClusterGroup* CreateGroup(plMaxNode* node, const char* name);
plClusterGroup* SetupGroup(plClusterGroup* group, plMaxNode* node, plSpanTemplateB* templ);
plClusterGroup* GetGroup() const { return fGroup; }
void AddClusters(plL2WTab& insts, plDeformVert* def, plShadeVert* shade);
};
#endif // plClusterUtil_inc

View File

@ -1,498 +1,498 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
//
// 3DSMax HeadSpin exporter
//
#include "hsTypes.h"
#include "Max.h"
#include "istdplug.h"
#include "Notify.h"
#include <commdlg.h>
#include "bmmlib.h"
#include "INode.h"
#include "plConvert.h"
#include "hsResMgr.h"
#include "hsTemplates.h"
#include "hsConverterUtils.h"
#include "hsControlConverter.h"
#include "plMeshConverter.h"
#include "hsMaterialConverter.h"
#include "plLayerConverter.h"
#include "UserPropMgr.h"
#include "hsStringTokenizer.h"
#include "../MaxExport/plErrorMsg.h"
#include "hsVertexShader.h"
#include "plLightMapGen.h"
#include "plBitmapCreator.h"
#include "plgDispatch.h"
#include "../pnMessage/plTimeMsg.h"
#include "../MaxComponent/plComponent.h"
#include "../MaxMain/plMaxNode.h"
#include "../plMessage/plNodeCleanupMsg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../MaxComponent/plClusterComponent.h"
#include "../plPhysX/plSimulationMgr.h"
#include "../MaxMain/plPhysXCooking.h"
#include "../MaxExport/plExportProgressBar.h"
#include "hsUtils.h"
#include "../MaxMain/plGetLocationDlg.h"
#ifdef HS_DEBUGGING
#define HS_NO_TRY
#endif
plConvert::plConvert() : fWarned(0)
{
}
plConvert& plConvert::Instance()
{
static plConvert theInstance;
return theInstance;
}
hsBool plConvert::IOK()
{
return (!fQuit && !fpErrorMsg->IsBogus() ) ? true: false;
}
hsBool plConvert::Convert()
{
#ifndef HS_NO_TRY
try
#endif
{
fSettings->fReconvert = false;
fWarned = 0;
fInterface->SetIncludeXRefsInHierarchy(TRUE);
plMaxNode *pNode = (plMaxNode *)fInterface->GetRootNode();
AddMessageToQueue(new plTransformMsg(nil, nil, nil, nil));
AddMessageToQueue(new plDelayedTransformMsg(nil, nil, nil, nil));
IFindDuplicateNames();
plExportProgressBar bar;
hsBool retVal = true; // sometime, we might look at this
if( !IAutoClusterRecur(pNode) )
{
fQuit = true;
}
if(IOK())
{
bar.Start("Clear Old Data");
retVal = pNode->DoAllRecur( plMaxNode::ClearData, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Convert Validate");
retVal = pNode->DoRecur( plMaxNode::ConvertValidate, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Components Initialize");
retVal = pNode->DoRecur( plMaxNode::SetupPropertiesPass, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Prepare for skinning");
retVal = pNode->DoRecur( plMaxNode::PrepareSkin, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Make Scene Object");
retVal = pNode->DoRecur( plMaxNode::MakeSceneObject, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Make Physical");
plPhysXCooking::Init();
retVal = pNode->DoRecur( plMaxNode::MakePhysical, fpErrorMsg, fSettings, &bar );
plPhysXCooking::Shutdown();
}
if(IOK())
{
bar.Start("Component Preconvert");
retVal = pNode->DoRecur( plMaxNode::FirstComponentPass, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Make Controller");
retVal = pNode->DoRecur( plMaxNode::MakeController, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{ // must be before mesh
bar.Start("Make Coord Interface");
retVal = pNode->DoRecur( plMaxNode::MakeCoordinateInterface, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{ // must be after coord interface but before pool data is created.
bar.Start("Make Connections");
retVal = pNode->DoRecur( plMaxNode::MakeParentOrRoomConnection, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{ // must be before simulation
bar.Start("Make Mesh");
retVal = pNode->DoRecur( plMaxNode::MakeMesh, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{ // doesn't matter when
bar.Start("Make Light");
retVal = pNode->DoRecur( plMaxNode::MakeLight, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{ // doesn't matter when
bar.Start("Make Occluder");
retVal = pNode->DoRecur( plMaxNode::MakeOccluder, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{ // must be after mesh
bar.Start("Make Modifiers");
retVal = pNode->DoRecur( plMaxNode::MakeModifiers, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Convert Components");
retVal = pNode->DoRecur( plMaxNode::ConvertComponents, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
// do this after convert
bar.Start("Set Up Interface References");
retVal = pNode->DoRecur( plMaxNode::MakeIfaceReferences, fpErrorMsg, fSettings, &bar );
}
if(IOK() && fSettings->fDoPreshade)
{
// These need to be opened after the components have had a chance to flag the MaxNodes
plLightMapGen::Instance().Open(fInterface, fInterface->GetTime(), fSettings->fDoLightMap);
hsVertexShader::Instance().Open();
bar.Start("Preshade Geometry");
retVal = pNode->DoRecur( plMaxNode::ShadeMesh, fpErrorMsg, fSettings, &bar );
plLightMapGen::Instance().Close();
hsVertexShader::Instance().Close();
}
if(IOK())
{
// Do this next-to-last--allows all the components to free up any temp data they kept around
bar.Start("Component DeInit");
retVal = pNode->DoRecur( plMaxNode::DeInitComponents, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
// Do this very last--it de-inits and frees all the maxNodeDatas lying around
bar.Start("Clear MaxNodeDatas");
retVal = pNode->DoAllRecur( plMaxNode::ClearMaxNodeData, fpErrorMsg, fSettings, &bar );
}
// fpErrorMsg->Set();
DeInit();
fInterface->SetIncludeXRefsInHierarchy(FALSE);
return IOK();
}
#ifndef HS_NO_TRY
catch(plErrorMsg& err)
{
DeInit();
fInterface->SetIncludeXRefsInHierarchy(FALSE);
err.Show();
return false;
}
catch(...)
{
DeInit();
fInterface->SetIncludeXRefsInHierarchy(FALSE);
fpErrorMsg->Set(true, "plConvert", "Unknown error during convert\n");
fpErrorMsg->Show();
return false;
}
#endif
}
//#include "../MaxMain/plMaxNodeData.h"
//#include <set>
hsBool ConvertList(hsTArray<plMaxNode*>& nodes, PMaxNodeFunc p, plErrorMsg *errMsg, plConvertSettings *settings)
{
for (int i = 0; i < nodes.Count(); i++)
{
(nodes[i]->*p)(errMsg, settings);
if (errMsg && errMsg->IsBogus())
return false;
}
return true;
}
hsBool plConvert::Convert(hsTArray<plMaxNode*>& nodes)
{
#ifndef HS_NO_TRY
try
#endif
{
fSettings->fReconvert = true;
hsBool retVal = true;
if (IOK())
retVal = ConvertList(nodes, plMaxNode::ClearData, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::ConvertValidate, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::SetupPropertiesPass, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::PrepareSkin, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::MakeSceneObject, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::FirstComponentPass, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::MakeController, fpErrorMsg,fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::MakeCoordinateInterface, fpErrorMsg, fSettings);// must be before mesh
if(IOK())
retVal = ConvertList(nodes, plMaxNode::MakeParentOrRoomConnection, fpErrorMsg, fSettings); // after coord, before mesh (or any other pool data).
// These shouldn't be opened until the components have had a chance to flag the MaxNodes
plLightMapGen::Instance().Open(fInterface, fInterface->GetTime(), fSettings->fDoLightMap);
hsVertexShader::Instance().Open();
if(IOK())
retVal = ConvertList(nodes, plMaxNode::MakeMesh, fpErrorMsg, fSettings); // must be before simulation
if(IOK()) // doesn't matter when
retVal = ConvertList(nodes, plMaxNode::MakeLight, fpErrorMsg, fSettings);
if(IOK()) // doesn't matter when
retVal = ConvertList(nodes, plMaxNode::MakeOccluder, fpErrorMsg, fSettings);
if(IOK()) // must be after mesh
retVal = ConvertList(nodes, plMaxNode::MakeModifiers, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::ConvertComponents, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::ShadeMesh, fpErrorMsg, fSettings);
// These may be used by components, so don't close them till the end.
plLightMapGen::Instance().Close();
hsVertexShader::Instance().Close();
plgDispatch::MsgSend(new plTransformMsg(nil, nil, nil, nil));
plgDispatch::MsgSend(new plDelayedTransformMsg(nil, nil, nil, nil));
DeInit();
return IOK();
}
#ifndef HS_NO_TRY
catch(plErrorMsg& err)
{
err.Show();
return false;
}
catch(...)
{
hsMessageBox("Unknown error during convert", "plConvert", hsMessageBoxNormal);
return false;
}
#endif
}
hsBool plConvert::Init(Interface *ip, plErrorMsg* msg, plConvertSettings *settings)
{
fInterface = ip;
fpErrorMsg = msg;
fSettings = settings;
// Move us to time 0, so that things like initial transforms are always consistent with the 0th frame.
// This saves our asses from things like the patch-generation process later
ip->SetTime( 0, false );
hsConverterUtils::Instance().Init(true, fpErrorMsg);
plBitmapCreator::Instance().Init(true, fpErrorMsg);
hsMaterialConverter::Instance().Init(true, fpErrorMsg);
hsControlConverter::Instance().Init(fpErrorMsg);
plMeshConverter::Instance().Init(true, fpErrorMsg);
plLayerConverter::Instance().Init(true, fpErrorMsg);
plGetLocationDlg::Instance().ResetDefaultLocation();
fQuit = false;
return true;
}
void plConvert::DeInit()
{
// Undo any autogenerated clusters.
IAutoUnClusterRecur(fInterface->GetRootNode());
// clear out the message queue
for (int i = 0; i < fMsgQueue.Count(); i++)
plgDispatch::MsgSend(fMsgQueue[i]);
fMsgQueue.Reset();
hsControlConverter::Instance().DeInit();
plMeshConverter::Instance().DeInit();
plLayerConverter::Instance().DeInit();
// Moving this to the end of writing the files out. Yes, this means that any unused mipmaps still get
// written to disk, including ones loaded on preload, but it's the only way to get shared texture pages
// to work without loading in the entire age worth of reffing objects. - 5.30.2002 mcn
// plBitmapCreator::Instance().DeInit();
plNodeCleanupMsg *clean = TRACKED_NEW plNodeCleanupMsg();
plgDispatch::MsgSend( clean );
}
void plConvert::AddMessageToQueue(plMessage* msg)
{
fMsgQueue.Append(msg);
}
void plConvert::SendEnvironmentMessage(plMaxNode* pNode, plMaxNode* efxRegion, plMessage* msg, hsBool ignorePhysicals )
{
for (int i = 0; i < pNode->NumberOfChildren(); i++)
SendEnvironmentMessage((plMaxNode *)pNode->GetChildNode(i), efxRegion, msg, ignorePhysicals );
// don't call ourself...
if (pNode == efxRegion)
return;
// send the scene object this message:
if (efxRegion->Contains( ((INode*)pNode)->GetNodeTM(hsConverterUtils::Instance().GetTime(pNode->GetInterface())).GetRow(3)) &&
pNode->GetSceneObject() && ( !ignorePhysicals || !pNode->IsPhysical() ) )
msg->AddReceiver( pNode->GetSceneObject()->GetKey() );
}
plMaxNode* plConvert::GetRootNode()
{
return (plMaxNode *)fInterface->GetRootNode();
}
BOOL plConvert::IAutoClusterRecur(INode* node)
{
plMaxNode* maxNode = (plMaxNode*)node;
plComponentBase* comp = maxNode->ConvertToComponent();
if( comp && (comp->ClassID() == CLUSTER_COMP_CID) )
{
plClusterComponent* clust = (plClusterComponent*)comp;
// Cluster decides if it needs autogen
if( clust->AutoGen(fpErrorMsg) )
return false;
}
int i;
for( i = 0; i < node->NumberOfChildren(); i++ )
{
if( !IAutoClusterRecur(node->GetChildNode(i)) )
return false;
}
return true;
}
BOOL plConvert::IAutoUnClusterRecur(INode* node)
{
plMaxNode* maxNode = (plMaxNode*)node;
plComponentBase* comp = maxNode->ConvertToComponent();
if( comp && (comp->ClassID() == CLUSTER_COMP_CID) )
{
plClusterComponent* clust = (plClusterComponent*)comp;
// Cluster remembers whether it was autogen'd.
clust->AutoClear(fpErrorMsg);
}
int i;
for( i = 0; i < node->NumberOfChildren(); i++ )
{
IAutoUnClusterRecur(node->GetChildNode(i));
}
return true;
}
bool plConvert::IFindDuplicateNames()
{
INode *node = fInterface->GetRootNode();
const char *name = ISearchNames(node, node);
if (!name)
return false;
fpErrorMsg->Set(true,
"Error in Conversion of Scene Objects",
"Two objects in the scene share the name '%s'.\nUnique names are necessary during the export process.\n",
name
);
fpErrorMsg->Show();
return true;
}
// Recursivly search nodes for duplicate names, and return when one is found
const char *plConvert::ISearchNames(INode *node, INode *root)
{
int count = ICountNameOccurances(root, node->GetName());
if (count > 1)
return node->GetName();
for (int i = 0; i < node->NumberOfChildren(); i++)
{
const char *name = ISearchNames(node->GetChildNode(i), root);
if (name)
return name;
}
return nil;
}
// Recursivly search nodes for this name, and return the number of times found
int plConvert::ICountNameOccurances(INode *node, const char *name)
{
int count = 0;
if (!stricmp(name, node->GetName()))
count++;
for (int i = 0; i < node->NumberOfChildren(); i++)
count += ICountNameOccurances(node->GetChildNode(i), name);
return count;
/*==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 <http://www.gnu.org/licenses/>.
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==*/
//
// 3DSMax HeadSpin exporter
//
#include "hsTypes.h"
#include "Max.h"
#include "istdplug.h"
#include "Notify.h"
#include <commdlg.h>
#include "bmmlib.h"
#include "INode.h"
#include "plConvert.h"
#include "hsResMgr.h"
#include "hsTemplates.h"
#include "hsConverterUtils.h"
#include "hsControlConverter.h"
#include "plMeshConverter.h"
#include "hsMaterialConverter.h"
#include "plLayerConverter.h"
#include "UserPropMgr.h"
#include "hsStringTokenizer.h"
#include "../MaxExport/plErrorMsg.h"
#include "hsVertexShader.h"
#include "plLightMapGen.h"
#include "plBitmapCreator.h"
#include "plgDispatch.h"
#include "../pnMessage/plTimeMsg.h"
#include "../MaxComponent/plComponent.h"
#include "../MaxMain/plMaxNode.h"
#include "../plMessage/plNodeCleanupMsg.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../MaxComponent/plClusterComponent.h"
#include "../plPhysX/plSimulationMgr.h"
#include "../MaxMain/plPhysXCooking.h"
#include "../MaxExport/plExportProgressBar.h"
#include "hsUtils.h"
#include "../MaxMain/plGetLocationDlg.h"
#ifdef HS_DEBUGGING
#define HS_NO_TRY
#endif
plConvert::plConvert() : fWarned(0)
{
}
plConvert& plConvert::Instance()
{
static plConvert theInstance;
return theInstance;
}
hsBool plConvert::IOK()
{
return (!fQuit && !fpErrorMsg->IsBogus() ) ? true: false;
}
hsBool plConvert::Convert()
{
#ifndef HS_NO_TRY
try
#endif
{
fSettings->fReconvert = false;
fWarned = 0;
fInterface->SetIncludeXRefsInHierarchy(TRUE);
plMaxNode *pNode = (plMaxNode *)fInterface->GetRootNode();
AddMessageToQueue(new plTransformMsg(nil, nil, nil, nil));
AddMessageToQueue(new plDelayedTransformMsg(nil, nil, nil, nil));
IFindDuplicateNames();
plExportProgressBar bar;
hsBool retVal = true; // sometime, we might look at this
if( !IAutoClusterRecur(pNode) )
{
fQuit = true;
}
if(IOK())
{
bar.Start("Clear Old Data");
retVal = pNode->DoAllRecur( plMaxNode::ClearData, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Convert Validate");
retVal = pNode->DoRecur( plMaxNode::ConvertValidate, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Components Initialize");
retVal = pNode->DoRecur( plMaxNode::SetupPropertiesPass, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Prepare for skinning");
retVal = pNode->DoRecur( plMaxNode::PrepareSkin, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Make Scene Object");
retVal = pNode->DoRecur( plMaxNode::MakeSceneObject, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Make Physical");
plPhysXCooking::Init();
retVal = pNode->DoRecur( plMaxNode::MakePhysical, fpErrorMsg, fSettings, &bar );
plPhysXCooking::Shutdown();
}
if(IOK())
{
bar.Start("Component Preconvert");
retVal = pNode->DoRecur( plMaxNode::FirstComponentPass, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Make Controller");
retVal = pNode->DoRecur( plMaxNode::MakeController, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{ // must be before mesh
bar.Start("Make Coord Interface");
retVal = pNode->DoRecur( plMaxNode::MakeCoordinateInterface, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{ // must be after coord interface but before pool data is created.
bar.Start("Make Connections");
retVal = pNode->DoRecur( plMaxNode::MakeParentOrRoomConnection, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{ // must be before simulation
bar.Start("Make Mesh");
retVal = pNode->DoRecur( plMaxNode::MakeMesh, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{ // doesn't matter when
bar.Start("Make Light");
retVal = pNode->DoRecur( plMaxNode::MakeLight, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{ // doesn't matter when
bar.Start("Make Occluder");
retVal = pNode->DoRecur( plMaxNode::MakeOccluder, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{ // must be after mesh
bar.Start("Make Modifiers");
retVal = pNode->DoRecur( plMaxNode::MakeModifiers, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
bar.Start("Convert Components");
retVal = pNode->DoRecur( plMaxNode::ConvertComponents, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
// do this after convert
bar.Start("Set Up Interface References");
retVal = pNode->DoRecur( plMaxNode::MakeIfaceReferences, fpErrorMsg, fSettings, &bar );
}
if(IOK() && fSettings->fDoPreshade)
{
// These need to be opened after the components have had a chance to flag the MaxNodes
plLightMapGen::Instance().Open(fInterface, fInterface->GetTime(), fSettings->fDoLightMap);
hsVertexShader::Instance().Open();
bar.Start("Preshade Geometry");
retVal = pNode->DoRecur( plMaxNode::ShadeMesh, fpErrorMsg, fSettings, &bar );
plLightMapGen::Instance().Close();
hsVertexShader::Instance().Close();
}
if(IOK())
{
// Do this next-to-last--allows all the components to free up any temp data they kept around
bar.Start("Component DeInit");
retVal = pNode->DoRecur( plMaxNode::DeInitComponents, fpErrorMsg, fSettings, &bar );
}
if(IOK())
{
// Do this very last--it de-inits and frees all the maxNodeDatas lying around
bar.Start("Clear MaxNodeDatas");
retVal = pNode->DoAllRecur( plMaxNode::ClearMaxNodeData, fpErrorMsg, fSettings, &bar );
}
// fpErrorMsg->Set();
DeInit();
fInterface->SetIncludeXRefsInHierarchy(FALSE);
return IOK();
}
#ifndef HS_NO_TRY
catch(plErrorMsg& err)
{
DeInit();
fInterface->SetIncludeXRefsInHierarchy(FALSE);
err.Show();
return false;
}
catch(...)
{
DeInit();
fInterface->SetIncludeXRefsInHierarchy(FALSE);
fpErrorMsg->Set(true, "plConvert", "Unknown error during convert\n");
fpErrorMsg->Show();
return false;
}
#endif
}
//#include "../MaxMain/plMaxNodeData.h"
//#include <set>
hsBool ConvertList(hsTArray<plMaxNode*>& nodes, PMaxNodeFunc p, plErrorMsg *errMsg, plConvertSettings *settings)
{
for (int i = 0; i < nodes.Count(); i++)
{
(nodes[i]->*p)(errMsg, settings);
if (errMsg && errMsg->IsBogus())
return false;
}
return true;
}
hsBool plConvert::Convert(hsTArray<plMaxNode*>& nodes)
{
#ifndef HS_NO_TRY
try
#endif
{
fSettings->fReconvert = true;
hsBool retVal = true;
if (IOK())
retVal = ConvertList(nodes, plMaxNode::ClearData, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::ConvertValidate, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::SetupPropertiesPass, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::PrepareSkin, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::MakeSceneObject, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::FirstComponentPass, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::MakeController, fpErrorMsg,fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::MakeCoordinateInterface, fpErrorMsg, fSettings);// must be before mesh
if(IOK())
retVal = ConvertList(nodes, plMaxNode::MakeParentOrRoomConnection, fpErrorMsg, fSettings); // after coord, before mesh (or any other pool data).
// These shouldn't be opened until the components have had a chance to flag the MaxNodes
plLightMapGen::Instance().Open(fInterface, fInterface->GetTime(), fSettings->fDoLightMap);
hsVertexShader::Instance().Open();
if(IOK())
retVal = ConvertList(nodes, plMaxNode::MakeMesh, fpErrorMsg, fSettings); // must be before simulation
if(IOK()) // doesn't matter when
retVal = ConvertList(nodes, plMaxNode::MakeLight, fpErrorMsg, fSettings);
if(IOK()) // doesn't matter when
retVal = ConvertList(nodes, plMaxNode::MakeOccluder, fpErrorMsg, fSettings);
if(IOK()) // must be after mesh
retVal = ConvertList(nodes, plMaxNode::MakeModifiers, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::ConvertComponents, fpErrorMsg, fSettings);
if(IOK())
retVal = ConvertList(nodes, plMaxNode::ShadeMesh, fpErrorMsg, fSettings);
// These may be used by components, so don't close them till the end.
plLightMapGen::Instance().Close();
hsVertexShader::Instance().Close();
plgDispatch::MsgSend(new plTransformMsg(nil, nil, nil, nil));
plgDispatch::MsgSend(new plDelayedTransformMsg(nil, nil, nil, nil));
DeInit();
return IOK();
}
#ifndef HS_NO_TRY
catch(plErrorMsg& err)
{
err.Show();
return false;
}
catch(...)
{
hsMessageBox("Unknown error during convert", "plConvert", hsMessageBoxNormal);
return false;
}
#endif
}
hsBool plConvert::Init(Interface *ip, plErrorMsg* msg, plConvertSettings *settings)
{
fInterface = ip;
fpErrorMsg = msg;
fSettings = settings;
// Move us to time 0, so that things like initial transforms are always consistent with the 0th frame.
// This saves our asses from things like the patch-generation process later
ip->SetTime( 0, false );
hsConverterUtils::Instance().Init(true, fpErrorMsg);
plBitmapCreator::Instance().Init(true, fpErrorMsg);
hsMaterialConverter::Instance().Init(true, fpErrorMsg);
hsControlConverter::Instance().Init(fpErrorMsg);
plMeshConverter::Instance().Init(true, fpErrorMsg);
plLayerConverter::Instance().Init(true, fpErrorMsg);
plGetLocationDlg::Instance().ResetDefaultLocation();
fQuit = false;
return true;
}
void plConvert::DeInit()
{
// Undo any autogenerated clusters.
IAutoUnClusterRecur(fInterface->GetRootNode());
// clear out the message queue
for (int i = 0; i < fMsgQueue.Count(); i++)
plgDispatch::MsgSend(fMsgQueue[i]);
fMsgQueue.Reset();
hsControlConverter::Instance().DeInit();
plMeshConverter::Instance().DeInit();
plLayerConverter::Instance().DeInit();
// Moving this to the end of writing the files out. Yes, this means that any unused mipmaps still get
// written to disk, including ones loaded on preload, but it's the only way to get shared texture pages
// to work without loading in the entire age worth of reffing objects. - 5.30.2002 mcn
// plBitmapCreator::Instance().DeInit();
plNodeCleanupMsg *clean = TRACKED_NEW plNodeCleanupMsg();
plgDispatch::MsgSend( clean );
}
void plConvert::AddMessageToQueue(plMessage* msg)
{
fMsgQueue.Append(msg);
}
void plConvert::SendEnvironmentMessage(plMaxNode* pNode, plMaxNode* efxRegion, plMessage* msg, hsBool ignorePhysicals )
{
for (int i = 0; i < pNode->NumberOfChildren(); i++)
SendEnvironmentMessage((plMaxNode *)pNode->GetChildNode(i), efxRegion, msg, ignorePhysicals );
// don't call ourself...
if (pNode == efxRegion)
return;
// send the scene object this message:
if (efxRegion->Contains( ((INode*)pNode)->GetNodeTM(hsConverterUtils::Instance().GetTime(pNode->GetInterface())).GetRow(3)) &&
pNode->GetSceneObject() && ( !ignorePhysicals || !pNode->IsPhysical() ) )
msg->AddReceiver( pNode->GetSceneObject()->GetKey() );
}
plMaxNode* plConvert::GetRootNode()
{
return (plMaxNode *)fInterface->GetRootNode();
}
BOOL plConvert::IAutoClusterRecur(INode* node)
{
plMaxNode* maxNode = (plMaxNode*)node;
plComponentBase* comp = maxNode->ConvertToComponent();
if( comp && (comp->ClassID() == CLUSTER_COMP_CID) )
{
plClusterComponent* clust = (plClusterComponent*)comp;
// Cluster decides if it needs autogen
if( clust->AutoGen(fpErrorMsg) )
return false;
}
int i;
for( i = 0; i < node->NumberOfChildren(); i++ )
{
if( !IAutoClusterRecur(node->GetChildNode(i)) )
return false;
}
return true;
}
BOOL plConvert::IAutoUnClusterRecur(INode* node)
{
plMaxNode* maxNode = (plMaxNode*)node;
plComponentBase* comp = maxNode->ConvertToComponent();
if( comp && (comp->ClassID() == CLUSTER_COMP_CID) )
{
plClusterComponent* clust = (plClusterComponent*)comp;
// Cluster remembers whether it was autogen'd.
clust->AutoClear(fpErrorMsg);
}
int i;
for( i = 0; i < node->NumberOfChildren(); i++ )
{
IAutoUnClusterRecur(node->GetChildNode(i));
}
return true;
}
bool plConvert::IFindDuplicateNames()
{
INode *node = fInterface->GetRootNode();
const char *name = ISearchNames(node, node);
if (!name)
return false;
fpErrorMsg->Set(true,
"Error in Conversion of Scene Objects",
"Two objects in the scene share the name '%s'.\nUnique names are necessary during the export process.\n",
name
);
fpErrorMsg->Show();
return true;
}
// Recursivly search nodes for duplicate names, and return when one is found
const char *plConvert::ISearchNames(INode *node, INode *root)
{
int count = ICountNameOccurances(root, node->GetName());
if (count > 1)
return node->GetName();
for (int i = 0; i < node->NumberOfChildren(); i++)
{
const char *name = ISearchNames(node->GetChildNode(i), root);
if (name)
return name;
}
return nil;
}
// Recursivly search nodes for this name, and return the number of times found
int plConvert::ICountNameOccurances(INode *node, const char *name)
{
int count = 0;
if (!stricmp(name, node->GetName()))
count++;
for (int i = 0; i < node->NumberOfChildren(); i++)
count += ICountNameOccurances(node->GetChildNode(i), name);
return count;
}

View File

@ -1,115 +1,115 @@
/*==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 <http://www.gnu.org/licenses/>.
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 plConvert_inc
#define plConvert_inc
#include "hsTypes.h"
#include "hsTemplates.h"
#include "../pnKeyedObject/plKey.h"
class plErrorMsg;
class plLocation;
class plMaxNode;
class plMessage;
class plLightMapGen;
class hsVertexShader;
class plConvertSettings
{
public:
plConvertSettings() : fSceneViewer(false), fReconvert(false), fDoPreshade(true), fDoLightMap(true),
fLightMapGen(nil), fVertexShader(nil), fPhysicalsOnly(false), fExportPage(nil) {}
bool fSceneViewer; // Are we converting this for the SceneViewer?
bool fReconvert; // Don't need to set, will be done internally by plConvert
bool fDoPreshade; // Doesn't do preshading if false (flat shades)
bool fDoLightMap; // Reuses available old lightmaps if false, else always generates fresh.
bool fPhysicalsOnly;// Only solid physicals get meshes
const char* fExportPage; // If this isn't nil, only export objects in this page
plLightMapGen* fLightMapGen;
hsVertexShader* fVertexShader;
};
class plConvert
{
protected:
hsBool fQuit;
plErrorMsg* fpErrorMsg;
Interface* fInterface;
plConvertSettings* fSettings;
hsTArray<plMessage*> fMsgQueue;
plConvert();
hsBool IMakeSceneObject(INode* node);
plKey IGetRoomKey(INode* node);
plKey INewRoom(INode* node, char roomName[]);
hsBool IOK();
public:
static plConvert& Instance();
UInt32 fWarned;
enum {
kWarnedDecalOnBlendObj = 0x1,
kWarnedBadMaterialOnParticle = 0x2,
kWarnedBadParticle = 0x4,
kWarnedDecalAndNonDecal = 0x8,
kWarnedWrongProj = 0x10,
kWarnedMissingProj = 0x20,
kWarnedDecalOnNonDrawable = 0x40,
kWarnedTooManyParticles = 0x80,
kWarnedParticleVelAndOnePer = 0x100,
kWarnedPhysics = 0x200,
};
// Init the converter. Only good for one call of Convert.
hsBool Init(Interface *ip, plErrorMsg* msg, plConvertSettings *settings);
void DeInit();
hsBool Convert();
hsBool Convert(hsTArray<plMaxNode*>& nodes); // Convert a set of nodes (for SceneViewer update)
plMaxNode* GetRootNode();
void SendEnvironmentMessage(plMaxNode* pNode, plMaxNode* efxRegion, plMessage* msg, hsBool ignorePhysicals = false); // iterates through scene to find nodes contained by the efxRegion
void AddMessageToQueue(plMessage* msg);
// Because components don't get the convert settings (too much work to retrofit all of them)
plConvertSettings* GetConvertSettings() { return fSettings; }
bool IsForSceneViewer() { return fSettings->fSceneViewer; }
// Search for nodes with the same name. Returns true if any are found and stops the export
bool IFindDuplicateNames();
// IFindDuplicateNames helper functions
const char *ISearchNames(INode *node, INode *root);
int ICountNameOccurances(INode *node, const char *name);
// Does any pre-export generation necessary for distributors, then cleans up after export.
BOOL IAutoClusterRecur(INode* node);
BOOL IAutoUnClusterRecur(INode* node);
};
/*==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 <http://www.gnu.org/licenses/>.
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 plConvert_inc
#define plConvert_inc
#include "hsTypes.h"
#include "hsTemplates.h"
#include "../pnKeyedObject/plKey.h"
class plErrorMsg;
class plLocation;
class plMaxNode;
class plMessage;
class plLightMapGen;
class hsVertexShader;
class plConvertSettings
{
public:
plConvertSettings() : fSceneViewer(false), fReconvert(false), fDoPreshade(true), fDoLightMap(true),
fLightMapGen(nil), fVertexShader(nil), fPhysicalsOnly(false), fExportPage(nil) {}
bool fSceneViewer; // Are we converting this for the SceneViewer?
bool fReconvert; // Don't need to set, will be done internally by plConvert
bool fDoPreshade; // Doesn't do preshading if false (flat shades)
bool fDoLightMap; // Reuses available old lightmaps if false, else always generates fresh.
bool fPhysicalsOnly;// Only solid physicals get meshes
const char* fExportPage; // If this isn't nil, only export objects in this page
plLightMapGen* fLightMapGen;
hsVertexShader* fVertexShader;
};
class plConvert
{
protected:
hsBool fQuit;
plErrorMsg* fpErrorMsg;
Interface* fInterface;
plConvertSettings* fSettings;
hsTArray<plMessage*> fMsgQueue;
plConvert();
hsBool IMakeSceneObject(INode* node);
plKey IGetRoomKey(INode* node);
plKey INewRoom(INode* node, char roomName[]);
hsBool IOK();
public:
static plConvert& Instance();
UInt32 fWarned;
enum {
kWarnedDecalOnBlendObj = 0x1,
kWarnedBadMaterialOnParticle = 0x2,
kWarnedBadParticle = 0x4,
kWarnedDecalAndNonDecal = 0x8,
kWarnedWrongProj = 0x10,
kWarnedMissingProj = 0x20,
kWarnedDecalOnNonDrawable = 0x40,
kWarnedTooManyParticles = 0x80,
kWarnedParticleVelAndOnePer = 0x100,
kWarnedPhysics = 0x200,
};
// Init the converter. Only good for one call of Convert.
hsBool Init(Interface *ip, plErrorMsg* msg, plConvertSettings *settings);
void DeInit();
hsBool Convert();
hsBool Convert(hsTArray<plMaxNode*>& nodes); // Convert a set of nodes (for SceneViewer update)
plMaxNode* GetRootNode();
void SendEnvironmentMessage(plMaxNode* pNode, plMaxNode* efxRegion, plMessage* msg, hsBool ignorePhysicals = false); // iterates through scene to find nodes contained by the efxRegion
void AddMessageToQueue(plMessage* msg);
// Because components don't get the convert settings (too much work to retrofit all of them)
plConvertSettings* GetConvertSettings() { return fSettings; }
bool IsForSceneViewer() { return fSettings->fSceneViewer; }
// Search for nodes with the same name. Returns true if any are found and stops the export
bool IFindDuplicateNames();
// IFindDuplicateNames helper functions
const char *ISearchNames(INode *node, INode *root);
int ICountNameOccurances(INode *node, const char *name);
// Does any pre-export generation necessary for distributors, then cleans up after export.
BOOL IAutoClusterRecur(INode* node);
BOOL IAutoUnClusterRecur(INode* node);
};
#endif // plSimpleConvert_inc

View File

@ -1,301 +1,301 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#include "hsTypes.h"
#include "Max.h"
#include "plDistTree.h"
plDistTree::plDistTree()
: fRoot(-1)
{
}
plDistTree::~plDistTree()
{
}
void plDistTree::Reset()
{
fRoot = -1;
fNodes.Reset();
}
void plDistTree::AddBoxIData(const Box3& box, const Box3& fade, UInt32 iData)
{
fRoot = IAddNodeRecur(fRoot, box, fade, iData);
}
BOOL plDistTree::BoxClear(const Box3& box, const Box3& fade) const
{
return IBoxClearRecur(fRoot, box, fade);
}
BOOL plDistTree::PointClear(const Point3& pt, const Box3& fade) const
{
return IPointClearRecur(fRoot, pt, fade);
}
BOOL plDistTree::IFadesClear(const Box3& fade0, const Box3& fade1) const
{
// Only two ways fade can come out non-overlapping.
// Either fade0 fades out before fade1 fades in, or v.v.
// First case, does fade0 fade out?
if( fade0.Max()[2] > 0 )
{
// does fade1 fade in?
if( fade1.Min()[2] < 0 )
{
// Okay they do, does fade0 fade out before fade1 fades in?
if( fade0.Max()[0] <= fade1.Min()[0] )
return true;
}
}
// Second case, same thing but reversed order
if( fade1.Max()[2] > 0 )
{
// does fade0 fade in?
if( fade0.Min()[2] < 0 )
{
// Okay they do, does fade1 fade out before fade0 fades in?
if( fade1.Max()[0] <= fade0.Min()[0] )
return true;
}
}
return false;
}
BOOL plDistTree::IBox0ContainsBox1(const Box3& box0, const Box3& box1, const Box3& fade0, const Box3& fade1) const
{
#ifdef MAX_CONTAINS_WORKS
if( !box0.Contains(box1) )
return false;
#else MAX_CONTAINS_WORKS
if( (box0.Min()[0] > box1.Min()[0])
||(box0.Min()[1] > box1.Min()[1])
||(box0.Min()[2] > box1.Min()[2])
||(box0.Max()[0] < box1.Max()[0])
||(box0.Max()[1] < box1.Max()[1])
||(box0.Max()[2] < box1.Max()[2]) )
return false;
#endif // MAX_CONTAINS_WORKS
if( IFadesClear(fade0, fade1) )
return false;
return true;
}
BOOL plDistTree::IBoxesClear(const Box3& box0, const Box3& box1) const
{
return (box0.Min()[0] > box1.Max()[0])
||(box0.Max()[0] < box1.Min()[0])
||(box0.Min()[1] > box1.Max()[1])
||(box0.Max()[1] < box1.Min()[1])
||(box0.Min()[2] > box1.Max()[2])
||(box0.Max()[2] < box1.Min()[2]);
}
BOOL plDistTree::IBoxClearRecur(Int32 iNode, const Box3& box, const Box3& fade) const
{
if( iNode < 0 )
return true;
if( IBoxesClear(fNodes[iNode].fBox, box) )
return true;
if( IFadesClear(fNodes[iNode].fFade, fade) )
return true;
if( fNodes[iNode].IsLeaf() )
return false;
int i;
for( i = 0; i < 8; i++ )
{
if( !IBoxClearRecur(fNodes[iNode].fChildren[i], box, fade) )
return false;
}
return true;
}
BOOL plDistTree::IPointClearRecur(Int32 iNode, const Point3& pt, const Box3& fade) const
{
if( iNode < 0 )
return true;
if( !fNodes[iNode].fBox.Contains(pt) )
return true;
if( IFadesClear(fNodes[iNode].fFade, fade) )
return true;
if( fNodes[iNode].IsLeaf() )
return false;
int i;
for( i = 0; i < 8; i++ )
{
if( !IPointClearRecur(fNodes[iNode].fChildren[i], pt, fade) )
return false;
}
return true;
}
Int32 plDistTree::IAddNodeRecur(Int32 iNode, const Box3& box, const Box3& fade, UInt32 iData)
{
// if iNode < 0, make a node for box and return that.
if( iNode < 0 )
{
return INextNode(box, fade, iData);
}
// if the box is contained
// if this node is a leaf, pitch the box
//
// else
// recur on one of 8 children, based on
// box's center relative to node center.
// if the box doesn't intercect this node,
// replace this node with a node of combined boxes.
// this node becomes sibling of box.
// if the box does intercect, but isn't contained
// same thing.
#if 0
if( IBox0ContainsBox1(fNodes[iNode].fBox, box, fNodes[iNode].fFade, fade) )
{
if( !fNodes[iNode].IsLeaf() )
#else
if( !fNodes[iNode].IsLeaf() && IBox0ContainsBox1(fNodes[iNode].fBox, box, fNodes[iNode].fFade, fade) )
{
#endif
{
Int32 iChild = IGetChild(fNodes[iNode].fBox, box);
Int32 iChildNode = IAddNodeRecur(fNodes[iNode].fChildren[iChild], box, fade, iData);
fNodes[iNode].fChildren[iChild] = iChildNode;
fNodes[iNode].fBox += fNodes[fNodes[iNode].fChildren[iChild]].fBox;
}
return iNode;
}
else
{
return IMergeNodes(iNode, box, fade, iData);
}
}
Int32 plDistTree::IMergeNodes(Int32 iNode, const Box3& box, const Box3& fade, UInt32 iData)
{
Box3 parBox = box;
parBox += fNodes[iNode].fBox;
Int32 pNode = INextNode(parBox, NonFade(), UInt32(-1));
Int32 iChild = IGetChild(parBox, box);
Int32 cNode = INextNode(box, fade, iData);
fNodes[pNode].fChildren[iChild] = cNode;
// Put the original node in the opposite quadrant from the child.
// This handles the case where one of the bounds completely contains
// the other. The octant structure of the tree isn't relied on, it
// only helps balance the tree. So being wrong here won't hurt anything.
iChild = iChild ^ 0x7;
fNodes[pNode].fChildren[iChild] = iNode;
fNodes[pNode].SetIsLeaf(false);
return pNode;
}
Int32 plDistTree::IGetChild(const Box3& parent, const Box3& child) const
{
Point3 parCenter = parent.Center();
Point3 chiCenter = child.Center();
Int32 idx = ((parCenter[0] < chiCenter[0]) << 0)
| ((parCenter[1] < chiCenter[1]) << 1)
| ((parCenter[2] < chiCenter[2]) << 2);
return idx;
}
Int32 plDistTree::INextNode(const Box3& box, const Box3& fade, UInt32 iData)
{
Int32 iNode = fNodes.GetCount();
fNodes.Push();
fNodes[iNode].fFlags = plDistNode::kIsLeaf;
fNodes[iNode].fBox = box;
fNodes[iNode].fFade = fade;
fNodes[iNode].fIData = iData;
fNodes[iNode].fChildren[0]
= fNodes[iNode].fChildren[1]
= fNodes[iNode].fChildren[2]
= fNodes[iNode].fChildren[3]
= fNodes[iNode].fChildren[4]
= fNodes[iNode].fChildren[5]
= fNodes[iNode].fChildren[6]
= fNodes[iNode].fChildren[7] = -1;
return iNode;
}
void plDistTree::HarvestBox(const Box3& box, Tab<Int32>& out) const
{
IHarvestBoxRecur(fRoot, box, out);
}
void plDistTree::IHarvestBoxRecur(Int32 iNode, const Box3& box, Tab<Int32>& out) const
{
if( iNode < 0 )
return;
if( IBoxesClear(fNodes[iNode].fBox, box) )
return;
if( fNodes[iNode].IsLeaf() )
{
out.Append(1, &iNode);
}
else
{
int i;
for( i = 0; i < 8; i++ )
IHarvestBoxRecur(fNodes[iNode].fChildren[i], box, out);
}
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#include "hsTypes.h"
#include "Max.h"
#include "plDistTree.h"
plDistTree::plDistTree()
: fRoot(-1)
{
}
plDistTree::~plDistTree()
{
}
void plDistTree::Reset()
{
fRoot = -1;
fNodes.Reset();
}
void plDistTree::AddBoxIData(const Box3& box, const Box3& fade, UInt32 iData)
{
fRoot = IAddNodeRecur(fRoot, box, fade, iData);
}
BOOL plDistTree::BoxClear(const Box3& box, const Box3& fade) const
{
return IBoxClearRecur(fRoot, box, fade);
}
BOOL plDistTree::PointClear(const Point3& pt, const Box3& fade) const
{
return IPointClearRecur(fRoot, pt, fade);
}
BOOL plDistTree::IFadesClear(const Box3& fade0, const Box3& fade1) const
{
// Only two ways fade can come out non-overlapping.
// Either fade0 fades out before fade1 fades in, or v.v.
// First case, does fade0 fade out?
if( fade0.Max()[2] > 0 )
{
// does fade1 fade in?
if( fade1.Min()[2] < 0 )
{
// Okay they do, does fade0 fade out before fade1 fades in?
if( fade0.Max()[0] <= fade1.Min()[0] )
return true;
}
}
// Second case, same thing but reversed order
if( fade1.Max()[2] > 0 )
{
// does fade0 fade in?
if( fade0.Min()[2] < 0 )
{
// Okay they do, does fade1 fade out before fade0 fades in?
if( fade1.Max()[0] <= fade0.Min()[0] )
return true;
}
}
return false;
}
BOOL plDistTree::IBox0ContainsBox1(const Box3& box0, const Box3& box1, const Box3& fade0, const Box3& fade1) const
{
#ifdef MAX_CONTAINS_WORKS
if( !box0.Contains(box1) )
return false;
#else MAX_CONTAINS_WORKS
if( (box0.Min()[0] > box1.Min()[0])
||(box0.Min()[1] > box1.Min()[1])
||(box0.Min()[2] > box1.Min()[2])
||(box0.Max()[0] < box1.Max()[0])
||(box0.Max()[1] < box1.Max()[1])
||(box0.Max()[2] < box1.Max()[2]) )
return false;
#endif // MAX_CONTAINS_WORKS
if( IFadesClear(fade0, fade1) )
return false;
return true;
}
BOOL plDistTree::IBoxesClear(const Box3& box0, const Box3& box1) const
{
return (box0.Min()[0] > box1.Max()[0])
||(box0.Max()[0] < box1.Min()[0])
||(box0.Min()[1] > box1.Max()[1])
||(box0.Max()[1] < box1.Min()[1])
||(box0.Min()[2] > box1.Max()[2])
||(box0.Max()[2] < box1.Min()[2]);
}
BOOL plDistTree::IBoxClearRecur(Int32 iNode, const Box3& box, const Box3& fade) const
{
if( iNode < 0 )
return true;
if( IBoxesClear(fNodes[iNode].fBox, box) )
return true;
if( IFadesClear(fNodes[iNode].fFade, fade) )
return true;
if( fNodes[iNode].IsLeaf() )
return false;
int i;
for( i = 0; i < 8; i++ )
{
if( !IBoxClearRecur(fNodes[iNode].fChildren[i], box, fade) )
return false;
}
return true;
}
BOOL plDistTree::IPointClearRecur(Int32 iNode, const Point3& pt, const Box3& fade) const
{
if( iNode < 0 )
return true;
if( !fNodes[iNode].fBox.Contains(pt) )
return true;
if( IFadesClear(fNodes[iNode].fFade, fade) )
return true;
if( fNodes[iNode].IsLeaf() )
return false;
int i;
for( i = 0; i < 8; i++ )
{
if( !IPointClearRecur(fNodes[iNode].fChildren[i], pt, fade) )
return false;
}
return true;
}
Int32 plDistTree::IAddNodeRecur(Int32 iNode, const Box3& box, const Box3& fade, UInt32 iData)
{
// if iNode < 0, make a node for box and return that.
if( iNode < 0 )
{
return INextNode(box, fade, iData);
}
// if the box is contained
// if this node is a leaf, pitch the box
//
// else
// recur on one of 8 children, based on
// box's center relative to node center.
// if the box doesn't intercect this node,
// replace this node with a node of combined boxes.
// this node becomes sibling of box.
// if the box does intercect, but isn't contained
// same thing.
#if 0
if( IBox0ContainsBox1(fNodes[iNode].fBox, box, fNodes[iNode].fFade, fade) )
{
if( !fNodes[iNode].IsLeaf() )
#else
if( !fNodes[iNode].IsLeaf() && IBox0ContainsBox1(fNodes[iNode].fBox, box, fNodes[iNode].fFade, fade) )
{
#endif
{
Int32 iChild = IGetChild(fNodes[iNode].fBox, box);
Int32 iChildNode = IAddNodeRecur(fNodes[iNode].fChildren[iChild], box, fade, iData);
fNodes[iNode].fChildren[iChild] = iChildNode;
fNodes[iNode].fBox += fNodes[fNodes[iNode].fChildren[iChild]].fBox;
}
return iNode;
}
else
{
return IMergeNodes(iNode, box, fade, iData);
}
}
Int32 plDistTree::IMergeNodes(Int32 iNode, const Box3& box, const Box3& fade, UInt32 iData)
{
Box3 parBox = box;
parBox += fNodes[iNode].fBox;
Int32 pNode = INextNode(parBox, NonFade(), UInt32(-1));
Int32 iChild = IGetChild(parBox, box);
Int32 cNode = INextNode(box, fade, iData);
fNodes[pNode].fChildren[iChild] = cNode;
// Put the original node in the opposite quadrant from the child.
// This handles the case where one of the bounds completely contains
// the other. The octant structure of the tree isn't relied on, it
// only helps balance the tree. So being wrong here won't hurt anything.
iChild = iChild ^ 0x7;
fNodes[pNode].fChildren[iChild] = iNode;
fNodes[pNode].SetIsLeaf(false);
return pNode;
}
Int32 plDistTree::IGetChild(const Box3& parent, const Box3& child) const
{
Point3 parCenter = parent.Center();
Point3 chiCenter = child.Center();
Int32 idx = ((parCenter[0] < chiCenter[0]) << 0)
| ((parCenter[1] < chiCenter[1]) << 1)
| ((parCenter[2] < chiCenter[2]) << 2);
return idx;
}
Int32 plDistTree::INextNode(const Box3& box, const Box3& fade, UInt32 iData)
{
Int32 iNode = fNodes.GetCount();
fNodes.Push();
fNodes[iNode].fFlags = plDistNode::kIsLeaf;
fNodes[iNode].fBox = box;
fNodes[iNode].fFade = fade;
fNodes[iNode].fIData = iData;
fNodes[iNode].fChildren[0]
= fNodes[iNode].fChildren[1]
= fNodes[iNode].fChildren[2]
= fNodes[iNode].fChildren[3]
= fNodes[iNode].fChildren[4]
= fNodes[iNode].fChildren[5]
= fNodes[iNode].fChildren[6]
= fNodes[iNode].fChildren[7] = -1;
return iNode;
}
void plDistTree::HarvestBox(const Box3& box, Tab<Int32>& out) const
{
IHarvestBoxRecur(fRoot, box, out);
}
void plDistTree::IHarvestBoxRecur(Int32 iNode, const Box3& box, Tab<Int32>& out) const
{
if( iNode < 0 )
return;
if( IBoxesClear(fNodes[iNode].fBox, box) )
return;
if( fNodes[iNode].IsLeaf() )
{
out.Append(1, &iNode);
}
else
{
int i;
for( i = 0; i < 8; i++ )
IHarvestBoxRecur(fNodes[iNode].fChildren[i], box, out);
}
}

View File

@ -1,103 +1,103 @@
/*==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 <http://www.gnu.org/licenses/>.
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 plDistTree_inc
#define plDistTree_inc
#include "hsTemplates.h"
class plDistNode
{
public:
enum {
kIsLeaf = 0x1
};
UInt32 fFlags;
Int32 fChildren[8];
Box3 fBox;
Box3 fFade;
union
{
void* fPData;
UInt32 fIData;
};
const Box3& GetBox() const { return fBox; }
BOOL IsLeaf() const { return 0 != (fFlags & kIsLeaf); }
void SetIsLeaf(BOOL on) { if(on)fFlags |= kIsLeaf; else fFlags &= ~kIsLeaf; }
};
class plDistTree
{
protected:
Int32 fRoot;
hsLargeArray<plDistNode> fNodes;
Int32 IAddNodeRecur(Int32 iNode, const Box3& box, const Box3& fade, UInt32 iData);
Int32 IMergeNodes(Int32 iNode, const Box3& box, const Box3& fade, UInt32 iData);
Int32 INextNode(const Box3& box, const Box3& fade, UInt32 iData);
Int32 IGetChild(const Box3& parent, const Box3& child) const;
inline BOOL IBoxesClear(const Box3& box0, const Box3& box1) const;
inline BOOL IFadesClear(const Box3& fade0, const Box3& fade1) const;
BOOL IBox0ContainsBox1(const Box3& box0, const Box3& box1, const Box3& fade0, const Box3& fade1) const;
BOOL IBoxClearRecur(Int32 iNode, const Box3& box, const Box3& fade) const;
BOOL IPointClearRecur(Int32 iNode, const Point3& pt, const Box3& fade) const;
void IHarvestBoxRecur(Int32 iNode, const Box3& box, Tab<Int32>& out) const;
public:
plDistTree();
virtual ~plDistTree();
void Reset();
void AddBoxPData(const Box3& box, const Box3& fade, void* pData=nil) { AddBoxIData(box, fade, UInt32(pData)); }
void AddBoxIData(const Box3& box, const Box3& fade, UInt32 iData=0);
void AddBox(const Box3& box, const Box3& fade=NonFade()) { AddBoxIData(box, fade, 0); }
BOOL BoxClear(const Box3& box, const Box3& fade) const;
BOOL PointClear(const Point3& pt, const Box3& fade) const;
BOOL IsEmpty() const { return fRoot < 0; }
static Box3 NonFade() { return Box3(Point3(0,0,0), Point3(0,0,0)); }
void HarvestBox(const Box3& box, Tab<Int32>& out) const;
const plDistNode& GetBox(Int32 i) const { return fNodes[i]; }
};
#endif // plDistTree_inc
/*==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 <http://www.gnu.org/licenses/>.
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 plDistTree_inc
#define plDistTree_inc
#include "hsTemplates.h"
class plDistNode
{
public:
enum {
kIsLeaf = 0x1
};
UInt32 fFlags;
Int32 fChildren[8];
Box3 fBox;
Box3 fFade;
union
{
void* fPData;
UInt32 fIData;
};
const Box3& GetBox() const { return fBox; }
BOOL IsLeaf() const { return 0 != (fFlags & kIsLeaf); }
void SetIsLeaf(BOOL on) { if(on)fFlags |= kIsLeaf; else fFlags &= ~kIsLeaf; }
};
class plDistTree
{
protected:
Int32 fRoot;
hsLargeArray<plDistNode> fNodes;
Int32 IAddNodeRecur(Int32 iNode, const Box3& box, const Box3& fade, UInt32 iData);
Int32 IMergeNodes(Int32 iNode, const Box3& box, const Box3& fade, UInt32 iData);
Int32 INextNode(const Box3& box, const Box3& fade, UInt32 iData);
Int32 IGetChild(const Box3& parent, const Box3& child) const;
inline BOOL IBoxesClear(const Box3& box0, const Box3& box1) const;
inline BOOL IFadesClear(const Box3& fade0, const Box3& fade1) const;
BOOL IBox0ContainsBox1(const Box3& box0, const Box3& box1, const Box3& fade0, const Box3& fade1) const;
BOOL IBoxClearRecur(Int32 iNode, const Box3& box, const Box3& fade) const;
BOOL IPointClearRecur(Int32 iNode, const Point3& pt, const Box3& fade) const;
void IHarvestBoxRecur(Int32 iNode, const Box3& box, Tab<Int32>& out) const;
public:
plDistTree();
virtual ~plDistTree();
void Reset();
void AddBoxPData(const Box3& box, const Box3& fade, void* pData=nil) { AddBoxIData(box, fade, UInt32(pData)); }
void AddBoxIData(const Box3& box, const Box3& fade, UInt32 iData=0);
void AddBox(const Box3& box, const Box3& fade=NonFade()) { AddBoxIData(box, fade, 0); }
BOOL BoxClear(const Box3& box, const Box3& fade) const;
BOOL PointClear(const Point3& pt, const Box3& fade) const;
BOOL IsEmpty() const { return fRoot < 0; }
static Box3 NonFade() { return Box3(Point3(0,0,0), Point3(0,0,0)); }
void HarvestBox(const Box3& box, Tab<Int32>& out) const;
const plDistNode& GetBox(Int32 i) const { return fNodes[i]; }
};
#endif // plDistTree_inc

File diff suppressed because it is too large Load Diff

View File

@ -1,405 +1,405 @@
/*==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 <http://www.gnu.org/licenses/>.
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 plDistributor_inc
#define plDistributor_inc
#include "../plMath/plRandom.h"
#include "plDistTree.h"
class INode;
class Mesh;
class TriObject;
class BitmapTex;
class plLayerTex;
class plExportProgressBar;
class plMaxNode;
class plDistTree;
// To Use:
//
// First you must set the interface
// Second, you must set the node(s) to be replicated.
// If multiple replicants, they will be randomly selected at each plant site.
// Set the spacing. Default is 10 or so, but shouldn't be counted on.
// Set the spacing range. Set it to less than half the spacing to prevent
// replicants piling up on each other.
// Rather than increasing the spacing range (which causes pileup), you can increase
// the randomness of placement with the overall probability factor. Reducing it
// means fewer grid points will be used, so placement seems more random
//
// Options:
// PolarRange - defines the cone about the surface normal to randomly fill for up direction
// PolarBunch - defines tendency to bunch around the center of PolarRange cone,
// with zero being uniform distribution, and one being all on cone axis.
// AlignmentVector - defines a world space preferred up orientation.
// AlignmentWeight - blend factor between random normal (from polar stuff) and
// above AlignmentVector.
// ScaleRange - defines range of non-uniform scale to apply to each replicant.
// ProbabilityTexmap - A BitmapTex which maps the probability of an instance
// taking root at any point on the surface. Various interpretations of the
// map available (see ProbabilityChan). If the surface mesh doesn't have
// the appropriate uvw mapping for the map, the map will be ignored.
// ProbabilityChan - defines interpretation of texel value from ProbTexmap
// into a probability. ColorChan enum types are pretty self-explanatory.
// In all cases, a higher texel channel value means more likely of a
// replicant taking root there.
//
// Finally, call Distrubute() with a node containing a surface to be populated.
//
// Modifying. Were actually creating the new node instances, but then we just
// want to re-pack them into clusters anyway. So all we really need is to
// know which template (fRepNodes) and what transform to use for it. We can
// use that to make our clusters, without bogging Max down with adding and
// deleting a gazillion INodes.
class plDistribInstance
{
public:
INode* fNode;
Matrix3 fNodeTM;
Matrix3 fObjectTM;
INode* fBone;
BOOL fRigid;
Box3 fFade;
Point3 fFlex;
Mesh* fMesh;
};
class plDistribInstTab : public Tab<plDistribInstance>
{
};
class plMeshCache
{
public:
Mesh* fMesh;
Point3 fFlex;
plMeshCache() {}
};
class plMeshCacheTab : public Tab<plMeshCache>
{
};
class plDistributor
{
public:
enum ColorChan
{
kRed = 0x1,
kGreen = 0x2,
kBlue = 0x4,
kAlpha = 0x8,
kAverageRedGreen = kRed | kGreen,
kAverageRedGreenTimesAlpha = kRed | kGreen | kAlpha,
kAverage = kRed | kGreen | kBlue,
kAverageTimesAlpha = kAverage | kAlpha,
kMax = 0x100,
kMaxColor = kMax | kRed | kGreen | kBlue,
kMaxColorTimesAlpha = kMaxColor | kAlpha,
kMaxRedGreen = kMax | kRed | kGreen,
kMaxRedGreenTimesAlpha = kMaxRedGreen | kAlpha
};
enum
{
kLockNone = 0x0,
kLockX = 0x1,
kLockY = 0x2,
kLockZ = 0x4
};
enum
{
kWgtMapChan = 66,
kNormMapChan = 67
};
enum IsoType
{
kIsoNone,
kIsoLow,
kIsoMedium,
kIsoHigh,
kIsoMax = kIsoHigh
};
enum ConformType
{
kConformNone,
kConformAll,
kConformHeight,
kConformCheck,
kConformBase
};
protected:
mutable INode* fSurfNode;
mutable Mesh* fSurfMesh;
mutable TriObject* fSurfObjToDelete;
mutable INodeTab fRepNodes;
mutable plDistTree* fDistTree;
mutable plDistTree fMeshTree;
Interface* fInterface;
IsoType fIsolation;
ConformType fConformity;
BOOL fFaceNormals;
float fSpacing;
float fRndPosRadius;
Point3 fAlignVec;
float fAlignWgt;
float fOffsetMin;
float fOffsetMax;
Point3 fAngProbVec;
float fAngProbLo;
float fAngProbHi;
float fAngProbTrans;
float fAltProbLo;
float fAltProbHi;
float fAltProbTrans;
float fPolarRange;
float fTanPolarRange;
float fAzimuthRange;
float fOverallProb;
float fPolarBunch;
ULONG fScaleLock;
Point3 fScaleLo;
Point3 fScaleHi;
BitmapTex* fProbBitmapTex;
plLayerTex* fProbLayerTex;
ColorChan fProbColorChan;
float fProbRemapFromLo;
float fProbRemapFromHi;
float fProbRemapToLo;
float fProbRemapToHi;
float fMaxConform; // in feet
Box3 fFade;
INode* fBone;
BOOL fRigid;
// Temps used during processing.
mutable Matrix3 fSurfToWorld;
mutable Matrix3 fWorldToSurf;
mutable Matrix3 fSurfToWorldVec;
mutable Matrix3 fWorldToSurfVec;
mutable Point3 fSurfAlignVec;
mutable Point3 fSurfAngProbVec;
mutable plRandom fRand;
mutable float fCosAngProbHi;
mutable float fCosAngProbHiTrans;
mutable float fCosAngProbLo;
mutable float fCosAngProbLoTrans;
void ISetAngProbCosines() const;
BOOL ISetSurfaceNode(INode* node) const;
BOOL IGetMesh(INode* node, TriObject*& objToDelete, Mesh*& retMesh) const;
BOOL INeedMeshTree() const;
void IMakeMeshTree() const;
void IFindFaceSet(const Box3& box, Tab<Int32>& faces) const;
BOOL IProjectVertex(const Point3& pt, const Point3& dir, float maxDist, Tab<Int32>&faces, Point3& projPt) const;
BOOL IConform(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const;
BOOL IConformHeight(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const;
BOOL IConformAll(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const;
BOOL IConformCheck(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const;
BOOL IConformBase(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const;
Matrix3 IOTM(int iRepNode) const;
Matrix3 IInvOTM(int iRepNode) const;
Matrix3 IGenerateTransform(int iRepNode, int iFace, const Point3& pt, const Point3& bary) const;
hsBool IProbablyDoIt(int iFace, Point3& del, const Point3& bary) const;
hsBool IFailsAltProb(int iFace, const Point3& bary) const;
hsBool IFailsAngProb(int iFace, const Point3& bary) const;
hsBool IFailsProbBitmap(int iFace, const Point3& bary) const;
Box3 ISetupGrid(const Point3& p0, const Point3& p1, const Point3& p2) const;
Point3& IPerturbPoint(Point3& pt) const;
int ISelectRepNode() const;
Point3 IPerpAxis(const Point3& p) const;
Point3 IGetSurfaceNormal(int iFace, const Point3& bary) const;
BOOL ISpaceClear(int iRepNode, const Matrix3& l2w, Box3& clearBox, plMeshCacheTab& cache) const;
void IReserveSpace(const Box3& clearBox) const;
void IReplicate(Matrix3& l2w, int iRep, plDistribInstTab& reps, plMeshCache& mCache) const;
void IDistributeOverFace(int iFace, plDistribInstTab& reps, plMeshCacheTab& cache) const;
BOOL IDistributeOverMesh(plDistribInstTab& reps, plMeshCacheTab& cache, plExportProgressBar& bar) const;
void IClear();
BOOL IValidateSettings(INode* surfNode, plMeshCacheTab& cache) const;
BOOL ISetupNormals(plMaxNode* node, Mesh* mesh, BOOL radiateNorm) const;
BOOL IDuplicate2Sided(plMaxNode* node, Mesh* mesh) const;
BOOL ISetupSkinWeights(plMaxNode* node, Mesh* mesh, const Point3& flex) const;
BOOL IReadyRepNodes(plMeshCacheTab& cache) const;
public:
plDistributor();
virtual ~plDistributor();
void SetTheInterface(Interface* i) { fInterface = i; }
Interface* GetTheInterface() const { return fInterface; }
BOOL Distribute(INode* surfNode, plDistribInstTab& replicants, plMeshCacheTab& cache, plExportProgressBar& bar) const;
void Reset();
UInt32 GetRandSeed() const;
void SetRandSeed(int seed);
void ClearReplicateNodes();
void AddReplicateNode(INode* node);
int GetNumReplicateNodes() const { return fRepNodes.Count(); }
INode* GetReplicateNode(int i) const { return fRepNodes[i]; }
INode* GetSurfaceNode() const { return fSurfNode; }
void SetSpacing(float f) { fSpacing = f; }
float GetSpacing() const { return fSpacing; }
void SetSpacingRange(float f) { fRndPosRadius = f; }
float GetSpacingRange() const { return fRndPosRadius; }
void SetAlignmentVec(const Point3& v) { fAlignVec = v; }
Point3 GetAlignmentVec() const { return fAlignVec; }
void SetAlignmentWeight(float w) { fAlignWgt = w / 100.f; }
float GetAlignmentWeight() const { return fAlignWgt * 100.f; }
void SetPolarRange(float deg);
float GetPolarRange() const { return hsScalarRadToDeg(fPolarRange); }
void SetAzimuthRange(float deg) { fAzimuthRange = hsScalarDegToRad(deg); }
float GetAzimuthRange() const { return hsScalarRadToDeg(fAzimuthRange); }
void SetOverallProb(float percent) { fOverallProb = percent/100.f; }
float GetOverallProb() const { return fOverallProb * 100.f; }
void SetAngleProbVec(const Point3& v) { fAngProbVec = v; }
Point3 GetAngleProbVec() const { return fAngProbVec; }
void SetAngleProbHi(float deg) { fAngProbHi = deg; }
float GetAngleProbHi() const { return fAngProbHi; }
void SetAngleProbLo(float deg) { fAngProbLo = deg; }
float GetAngleProbLo() const { return fAngProbLo; }
void SetAngleProbTransition(float deg) { fAngProbTrans = deg; }
float GetAngleProbTransition() const { return fAngProbTrans; }
void SetMinAltitude(float feet) { fAltProbLo = feet; }
float GetMinAltitude() const { return fAltProbLo; }
void SetMaxAltitude(float feet) { fAltProbHi = feet; }
float GetMaxAltitude() const { return fAltProbHi; }
void SetAltitudeTransition(float feet) { fAltProbTrans = feet; }
float GetAltitudeTransition() const { return fAltProbTrans; }
void SetPolarBunch(float b) { fPolarBunch = b/100.f; }
float GetPolarBunch() const { return fPolarBunch * 100.f; }
void SetScaleRange(const Point3& lo, const Point3& hi) { fScaleLo = lo; fScaleHi = hi; }
Point3 GetScaleRangeMin() const { return fScaleLo; }
Point3 GetScaleRangeMax() const { return fScaleHi; }
void SetProbabilityBitmapTex(BitmapTex* t);
BitmapTex* GetProbabilityBitmapTex() const { return fProbBitmapTex; }
void SetProbabilityLayerTex(plLayerTex* t);
plLayerTex* GetProbabilityLayerTex() const { return fProbLayerTex; }
void SetProbabilityChan(ColorChan c) { fProbColorChan = c; }
ColorChan GetProbabilityChan() const { return fProbColorChan; }
void SetProbabilityRemapFromLo(float f) { fProbRemapFromLo = f / 255.f; }
float GetProbabilityRemapFromLo() const { return fProbRemapFromLo * 255.f; }
void SetProbabilityRemapFromHi(float f) { fProbRemapFromHi = f / 255.f; }
float GetProbabilityRemapFromHi() const { return fProbRemapFromHi * 255.f; }
void SetProbabilityRemapToLo(float f) { fProbRemapToLo = f / 255.f; }
float GetProbabilityRemapToLo() const { return fProbRemapToLo * 255.f; }
void SetProbabilityRemapToHi(float f) { fProbRemapToHi = f / 255.f; }
float GetProbabilityRemapToHi() const { return fProbRemapToHi * 255.f; }
// We don't really know what fades are, they're just something we're handed that
// we stamp on every distribInstance we generate. See plDistribComponent.h.
void SetFade(const Box3& fade) { fFade = fade; }
Box3 GetFade() const { return fFade; }
void SetBone(INode* b) { fBone = b; }
INode* GetBone() const { return fBone; }
void SetRigid(BOOL b) { fRigid = b; }
BOOL GetRigid() const { return fRigid; }
void SetScaleLock(ULONG f) { fScaleLock = f; }
ULONG GetScaleLock() const { return fScaleLock; }
void SetDistTree(plDistTree* dt) { fDistTree = dt; }
plDistTree* GetDistTree() const { return fDistTree; }
void SetIsolation(IsoType t) { fIsolation = t; }
IsoType GetIsolation() const { return fIsolation; }
void SetConformity(ConformType t) { fConformity = t; }
ConformType GetConformity() const { return fConformity; }
void SetMaxConform(float feet) { fMaxConform = feet; }
float GetMaxConform() const { return fMaxConform; }
void SetMinOffset(float feet) { fOffsetMin = feet; }
float GetMinOffset() const { return fOffsetMin; }
void SetMaxOffset(float feet) { fOffsetMax = feet; }
float GetMaxOffset() const { return fOffsetMax; }
void SetFaceNormals(BOOL on=true) { fFaceNormals = on; }
BOOL GetFaceNormals() const { return fFaceNormals; }
};
#endif // plDistributor_inc
/*==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 <http://www.gnu.org/licenses/>.
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 plDistributor_inc
#define plDistributor_inc
#include "../plMath/plRandom.h"
#include "plDistTree.h"
class INode;
class Mesh;
class TriObject;
class BitmapTex;
class plLayerTex;
class plExportProgressBar;
class plMaxNode;
class plDistTree;
// To Use:
//
// First you must set the interface
// Second, you must set the node(s) to be replicated.
// If multiple replicants, they will be randomly selected at each plant site.
// Set the spacing. Default is 10 or so, but shouldn't be counted on.
// Set the spacing range. Set it to less than half the spacing to prevent
// replicants piling up on each other.
// Rather than increasing the spacing range (which causes pileup), you can increase
// the randomness of placement with the overall probability factor. Reducing it
// means fewer grid points will be used, so placement seems more random
//
// Options:
// PolarRange - defines the cone about the surface normal to randomly fill for up direction
// PolarBunch - defines tendency to bunch around the center of PolarRange cone,
// with zero being uniform distribution, and one being all on cone axis.
// AlignmentVector - defines a world space preferred up orientation.
// AlignmentWeight - blend factor between random normal (from polar stuff) and
// above AlignmentVector.
// ScaleRange - defines range of non-uniform scale to apply to each replicant.
// ProbabilityTexmap - A BitmapTex which maps the probability of an instance
// taking root at any point on the surface. Various interpretations of the
// map available (see ProbabilityChan). If the surface mesh doesn't have
// the appropriate uvw mapping for the map, the map will be ignored.
// ProbabilityChan - defines interpretation of texel value from ProbTexmap
// into a probability. ColorChan enum types are pretty self-explanatory.
// In all cases, a higher texel channel value means more likely of a
// replicant taking root there.
//
// Finally, call Distrubute() with a node containing a surface to be populated.
//
// Modifying. Were actually creating the new node instances, but then we just
// want to re-pack them into clusters anyway. So all we really need is to
// know which template (fRepNodes) and what transform to use for it. We can
// use that to make our clusters, without bogging Max down with adding and
// deleting a gazillion INodes.
class plDistribInstance
{
public:
INode* fNode;
Matrix3 fNodeTM;
Matrix3 fObjectTM;
INode* fBone;
BOOL fRigid;
Box3 fFade;
Point3 fFlex;
Mesh* fMesh;
};
class plDistribInstTab : public Tab<plDistribInstance>
{
};
class plMeshCache
{
public:
Mesh* fMesh;
Point3 fFlex;
plMeshCache() {}
};
class plMeshCacheTab : public Tab<plMeshCache>
{
};
class plDistributor
{
public:
enum ColorChan
{
kRed = 0x1,
kGreen = 0x2,
kBlue = 0x4,
kAlpha = 0x8,
kAverageRedGreen = kRed | kGreen,
kAverageRedGreenTimesAlpha = kRed | kGreen | kAlpha,
kAverage = kRed | kGreen | kBlue,
kAverageTimesAlpha = kAverage | kAlpha,
kMax = 0x100,
kMaxColor = kMax | kRed | kGreen | kBlue,
kMaxColorTimesAlpha = kMaxColor | kAlpha,
kMaxRedGreen = kMax | kRed | kGreen,
kMaxRedGreenTimesAlpha = kMaxRedGreen | kAlpha
};
enum
{
kLockNone = 0x0,
kLockX = 0x1,
kLockY = 0x2,
kLockZ = 0x4
};
enum
{
kWgtMapChan = 66,
kNormMapChan = 67
};
enum IsoType
{
kIsoNone,
kIsoLow,
kIsoMedium,
kIsoHigh,
kIsoMax = kIsoHigh
};
enum ConformType
{
kConformNone,
kConformAll,
kConformHeight,
kConformCheck,
kConformBase
};
protected:
mutable INode* fSurfNode;
mutable Mesh* fSurfMesh;
mutable TriObject* fSurfObjToDelete;
mutable INodeTab fRepNodes;
mutable plDistTree* fDistTree;
mutable plDistTree fMeshTree;
Interface* fInterface;
IsoType fIsolation;
ConformType fConformity;
BOOL fFaceNormals;
float fSpacing;
float fRndPosRadius;
Point3 fAlignVec;
float fAlignWgt;
float fOffsetMin;
float fOffsetMax;
Point3 fAngProbVec;
float fAngProbLo;
float fAngProbHi;
float fAngProbTrans;
float fAltProbLo;
float fAltProbHi;
float fAltProbTrans;
float fPolarRange;
float fTanPolarRange;
float fAzimuthRange;
float fOverallProb;
float fPolarBunch;
ULONG fScaleLock;
Point3 fScaleLo;
Point3 fScaleHi;
BitmapTex* fProbBitmapTex;
plLayerTex* fProbLayerTex;
ColorChan fProbColorChan;
float fProbRemapFromLo;
float fProbRemapFromHi;
float fProbRemapToLo;
float fProbRemapToHi;
float fMaxConform; // in feet
Box3 fFade;
INode* fBone;
BOOL fRigid;
// Temps used during processing.
mutable Matrix3 fSurfToWorld;
mutable Matrix3 fWorldToSurf;
mutable Matrix3 fSurfToWorldVec;
mutable Matrix3 fWorldToSurfVec;
mutable Point3 fSurfAlignVec;
mutable Point3 fSurfAngProbVec;
mutable plRandom fRand;
mutable float fCosAngProbHi;
mutable float fCosAngProbHiTrans;
mutable float fCosAngProbLo;
mutable float fCosAngProbLoTrans;
void ISetAngProbCosines() const;
BOOL ISetSurfaceNode(INode* node) const;
BOOL IGetMesh(INode* node, TriObject*& objToDelete, Mesh*& retMesh) const;
BOOL INeedMeshTree() const;
void IMakeMeshTree() const;
void IFindFaceSet(const Box3& box, Tab<Int32>& faces) const;
BOOL IProjectVertex(const Point3& pt, const Point3& dir, float maxDist, Tab<Int32>&faces, Point3& projPt) const;
BOOL IConform(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const;
BOOL IConformHeight(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const;
BOOL IConformAll(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const;
BOOL IConformCheck(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const;
BOOL IConformBase(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const;
Matrix3 IOTM(int iRepNode) const;
Matrix3 IInvOTM(int iRepNode) const;
Matrix3 IGenerateTransform(int iRepNode, int iFace, const Point3& pt, const Point3& bary) const;
hsBool IProbablyDoIt(int iFace, Point3& del, const Point3& bary) const;
hsBool IFailsAltProb(int iFace, const Point3& bary) const;
hsBool IFailsAngProb(int iFace, const Point3& bary) const;
hsBool IFailsProbBitmap(int iFace, const Point3& bary) const;
Box3 ISetupGrid(const Point3& p0, const Point3& p1, const Point3& p2) const;
Point3& IPerturbPoint(Point3& pt) const;
int ISelectRepNode() const;
Point3 IPerpAxis(const Point3& p) const;
Point3 IGetSurfaceNormal(int iFace, const Point3& bary) const;
BOOL ISpaceClear(int iRepNode, const Matrix3& l2w, Box3& clearBox, plMeshCacheTab& cache) const;
void IReserveSpace(const Box3& clearBox) const;
void IReplicate(Matrix3& l2w, int iRep, plDistribInstTab& reps, plMeshCache& mCache) const;
void IDistributeOverFace(int iFace, plDistribInstTab& reps, plMeshCacheTab& cache) const;
BOOL IDistributeOverMesh(plDistribInstTab& reps, plMeshCacheTab& cache, plExportProgressBar& bar) const;
void IClear();
BOOL IValidateSettings(INode* surfNode, plMeshCacheTab& cache) const;
BOOL ISetupNormals(plMaxNode* node, Mesh* mesh, BOOL radiateNorm) const;
BOOL IDuplicate2Sided(plMaxNode* node, Mesh* mesh) const;
BOOL ISetupSkinWeights(plMaxNode* node, Mesh* mesh, const Point3& flex) const;
BOOL IReadyRepNodes(plMeshCacheTab& cache) const;
public:
plDistributor();
virtual ~plDistributor();
void SetTheInterface(Interface* i) { fInterface = i; }
Interface* GetTheInterface() const { return fInterface; }
BOOL Distribute(INode* surfNode, plDistribInstTab& replicants, plMeshCacheTab& cache, plExportProgressBar& bar) const;
void Reset();
UInt32 GetRandSeed() const;
void SetRandSeed(int seed);
void ClearReplicateNodes();
void AddReplicateNode(INode* node);
int GetNumReplicateNodes() const { return fRepNodes.Count(); }
INode* GetReplicateNode(int i) const { return fRepNodes[i]; }
INode* GetSurfaceNode() const { return fSurfNode; }
void SetSpacing(float f) { fSpacing = f; }
float GetSpacing() const { return fSpacing; }
void SetSpacingRange(float f) { fRndPosRadius = f; }
float GetSpacingRange() const { return fRndPosRadius; }
void SetAlignmentVec(const Point3& v) { fAlignVec = v; }
Point3 GetAlignmentVec() const { return fAlignVec; }
void SetAlignmentWeight(float w) { fAlignWgt = w / 100.f; }
float GetAlignmentWeight() const { return fAlignWgt * 100.f; }
void SetPolarRange(float deg);
float GetPolarRange() const { return hsScalarRadToDeg(fPolarRange); }
void SetAzimuthRange(float deg) { fAzimuthRange = hsScalarDegToRad(deg); }
float GetAzimuthRange() const { return hsScalarRadToDeg(fAzimuthRange); }
void SetOverallProb(float percent) { fOverallProb = percent/100.f; }
float GetOverallProb() const { return fOverallProb * 100.f; }
void SetAngleProbVec(const Point3& v) { fAngProbVec = v; }
Point3 GetAngleProbVec() const { return fAngProbVec; }
void SetAngleProbHi(float deg) { fAngProbHi = deg; }
float GetAngleProbHi() const { return fAngProbHi; }
void SetAngleProbLo(float deg) { fAngProbLo = deg; }
float GetAngleProbLo() const { return fAngProbLo; }
void SetAngleProbTransition(float deg) { fAngProbTrans = deg; }
float GetAngleProbTransition() const { return fAngProbTrans; }
void SetMinAltitude(float feet) { fAltProbLo = feet; }
float GetMinAltitude() const { return fAltProbLo; }
void SetMaxAltitude(float feet) { fAltProbHi = feet; }
float GetMaxAltitude() const { return fAltProbHi; }
void SetAltitudeTransition(float feet) { fAltProbTrans = feet; }
float GetAltitudeTransition() const { return fAltProbTrans; }
void SetPolarBunch(float b) { fPolarBunch = b/100.f; }
float GetPolarBunch() const { return fPolarBunch * 100.f; }
void SetScaleRange(const Point3& lo, const Point3& hi) { fScaleLo = lo; fScaleHi = hi; }
Point3 GetScaleRangeMin() const { return fScaleLo; }
Point3 GetScaleRangeMax() const { return fScaleHi; }
void SetProbabilityBitmapTex(BitmapTex* t);
BitmapTex* GetProbabilityBitmapTex() const { return fProbBitmapTex; }
void SetProbabilityLayerTex(plLayerTex* t);
plLayerTex* GetProbabilityLayerTex() const { return fProbLayerTex; }
void SetProbabilityChan(ColorChan c) { fProbColorChan = c; }
ColorChan GetProbabilityChan() const { return fProbColorChan; }
void SetProbabilityRemapFromLo(float f) { fProbRemapFromLo = f / 255.f; }
float GetProbabilityRemapFromLo() const { return fProbRemapFromLo * 255.f; }
void SetProbabilityRemapFromHi(float f) { fProbRemapFromHi = f / 255.f; }
float GetProbabilityRemapFromHi() const { return fProbRemapFromHi * 255.f; }
void SetProbabilityRemapToLo(float f) { fProbRemapToLo = f / 255.f; }
float GetProbabilityRemapToLo() const { return fProbRemapToLo * 255.f; }
void SetProbabilityRemapToHi(float f) { fProbRemapToHi = f / 255.f; }
float GetProbabilityRemapToHi() const { return fProbRemapToHi * 255.f; }
// We don't really know what fades are, they're just something we're handed that
// we stamp on every distribInstance we generate. See plDistribComponent.h.
void SetFade(const Box3& fade) { fFade = fade; }
Box3 GetFade() const { return fFade; }
void SetBone(INode* b) { fBone = b; }
INode* GetBone() const { return fBone; }
void SetRigid(BOOL b) { fRigid = b; }
BOOL GetRigid() const { return fRigid; }
void SetScaleLock(ULONG f) { fScaleLock = f; }
ULONG GetScaleLock() const { return fScaleLock; }
void SetDistTree(plDistTree* dt) { fDistTree = dt; }
plDistTree* GetDistTree() const { return fDistTree; }
void SetIsolation(IsoType t) { fIsolation = t; }
IsoType GetIsolation() const { return fIsolation; }
void SetConformity(ConformType t) { fConformity = t; }
ConformType GetConformity() const { return fConformity; }
void SetMaxConform(float feet) { fMaxConform = feet; }
float GetMaxConform() const { return fMaxConform; }
void SetMinOffset(float feet) { fOffsetMin = feet; }
float GetMinOffset() const { return fOffsetMin; }
void SetMaxOffset(float feet) { fOffsetMax = feet; }
float GetMaxOffset() const { return fOffsetMax; }
void SetFaceNormals(BOOL on=true) { fFaceNormals = on; }
BOOL GetFaceNormals() const { return fFaceNormals; }
};
#endif // plDistributor_inc

File diff suppressed because it is too large Load Diff

View File

@ -1,123 +1,123 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plLayerConverter - Utility class that converts plPlasmaMAXLayers into //
// other stuff. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 1.13.2002 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plLayerConverter_h
#define _plLayerConverter_h
#include "hsTypes.h"
#include "hsTemplates.h"
#include "Max.h"
//// Class Definition /////////////////////////////////////////////////////////
class plErrorMsg;
class plLayerInterface;
class plMaxNode;
class plPlasmaMAXLayer;
class plLayer;
class plLocation;
class plBitmapData;
class plDynamicTextMap;
class plBitmap;
class plCubicRenderTarget;
class hsConverterUtils;
class plDynamicTextLayer;
class plLayerConverter
{
private:
plLayerConverter();
protected:
static const Class_ID fDerivedTypes[];
public:
~plLayerConverter();
static plLayerConverter &Instance( void );
void Init( hsBool save, plErrorMsg *msg );
void DeInit( void );
plLayerInterface *ConvertTexmap( Texmap *texmap, plMaxNode *maxNode,
UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer );
plBitmap *CreateSimpleTexture(const char *fileName, const plLocation &loc, UInt32 clipID = 0, UInt32 texFlags = 0, bool useJPEG = false);
void MuteWarnings( void );
void UnmuteWarnings( void );
protected:
plErrorMsg *fErrorMsg;
UInt32 fWarned, fSavedWarned;
hsBool fSaving;
Interface *fInterface;
hsConverterUtils &fConverterUtils;
const char *fDbgNodeName;
hsTArray<plPlasmaMAXLayer *> fConvertedLayers;
plLayer *ICreateLayer( const char *name, hsBool upperLayer, plLocation &loc );
void IProcessUVGen( plPlasmaMAXLayer *srcLayer, plLayer *destLayer, plBitmapData *bitmapData, hsBool preserveUVOffset );
plDynamicTextMap *ICreateDynTextMap( const char *layerName, UInt32 width, UInt32 height, hsBool includeAlpha, plMaxNode *node );
plLayer *IAssignTexture( plBitmapData *bd, plMaxNode *maxNode, plLayer *destLayer, hsBool upperLayer, int clipID = -1 );
plCubicRenderTarget *IMakeCubicRenderTarget( const char *name, plMaxNode *maxNode, plMaxNode *anchor );
// Add your function to process your layer type here
plLayerInterface *IConvertLayerTex( plPlasmaMAXLayer *layer, plMaxNode *maxNode, UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer );
plLayerInterface *IConvertStaticEnvLayer( plPlasmaMAXLayer *layer, plMaxNode *maxNode, UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer );
plLayerInterface *IConvertDynamicEnvLayer( plPlasmaMAXLayer *layer, plMaxNode *maxNode, UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer );
plLayerInterface *IConvertCameraLayer( plPlasmaMAXLayer *layer, plMaxNode *maxNode, UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer );
plLayerInterface *IConvertDynamicTextLayer( plPlasmaMAXLayer *layer, plMaxNode *maxNode, UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer );
plBitmap* IGetAttenRamp( plMaxNode *maxNode, BOOL isAdd, int loClamp, int hiClamp);
plLayer* ICreateAttenuationLayer(const char* name, plMaxNode *maxNode, int uvwSrc, float tr0, float op0, float tr1, float op1, int loClamp, int hiClamp);
plLayerInterface* IConvertAngleAttenLayer(plPlasmaMAXLayer *layer, plMaxNode *maxNode, UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer);
void IRegisterConversion( plPlasmaMAXLayer *origLayer, plLayerInterface *convertedLayer );
UInt32 *IGetInitBitmapBuffer( plDynamicTextLayer *layer ) const;
};
#endif // _plLayerConverter_h
/*==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 <http://www.gnu.org/licenses/>.
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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plLayerConverter - Utility class that converts plPlasmaMAXLayers into //
// other stuff. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 1.13.2002 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plLayerConverter_h
#define _plLayerConverter_h
#include "hsTypes.h"
#include "hsTemplates.h"
#include "Max.h"
//// Class Definition /////////////////////////////////////////////////////////
class plErrorMsg;
class plLayerInterface;
class plMaxNode;
class plPlasmaMAXLayer;
class plLayer;
class plLocation;
class plBitmapData;
class plDynamicTextMap;
class plBitmap;
class plCubicRenderTarget;
class hsConverterUtils;
class plDynamicTextLayer;
class plLayerConverter
{
private:
plLayerConverter();
protected:
static const Class_ID fDerivedTypes[];
public:
~plLayerConverter();
static plLayerConverter &Instance( void );
void Init( hsBool save, plErrorMsg *msg );
void DeInit( void );
plLayerInterface *ConvertTexmap( Texmap *texmap, plMaxNode *maxNode,
UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer );
plBitmap *CreateSimpleTexture(const char *fileName, const plLocation &loc, UInt32 clipID = 0, UInt32 texFlags = 0, bool useJPEG = false);
void MuteWarnings( void );
void UnmuteWarnings( void );
protected:
plErrorMsg *fErrorMsg;
UInt32 fWarned, fSavedWarned;
hsBool fSaving;
Interface *fInterface;
hsConverterUtils &fConverterUtils;
const char *fDbgNodeName;
hsTArray<plPlasmaMAXLayer *> fConvertedLayers;
plLayer *ICreateLayer( const char *name, hsBool upperLayer, plLocation &loc );
void IProcessUVGen( plPlasmaMAXLayer *srcLayer, plLayer *destLayer, plBitmapData *bitmapData, hsBool preserveUVOffset );
plDynamicTextMap *ICreateDynTextMap( const char *layerName, UInt32 width, UInt32 height, hsBool includeAlpha, plMaxNode *node );
plLayer *IAssignTexture( plBitmapData *bd, plMaxNode *maxNode, plLayer *destLayer, hsBool upperLayer, int clipID = -1 );
plCubicRenderTarget *IMakeCubicRenderTarget( const char *name, plMaxNode *maxNode, plMaxNode *anchor );
// Add your function to process your layer type here
plLayerInterface *IConvertLayerTex( plPlasmaMAXLayer *layer, plMaxNode *maxNode, UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer );
plLayerInterface *IConvertStaticEnvLayer( plPlasmaMAXLayer *layer, plMaxNode *maxNode, UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer );
plLayerInterface *IConvertDynamicEnvLayer( plPlasmaMAXLayer *layer, plMaxNode *maxNode, UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer );
plLayerInterface *IConvertCameraLayer( plPlasmaMAXLayer *layer, plMaxNode *maxNode, UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer );
plLayerInterface *IConvertDynamicTextLayer( plPlasmaMAXLayer *layer, plMaxNode *maxNode, UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer );
plBitmap* IGetAttenRamp( plMaxNode *maxNode, BOOL isAdd, int loClamp, int hiClamp);
plLayer* ICreateAttenuationLayer(const char* name, plMaxNode *maxNode, int uvwSrc, float tr0, float op0, float tr1, float op1, int loClamp, int hiClamp);
plLayerInterface* IConvertAngleAttenLayer(plPlasmaMAXLayer *layer, plMaxNode *maxNode, UInt32 blendFlags, hsBool preserveUVOffset, hsBool upperLayer);
void IRegisterConversion( plPlasmaMAXLayer *origLayer, plLayerInterface *convertedLayer );
UInt32 *IGetInitBitmapBuffer( plDynamicTextLayer *layer ) const;
};
#endif // _plLayerConverter_h

File diff suppressed because it is too large Load Diff

View File

@ -1,174 +1,174 @@
/*==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 <http://www.gnu.org/licenses/>.
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 plLightMapGen_inc
#define plLightMapGen_inc
#include "hsTemplates.h"
#include <vector>
class plMaxLightContext;
class plRenderGlobalContext;
class plLayerInterface;
class plMaxNode;
class hsGMaterial;
class plGeometrySpan;
class plMipmap;
class plBitmap;
struct hsColorRGBA;
struct hsPoint3;
struct hsVector3;
struct hsMatrix44;
class plErrorMsg;
class plConvertSettings;
class hsBounds3Ext;
class plLightMapComponent;
class plLightMapInfo
{
public:
ObjLightDesc* fObjLiDesc;
INode* fLiNode;
int fResetShadowType;
float fResetMapRange;
float fMapRange;
hsBool fNewRender;
};
class plLightMapGen
{
protected:
Interface* fInterface;
TimeValue fTime;
int fUVWSrc;
float fScale;
float fMapRange;
int fWidth;
int fHeight;
bool fRecalcLightMaps;
Renderer* fRenderer;
#ifdef MF_NEW_RGC
RenderGlobalContext* fRGC;
#else // MF_NEW_RGC
plRenderGlobalContext* fRGC;
#endif // MF_NEW_RGC
RendParams* fRP;
hsTArray<plLightMapInfo> fAllLights;
hsTArray<plLightMapInfo*> fActiveLights;
mutable hsTArray<plLayerInterface*> fCreatedLayers;
mutable hsTArray<plMipmap*> fPreppedMipmaps;
mutable hsTArray<plBitmap*> fNewMaps; // Mipmaps created this session (not loaded from disk)
std::vector<plLightMapComponent*> fSharedComponents; // HACK so we can get rid of key refs before deleting bitmaps
hsBounds3Ext IGetBoundsLightSpace(INode* node, INode* liNode);
hsBool IDirAffectsNode(plLightMapInfo* liInfo, LightObject* liObj, INode* node);
hsBool ISpotAffectsNode(plLightMapInfo* liInfo, LightObject* liObj, INode* node);
hsBool IOmniAffectsNode(plLightMapInfo* liInfo, LightObject* liObj, INode* node);
hsBool ILightAffectsNode(plLightMapInfo* liInfo, LightObject* liObj, INode* node);
hsBool IPrepLight(plLightMapInfo* liInfo, INode* node);
hsBool IGetLight(INode* node);
hsBool IFindLightsRecur(INode* node);
hsBool IFindActiveLights(plMaxNode* node);
hsBool IReleaseActiveLights();
hsBool IReleaseAllLights();
int IPowerOfTwo(int sz) const;
hsBool ISelectBitmapDimension(plMaxNode* node, const hsMatrix44& l2w, const hsMatrix44& w2l, hsTArray<plGeometrySpan *> &spans);
hsBool ICompressLightMaps();
hsBool IsFresh(plBitmap* map) const;
hsBool IAddToLightMap(plLayerInterface* lay, plMipmap* src) const;
plMipmap* IMakeAccumBitmap(plLayerInterface* lay) const;
void IInitBitmapColor(plMipmap* bitmap, const hsColorRGBA& col) const;
plLayerInterface* IGetLightMapLayer(plMaxNode* node, plGeometrySpan& span);
plLayerInterface* IMakeLightMapLayer(plMaxNode* node, plGeometrySpan& span);
int IGetUVWSrc() const { return fUVWSrc; }
UInt32 IShadePoint(plMaxLightContext& ctx, const Color& amb, const hsPoint3& p, const hsVector3& n);
hsBool IShadeVerts(plMaxLightContext& ctx, const Color& amb, const hsPoint3 pt[3], const hsVector3 norm[3], const hsPoint3 uv[3], plMipmap* bitmap);
hsBool IShadeFace(plMaxNode* node, const hsMatrix44& l2w, const hsMatrix44& w2l, plGeometrySpan& span, int iFace, plMipmap* bitmap);
hsBool IShadeSpan(plMaxNode* node, const hsMatrix44& l2w, const hsMatrix44& w2l, plGeometrySpan& spans);
hsBool IShadeGeometrySpans(plMaxNode* node, const hsMatrix44& l2w, const hsMatrix44& w2l, hsTArray<plGeometrySpan *> &spans);
hsBool IWantsMaps(plMaxNode* node);
hsBool IValidateUVWSrc(hsTArray<plGeometrySpan *> &spans) const;
public:
plLightMapGen();
virtual ~plLightMapGen();
#ifdef MF_NEW_RGC
void SetRGC(RenderGlobalContext* rgc); // Don't call this ever ever ever
#endif // MF_NEW_RGC
hsBool Open(Interface* ip, TimeValue t, bool forceRegen=true);
hsBool InitNode(INode* node, hsBool softShadow=true); // unnecessary when using MakeMaps()
hsBool Update(TimeValue t);
void SetUVWSrc(int i) { fUVWSrc = i; }
int GetUVWSrc() const { return fUVWSrc; }
void SetScale(float f) { fScale = f; }
float GetScale() const { return fScale; }
// Calls to either the global or single must be wrapped in
// a call to Open and a call to close. That is, you must first
// call Open(), then you can make maps all day, but at the end
// of the day, you need to call Close(). Also, if the scene
// lighting changes, you need to call Close() and then Open() again.
// With the possibility of lights getting deleted from the scene,
// you're best off calling Open(), making as many maps as you want
// for now, call Close(), and if you decide later you want more,
// re-open. There's no protection in here from a user deleting
// a light (or any other node) while the shader is Open. For your
// own safety and the safety of your fellow passengers, don't
// return control to the user until the system is Closed.
hsBool MakeMaps(plMaxNode* node, const hsMatrix44& l2w, const hsMatrix44& w2l, hsTArray<plGeometrySpan *>& spans, plErrorMsg *pErrMsg, plConvertSettings *settings);
Color ShadowPoint(plMaxLightContext& ctx);
Color ShadePoint(plMaxLightContext& ctx); // ctx already contains pos & norm
Color ShadePoint(plMaxLightContext& ctx, const Point3& p, const Point3& n);
Color ShadePoint(plMaxLightContext& ctx, const hsPoint3& p, const hsVector3& n);
hsBool DeInitNode();
hsBool Close();
static plLightMapGen& Instance();
};
#endif // plLightMapGen_inc
/*==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 <http://www.gnu.org/licenses/>.
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 plLightMapGen_inc
#define plLightMapGen_inc
#include "hsTemplates.h"
#include <vector>
class plMaxLightContext;
class plRenderGlobalContext;
class plLayerInterface;
class plMaxNode;
class hsGMaterial;
class plGeometrySpan;
class plMipmap;
class plBitmap;
struct hsColorRGBA;
struct hsPoint3;
struct hsVector3;
struct hsMatrix44;
class plErrorMsg;
class plConvertSettings;
class hsBounds3Ext;
class plLightMapComponent;
class plLightMapInfo
{
public:
ObjLightDesc* fObjLiDesc;
INode* fLiNode;
int fResetShadowType;
float fResetMapRange;
float fMapRange;
hsBool fNewRender;
};
class plLightMapGen
{
protected:
Interface* fInterface;
TimeValue fTime;
int fUVWSrc;
float fScale;
float fMapRange;
int fWidth;
int fHeight;
bool fRecalcLightMaps;
Renderer* fRenderer;
#ifdef MF_NEW_RGC
RenderGlobalContext* fRGC;
#else // MF_NEW_RGC
plRenderGlobalContext* fRGC;
#endif // MF_NEW_RGC
RendParams* fRP;
hsTArray<plLightMapInfo> fAllLights;
hsTArray<plLightMapInfo*> fActiveLights;
mutable hsTArray<plLayerInterface*> fCreatedLayers;
mutable hsTArray<plMipmap*> fPreppedMipmaps;
mutable hsTArray<plBitmap*> fNewMaps; // Mipmaps created this session (not loaded from disk)
std::vector<plLightMapComponent*> fSharedComponents; // HACK so we can get rid of key refs before deleting bitmaps
hsBounds3Ext IGetBoundsLightSpace(INode* node, INode* liNode);
hsBool IDirAffectsNode(plLightMapInfo* liInfo, LightObject* liObj, INode* node);
hsBool ISpotAffectsNode(plLightMapInfo* liInfo, LightObject* liObj, INode* node);
hsBool IOmniAffectsNode(plLightMapInfo* liInfo, LightObject* liObj, INode* node);
hsBool ILightAffectsNode(plLightMapInfo* liInfo, LightObject* liObj, INode* node);
hsBool IPrepLight(plLightMapInfo* liInfo, INode* node);
hsBool IGetLight(INode* node);
hsBool IFindLightsRecur(INode* node);
hsBool IFindActiveLights(plMaxNode* node);
hsBool IReleaseActiveLights();
hsBool IReleaseAllLights();
int IPowerOfTwo(int sz) const;
hsBool ISelectBitmapDimension(plMaxNode* node, const hsMatrix44& l2w, const hsMatrix44& w2l, hsTArray<plGeometrySpan *> &spans);
hsBool ICompressLightMaps();
hsBool IsFresh(plBitmap* map) const;
hsBool IAddToLightMap(plLayerInterface* lay, plMipmap* src) const;
plMipmap* IMakeAccumBitmap(plLayerInterface* lay) const;
void IInitBitmapColor(plMipmap* bitmap, const hsColorRGBA& col) const;
plLayerInterface* IGetLightMapLayer(plMaxNode* node, plGeometrySpan& span);
plLayerInterface* IMakeLightMapLayer(plMaxNode* node, plGeometrySpan& span);
int IGetUVWSrc() const { return fUVWSrc; }
UInt32 IShadePoint(plMaxLightContext& ctx, const Color& amb, const hsPoint3& p, const hsVector3& n);
hsBool IShadeVerts(plMaxLightContext& ctx, const Color& amb, const hsPoint3 pt[3], const hsVector3 norm[3], const hsPoint3 uv[3], plMipmap* bitmap);
hsBool IShadeFace(plMaxNode* node, const hsMatrix44& l2w, const hsMatrix44& w2l, plGeometrySpan& span, int iFace, plMipmap* bitmap);
hsBool IShadeSpan(plMaxNode* node, const hsMatrix44& l2w, const hsMatrix44& w2l, plGeometrySpan& spans);
hsBool IShadeGeometrySpans(plMaxNode* node, const hsMatrix44& l2w, const hsMatrix44& w2l, hsTArray<plGeometrySpan *> &spans);
hsBool IWantsMaps(plMaxNode* node);
hsBool IValidateUVWSrc(hsTArray<plGeometrySpan *> &spans) const;
public:
plLightMapGen();
virtual ~plLightMapGen();
#ifdef MF_NEW_RGC
void SetRGC(RenderGlobalContext* rgc); // Don't call this ever ever ever
#endif // MF_NEW_RGC
hsBool Open(Interface* ip, TimeValue t, bool forceRegen=true);
hsBool InitNode(INode* node, hsBool softShadow=true); // unnecessary when using MakeMaps()
hsBool Update(TimeValue t);
void SetUVWSrc(int i) { fUVWSrc = i; }
int GetUVWSrc() const { return fUVWSrc; }
void SetScale(float f) { fScale = f; }
float GetScale() const { return fScale; }
// Calls to either the global or single must be wrapped in
// a call to Open and a call to close. That is, you must first
// call Open(), then you can make maps all day, but at the end
// of the day, you need to call Close(). Also, if the scene
// lighting changes, you need to call Close() and then Open() again.
// With the possibility of lights getting deleted from the scene,
// you're best off calling Open(), making as many maps as you want
// for now, call Close(), and if you decide later you want more,
// re-open. There's no protection in here from a user deleting
// a light (or any other node) while the shader is Open. For your
// own safety and the safety of your fellow passengers, don't
// return control to the user until the system is Closed.
hsBool MakeMaps(plMaxNode* node, const hsMatrix44& l2w, const hsMatrix44& w2l, hsTArray<plGeometrySpan *>& spans, plErrorMsg *pErrMsg, plConvertSettings *settings);
Color ShadowPoint(plMaxLightContext& ctx);
Color ShadePoint(plMaxLightContext& ctx); // ctx already contains pos & norm
Color ShadePoint(plMaxLightContext& ctx, const Point3& p, const Point3& n);
Color ShadePoint(plMaxLightContext& ctx, const hsPoint3& p, const hsVector3& n);
hsBool DeInitNode();
hsBool Close();
static plLightMapGen& Instance();
};
#endif // plLightMapGen_inc

View File

@ -1,124 +1,124 @@
/*==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 <http://www.gnu.org/licenses/>.
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 plMaxLightContext_inc
#define plMaxLightContext_inc
#include "hsGeometry3.h"
class plMaxLightContext : public ShadeContext
{
protected:
TimeValue fCurrentTime;
Box3 fBounds;
Point3 fPos;
Point3 fNorm;
Point3 fPertNorm;
public:
plMaxLightContext(const Box3& b, TimeValue t=0)
{
fBounds = b;
fCurrentTime = t;
doMaps = true;
filterMaps = true;
backFace = false;
xshadeID = 0;
mtlNum = 0;
}
void SetPoint(const Point3& p, const Point3& n) { fPos = p; fNorm = fPertNorm = n; } // Must be world space coming in.
void SetPoint(const hsPoint3& p, const hsVector3& n) { fPos = Point3(p.fX,p.fY,p.fZ); fNorm = fPertNorm = Point3(n.fX,n.fY,n.fZ); } // Must be world space coming in.
virtual BOOL InMtlEditor() { return false; } // is this rendering the mtl editor sample sphere?
virtual LightDesc* Light(int n) { return nil; } // get the nth light.
virtual TimeValue CurTime() { return fCurrentTime; } // current time value
virtual int FaceNumber() { return 0; }
virtual Point3 Normal() { return fPertNorm; } // interpolated surface normal, in cameara coords: affected by SetNormal()
virtual void SetNormal(Point3 p) { fPertNorm = p; } // used for perturbing normal
virtual Point3 OrigNormal() { return fNorm; } // original surface normal: not affected by SetNormal();
virtual Point3 GNormal() { return fNorm; } // geometric (face) normal
virtual Point3 V() { return Point3(0.f,1.f,0.f); } // Unit view vector: from camera towards P
virtual void SetView(Point3 p) { } // Set the view vector
virtual Point3 ReflectVector() { return V(); } // reflection vector
virtual Point3 RefractVector(float ior) { return V(); } // refraction vector
virtual Point3 CamPos() { return Point3(0,0,0); } // camera position
virtual Point3 P() { return fPos; } // point to be shaded;
virtual Point3 DP() { return Point3(0,0,0); } // deriv of P, relative to pixel, for AA
virtual Point3 PObj() { return P(); } // point in obj coords
virtual Point3 DPObj() { return DP(); } // deriv of PObj, rel to pixel, for AA
virtual Box3 ObjectBox() { return fBounds; } // Object extents box in obj coords
virtual Point3 PObjRelBox(); // Point rel to obj box [-1 .. +1 ]
virtual Point3 DPObjRelBox() { return Point3(0,0,0); } // deriv of Point rel to obj box [-1 .. +1 ]
virtual void ScreenUV(Point2& uv, Point2 &duv) {uv.Set(0,0); duv.Set(0,0); } // screen relative uv (from lower left)
virtual IPoint2 ScreenCoord() { return IPoint2(0,0); } // integer screen coordinate (from upper left)
virtual Point3 UVW(int channel=0) { return Point3(0,0,0); } // return UVW coords for point
virtual Point3 DUVW(int channel=0) { return Point3(0,0,0); } // return UVW derivs for point
virtual void DPdUVW(Point3 dP[3],int channel=0) { dP[0] = dP[1] = dP[2] = Point3(0,0,0); } // Bump vectors for UVW (camera space)
virtual void GetBGColor(Color &bgcol, Color& transp, BOOL fogBG=TRUE) { bgcol.Black(); transp.Black(); } // returns Background color, bg transparency
virtual Point3 PointTo(const Point3& p, RefFrame ito) { return p; }
virtual Point3 PointFrom(const Point3& p, RefFrame ifrom) { return p; }
virtual Point3 VectorTo(const Point3& p, RefFrame ito) { return p; }
virtual Point3 VectorFrom(const Point3& p, RefFrame ifrom) { return p; }
};
inline Point3 plMaxLightContext::PObjRelBox(void)
{
Point3 q;
Point3 p = PObj();
Box3 b = ObjectBox();
q.x = 2.0f*(p.x-b.pmin.x)/(b.pmax.x-b.pmin.x) - 1.0f;
q.y = 2.0f*(p.y-b.pmin.y)/(b.pmax.y-b.pmin.y) - 1.0f;
q.z = 2.0f*(p.z-b.pmin.z)/(b.pmax.z-b.pmin.z) - 1.0f;
return q;
}
class plMaxRendContext : public RendContext
{
public:
Matrix3 WorldToCam() const { return Matrix3(1); }
Color GlobalLightLevel() const { return Color(1.f, 1.f, 1.f); }
int Progress(int done, int total) {
return 1;
}
};
#endif // plMaxLightContext_inc
/*==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 <http://www.gnu.org/licenses/>.
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 plMaxLightContext_inc
#define plMaxLightContext_inc
#include "hsGeometry3.h"
class plMaxLightContext : public ShadeContext
{
protected:
TimeValue fCurrentTime;
Box3 fBounds;
Point3 fPos;
Point3 fNorm;
Point3 fPertNorm;
public:
plMaxLightContext(const Box3& b, TimeValue t=0)
{
fBounds = b;
fCurrentTime = t;
doMaps = true;
filterMaps = true;
backFace = false;
xshadeID = 0;
mtlNum = 0;
}
void SetPoint(const Point3& p, const Point3& n) { fPos = p; fNorm = fPertNorm = n; } // Must be world space coming in.
void SetPoint(const hsPoint3& p, const hsVector3& n) { fPos = Point3(p.fX,p.fY,p.fZ); fNorm = fPertNorm = Point3(n.fX,n.fY,n.fZ); } // Must be world space coming in.
virtual BOOL InMtlEditor() { return false; } // is this rendering the mtl editor sample sphere?
virtual LightDesc* Light(int n) { return nil; } // get the nth light.
virtual TimeValue CurTime() { return fCurrentTime; } // current time value
virtual int FaceNumber() { return 0; }
virtual Point3 Normal() { return fPertNorm; } // interpolated surface normal, in cameara coords: affected by SetNormal()
virtual void SetNormal(Point3 p) { fPertNorm = p; } // used for perturbing normal
virtual Point3 OrigNormal() { return fNorm; } // original surface normal: not affected by SetNormal();
virtual Point3 GNormal() { return fNorm; } // geometric (face) normal
virtual Point3 V() { return Point3(0.f,1.f,0.f); } // Unit view vector: from camera towards P
virtual void SetView(Point3 p) { } // Set the view vector
virtual Point3 ReflectVector() { return V(); } // reflection vector
virtual Point3 RefractVector(float ior) { return V(); } // refraction vector
virtual Point3 CamPos() { return Point3(0,0,0); } // camera position
virtual Point3 P() { return fPos; } // point to be shaded;
virtual Point3 DP() { return Point3(0,0,0); } // deriv of P, relative to pixel, for AA
virtual Point3 PObj() { return P(); } // point in obj coords
virtual Point3 DPObj() { return DP(); } // deriv of PObj, rel to pixel, for AA
virtual Box3 ObjectBox() { return fBounds; } // Object extents box in obj coords
virtual Point3 PObjRelBox(); // Point rel to obj box [-1 .. +1 ]
virtual Point3 DPObjRelBox() { return Point3(0,0,0); } // deriv of Point rel to obj box [-1 .. +1 ]
virtual void ScreenUV(Point2& uv, Point2 &duv) {uv.Set(0,0); duv.Set(0,0); } // screen relative uv (from lower left)
virtual IPoint2 ScreenCoord() { return IPoint2(0,0); } // integer screen coordinate (from upper left)
virtual Point3 UVW(int channel=0) { return Point3(0,0,0); } // return UVW coords for point
virtual Point3 DUVW(int channel=0) { return Point3(0,0,0); } // return UVW derivs for point
virtual void DPdUVW(Point3 dP[3],int channel=0) { dP[0] = dP[1] = dP[2] = Point3(0,0,0); } // Bump vectors for UVW (camera space)
virtual void GetBGColor(Color &bgcol, Color& transp, BOOL fogBG=TRUE) { bgcol.Black(); transp.Black(); } // returns Background color, bg transparency
virtual Point3 PointTo(const Point3& p, RefFrame ito) { return p; }
virtual Point3 PointFrom(const Point3& p, RefFrame ifrom) { return p; }
virtual Point3 VectorTo(const Point3& p, RefFrame ito) { return p; }
virtual Point3 VectorFrom(const Point3& p, RefFrame ifrom) { return p; }
};
inline Point3 plMaxLightContext::PObjRelBox(void)
{
Point3 q;
Point3 p = PObj();
Box3 b = ObjectBox();
q.x = 2.0f*(p.x-b.pmin.x)/(b.pmax.x-b.pmin.x) - 1.0f;
q.y = 2.0f*(p.y-b.pmin.y)/(b.pmax.y-b.pmin.y) - 1.0f;
q.z = 2.0f*(p.z-b.pmin.z)/(b.pmax.z-b.pmin.z) - 1.0f;
return q;
}
class plMaxRendContext : public RendContext
{
public:
Matrix3 WorldToCam() const { return Matrix3(1); }
Color GlobalLightLevel() const { return Color(1.f, 1.f, 1.f); }
int Progress(int done, int total) {
return 1;
}
};
#endif // plMaxLightContext_inc

File diff suppressed because it is too large Load Diff

View File

@ -1,129 +1,129 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plMeshConverter Class Header //
// Static class that converts a Max triMesh object into the geometrySpans //
// necessary for a plDrawableIce object. //
// //
//// Version History /////////////////////////////////////////////////////////
// //
// Created 4.18.2001 mcn //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plMeshConverter_h
#define _plMeshConverter_h
#include "Max.h"
#include "HeadSpin.h"
#include "hsTemplates.h"
class plMaxNode;
class plErrorMsg;
class hsConverterUtils;
class plMaxNode;
class plGeometrySpan;
struct hsPoint3;
struct hsVector3;
struct hsMatrix44;
class ISkin;
class plConvexVolume;
class plMAXVertNormal;
class BitmapTex;
class hsGMaterial;
class plExportMaterialData;
//// Class Definition ////////////////////////////////////////////////////////
class plMeshConverter
{
private:
plMeshConverter();
static hsBool fWarnBadNormals;
static char fWarnBadNormalsMsg[];
static hsBool fWarnBadUVs;
static char fWarnBadUVsMsg[];
static hsBool fWarnSuspiciousUVs;
static char fWarnSuspiciousUVsMsg[];
static char fTooManyVertsMsg[];
static char fTooManyFacesMsg[];
public:
~plMeshConverter();
static plMeshConverter& Instance();
void Init( hsBool save, plErrorMsg *msg );
void DeInit( hsBool deInitLongRecur = true );
void StuffPositionsAndNormals(plMaxNode *node, hsTArray<hsPoint3> *pos, hsTArray<hsVector3> *normals);
plConvexVolume *CreateConvexVolume( plMaxNode *node );
// doPreshading - If true, do crappy flat shading now (since we won't do any shading later)
hsBool CreateSpans( plMaxNode *node, hsTArray<plGeometrySpan *> &spanArray, bool doPreshading );
private:
bool IValidateUVs(plMaxNode* node);
void ISetBumpUvs(Int16 uvChan, hsTArray<plMAXVertNormal>& vertDPosDuvCache, TVFace* tvFace, UInt32 smGroup,
hsPoint3* uvs1, hsPoint3* uvs2, hsPoint3* uvs3);
void ISetBumpUvSrcs(hsTArray<hsTArray<plExportMaterialData> *>& ourMaterials,
hsTArray<Int16>& bumpLayIdx, hsTArray<Int16>& bumpLayChan, hsTArray<Int16>& bumpDuChan, hsTArray<Int16>& bumpDvChan);
void ISetWaterDecEnvUvSrcs(hsTArray<hsTArray<plExportMaterialData> *>& ourMaterials,
hsTArray<Int16>& bumpLayIdx, hsTArray<Int16>& bumpLayChan, hsTArray<Int16>& bumpDuChan, hsTArray<Int16>& bumpDvChan);
void ISmoothUVGradients(plMaxNode* node, Mesh* mesh,
hsTArray<hsTArray<plExportMaterialData> *>& ourMaterials,
hsTArray<Int16>& bumpLayIdx, hsTArray<Int16>& bumpLayChan,
hsTArray<plMAXVertNormal>* vertDPosDuCache, hsTArray<plMAXVertNormal>* vertDPosDvCache);
Point3 IGetUvGradient(plMaxNode* node, const hsMatrix44& uvXform44, Int16 bmpUvwSrc,
Mesh *mesh, int faceIdx,
int iUV);
int IGenerateUVs( plMaxNode *node, Mtl *maxMtl, Mesh *mesh, int faceIdx, int numChan, int numBlend,
hsPoint3 *uvs1, hsPoint3 *uvs2, hsPoint3 *uvs3 );
void IGetUVTransform( plMaxNode *node, Mtl *mtl, Matrix3 *uvTransform, int which );
UInt32 ICreateHexColor( float r, float g, float b );
UInt32 ISetHexAlpha( UInt32 color, float alpha );
Mesh* IGetNodeMesh(plMaxNode *node);
void IDeleteTempGeometry();
Mesh* IDuplicate2Sided(plMaxNode *node, Mesh* mesh);
Interface *fInterface;
hsConverterUtils& fConverterUtils;
plErrorMsg *fErrorMsg;
hsBool fIsInitialized;
// Non-nil if we converted the MAX object and have to delete it when we're done
TriObject *fTriObjToDelete;
// Non-nil if we made a copy to mess with that we need to delete when we're done
Mesh *fMeshToDelete;
};
#endif // _plMeshConverter_h
/*==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 <http://www.gnu.org/licenses/>.
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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plMeshConverter Class Header //
// Static class that converts a Max triMesh object into the geometrySpans //
// necessary for a plDrawableIce object. //
// //
//// Version History /////////////////////////////////////////////////////////
// //
// Created 4.18.2001 mcn //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plMeshConverter_h
#define _plMeshConverter_h
#include "Max.h"
#include "HeadSpin.h"
#include "hsTemplates.h"
class plMaxNode;
class plErrorMsg;
class hsConverterUtils;
class plMaxNode;
class plGeometrySpan;
struct hsPoint3;
struct hsVector3;
struct hsMatrix44;
class ISkin;
class plConvexVolume;
class plMAXVertNormal;
class BitmapTex;
class hsGMaterial;
class plExportMaterialData;
//// Class Definition ////////////////////////////////////////////////////////
class plMeshConverter
{
private:
plMeshConverter();
static hsBool fWarnBadNormals;
static char fWarnBadNormalsMsg[];
static hsBool fWarnBadUVs;
static char fWarnBadUVsMsg[];
static hsBool fWarnSuspiciousUVs;
static char fWarnSuspiciousUVsMsg[];
static char fTooManyVertsMsg[];
static char fTooManyFacesMsg[];
public:
~plMeshConverter();
static plMeshConverter& Instance();
void Init( hsBool save, plErrorMsg *msg );
void DeInit( hsBool deInitLongRecur = true );
void StuffPositionsAndNormals(plMaxNode *node, hsTArray<hsPoint3> *pos, hsTArray<hsVector3> *normals);
plConvexVolume *CreateConvexVolume( plMaxNode *node );
// doPreshading - If true, do crappy flat shading now (since we won't do any shading later)
hsBool CreateSpans( plMaxNode *node, hsTArray<plGeometrySpan *> &spanArray, bool doPreshading );
private:
bool IValidateUVs(plMaxNode* node);
void ISetBumpUvs(Int16 uvChan, hsTArray<plMAXVertNormal>& vertDPosDuvCache, TVFace* tvFace, UInt32 smGroup,
hsPoint3* uvs1, hsPoint3* uvs2, hsPoint3* uvs3);
void ISetBumpUvSrcs(hsTArray<hsTArray<plExportMaterialData> *>& ourMaterials,
hsTArray<Int16>& bumpLayIdx, hsTArray<Int16>& bumpLayChan, hsTArray<Int16>& bumpDuChan, hsTArray<Int16>& bumpDvChan);
void ISetWaterDecEnvUvSrcs(hsTArray<hsTArray<plExportMaterialData> *>& ourMaterials,
hsTArray<Int16>& bumpLayIdx, hsTArray<Int16>& bumpLayChan, hsTArray<Int16>& bumpDuChan, hsTArray<Int16>& bumpDvChan);
void ISmoothUVGradients(plMaxNode* node, Mesh* mesh,
hsTArray<hsTArray<plExportMaterialData> *>& ourMaterials,
hsTArray<Int16>& bumpLayIdx, hsTArray<Int16>& bumpLayChan,
hsTArray<plMAXVertNormal>* vertDPosDuCache, hsTArray<plMAXVertNormal>* vertDPosDvCache);
Point3 IGetUvGradient(plMaxNode* node, const hsMatrix44& uvXform44, Int16 bmpUvwSrc,
Mesh *mesh, int faceIdx,
int iUV);
int IGenerateUVs( plMaxNode *node, Mtl *maxMtl, Mesh *mesh, int faceIdx, int numChan, int numBlend,
hsPoint3 *uvs1, hsPoint3 *uvs2, hsPoint3 *uvs3 );
void IGetUVTransform( plMaxNode *node, Mtl *mtl, Matrix3 *uvTransform, int which );
UInt32 ICreateHexColor( float r, float g, float b );
UInt32 ISetHexAlpha( UInt32 color, float alpha );
Mesh* IGetNodeMesh(plMaxNode *node);
void IDeleteTempGeometry();
Mesh* IDuplicate2Sided(plMaxNode *node, Mesh* mesh);
Interface *fInterface;
hsConverterUtils& fConverterUtils;
plErrorMsg *fErrorMsg;
hsBool fIsInitialized;
// Non-nil if we converted the MAX object and have to delete it when we're done
TriObject *fTriObjToDelete;
// Non-nil if we made a copy to mess with that we need to delete when we're done
Mesh *fMeshToDelete;
};
#endif // _plMeshConverter_h

View File

@ -1,205 +1,205 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#include "HeadSpin.h"
#include "Max.h"
#include "../MaxMain/plMaxNode.h"
#include "plRenderGlobalContext.h"
plRenderGlobalContext::plRenderGlobalContext(Interface* ip, TimeValue t)
{
fInterface = ip;
renderer = ip->GetProductionRenderer();
projType = PROJ_PERSPECTIVE;
devWidth = 640;
devHeight = 480;
xscale = 1.6f;
yscale = -1.6f;
xc = 320.f;
yc = 240.f;
antialias = 1;
camToWorld.IdentityMatrix();
worldToCam.IdentityMatrix();
nearRange = 0;
farRange = 10000.f;
devAspect = 1.f; // PIXEL aspect ratio of device pixel H/W
frameDur = 1.f;
envMap = nil;
globalLightLevel.White();
atmos = nil;
pToneOp = nil; // The tone operator, may be NULL
time = t;
wireMode = false; // wire frame render mode?
wire_thick = 1.f; // global wire thickness
force2Side = false; // is force two-sided rendering enabled
inMtlEdit = false; // rendering in mtl editor?
fieldRender = false; // are we rendering fields
first_field = 1; // is this the first field or the second?
field_order = 1; // which field is first: 0->even first, 1->odd first
objMotBlur = true; // is object motion blur enabled
nBlurFrames = 10; // number of object motion blur time slices
SetRenderElementMgr(ip->GetRenderElementMgr(RS_Production));
}
plRenderGlobalContext::~plRenderGlobalContext()
{
int i;
for( i = 0; i < fInstList.GetCount(); i++ )
{
fInstList[i].Cleanup();
}
}
void plRenderGlobalContext::Update(TimeValue t)
{
time = t;
int i;
for( i = 0; i < fInstList.GetCount(); i++ )
fInstList[i].Update(time);
}
void plRenderGlobalContext::MakeRenderInstances(plMaxNode* root, TimeValue t)
{
time = t;
int i;
for( i = 0; i < root->NumberOfChildren(); i++ )
IMakeRenderInstances((plMaxNode*)root->GetChildNode(i), t, false);
for( i = 0; i < fInstList.GetCount() - 1; i++ )
fInstList[i].SetNext(&fInstList[i+1]);
}
void plRenderGlobalContext::IMakeRenderInstances(plMaxNode* node, TimeValue t, hsBool isBarney)
{
const char* dbgNodeName = node->GetName();
if( !isBarney )
isBarney = node->GetIsBarney();
hsBool doMe = isBarney || (node->CanConvert() && node->GetDrawable());
if( !doMe )
return;
int idx = fInstList.GetCount();
plRenderInstance* inst = fInstList.Push();
if( !inst->GetFromNode(node, t, idx) )
fInstList.Pop();
int i;
for( i = 0; i < node->NumberOfChildren(); i++ )
IMakeRenderInstances((plMaxNode *)node->GetChildNode(i), t, isBarney);
}
void plRenderGlobalContext::IntersectRay(RenderInstance *inst, Ray& origRay, ISect &isct, ISectList &xplist, BOOL findExit)
{
const float kFarAway = 1.e5f;
Ray ray;
if( findExit )
{
ray.p = origRay.p + origRay.dir * kFarAway;
ray.dir = -ray.dir;
}
else
{
ray = origRay;
}
float at;
Point3 norm;
DWORD faceIdx;
Point3 bary;
int hit = inst->mesh->IntersectRay(ray, at, norm, faceIdx, bary);
if( hit )
{
ISect thisHit;
thisHit.t = findExit ? kFarAway - at : at;
thisHit.exit = findExit;
thisHit.backFace = findExit;
thisHit.inst = inst;
thisHit.fnum = faceIdx;
thisHit.bc = bary;
Point3 worldP = (ray.p + at * ray.dir);
thisHit.p = inst->GetINode()->GetObjectTM(time) * worldP;
thisHit.pc = worldToCam * thisHit.p;
thisHit.mtlNum = inst->mesh->faces[faceIdx].getMatID();
Mtl* mtl = inst->GetINode()->GetMtl();
thisHit.matreq = mtl ? mtl->Requirements(thisHit.mtlNum) : 0;
thisHit.next = nil;
if( thisHit.matreq & (MTLREQ_TRANSP | MTLREQ_ADDITIVE_TRANSP) )
{
// advance the ray and try again. This one goes in the xplist.
ISect* xHit = GetNewISect();
*xHit = thisHit;
xplist.Add(xHit);
const float kAdvanceHack = 0.5f;
Ray newRay;
newRay.p = origRay.p + origRay.dir * (thisHit.t + kAdvanceHack);
newRay.dir = origRay.dir;
IntersectRay(inst, newRay, isct, xplist, findExit);
}
else
{
xplist.Prune(thisHit.t);
isct = thisHit;
}
}
}
BOOL plRenderGlobalContext::IntersectWorld(Ray &ray, int skipID, ISect &hit, ISectList &xplist, int blurFrame)
{
hit.t = -1.f;
xplist.Init();
int i;
for( i = 0; i < fInstList.GetCount(); i++ )
{
if( skipID != i )
{
ISect thisHit;
hit.t = -1.f;
IntersectRay(&fInstList[i], ray, thisHit, xplist, false);
if( thisHit.t >= 0 )
{
if( (hit.t < 0) || (thisHit.t < hit.t) )
{
// grab our new winner.
hit = thisHit;
}
}
}
}
return (hit.t >= 0) || !xplist.IsEmpty();
}
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#include "HeadSpin.h"
#include "Max.h"
#include "../MaxMain/plMaxNode.h"
#include "plRenderGlobalContext.h"
plRenderGlobalContext::plRenderGlobalContext(Interface* ip, TimeValue t)
{
fInterface = ip;
renderer = ip->GetProductionRenderer();
projType = PROJ_PERSPECTIVE;
devWidth = 640;
devHeight = 480;
xscale = 1.6f;
yscale = -1.6f;
xc = 320.f;
yc = 240.f;
antialias = 1;
camToWorld.IdentityMatrix();
worldToCam.IdentityMatrix();
nearRange = 0;
farRange = 10000.f;
devAspect = 1.f; // PIXEL aspect ratio of device pixel H/W
frameDur = 1.f;
envMap = nil;
globalLightLevel.White();
atmos = nil;
pToneOp = nil; // The tone operator, may be NULL
time = t;
wireMode = false; // wire frame render mode?
wire_thick = 1.f; // global wire thickness
force2Side = false; // is force two-sided rendering enabled
inMtlEdit = false; // rendering in mtl editor?
fieldRender = false; // are we rendering fields
first_field = 1; // is this the first field or the second?
field_order = 1; // which field is first: 0->even first, 1->odd first
objMotBlur = true; // is object motion blur enabled
nBlurFrames = 10; // number of object motion blur time slices
SetRenderElementMgr(ip->GetRenderElementMgr(RS_Production));
}
plRenderGlobalContext::~plRenderGlobalContext()
{
int i;
for( i = 0; i < fInstList.GetCount(); i++ )
{
fInstList[i].Cleanup();
}
}
void plRenderGlobalContext::Update(TimeValue t)
{
time = t;
int i;
for( i = 0; i < fInstList.GetCount(); i++ )
fInstList[i].Update(time);
}
void plRenderGlobalContext::MakeRenderInstances(plMaxNode* root, TimeValue t)
{
time = t;
int i;
for( i = 0; i < root->NumberOfChildren(); i++ )
IMakeRenderInstances((plMaxNode*)root->GetChildNode(i), t, false);
for( i = 0; i < fInstList.GetCount() - 1; i++ )
fInstList[i].SetNext(&fInstList[i+1]);
}
void plRenderGlobalContext::IMakeRenderInstances(plMaxNode* node, TimeValue t, hsBool isBarney)
{
const char* dbgNodeName = node->GetName();
if( !isBarney )
isBarney = node->GetIsBarney();
hsBool doMe = isBarney || (node->CanConvert() && node->GetDrawable());
if( !doMe )
return;
int idx = fInstList.GetCount();
plRenderInstance* inst = fInstList.Push();
if( !inst->GetFromNode(node, t, idx) )
fInstList.Pop();
int i;
for( i = 0; i < node->NumberOfChildren(); i++ )
IMakeRenderInstances((plMaxNode *)node->GetChildNode(i), t, isBarney);
}
void plRenderGlobalContext::IntersectRay(RenderInstance *inst, Ray& origRay, ISect &isct, ISectList &xplist, BOOL findExit)
{
const float kFarAway = 1.e5f;
Ray ray;
if( findExit )
{
ray.p = origRay.p + origRay.dir * kFarAway;
ray.dir = -ray.dir;
}
else
{
ray = origRay;
}
float at;
Point3 norm;
DWORD faceIdx;
Point3 bary;
int hit = inst->mesh->IntersectRay(ray, at, norm, faceIdx, bary);
if( hit )
{
ISect thisHit;
thisHit.t = findExit ? kFarAway - at : at;
thisHit.exit = findExit;
thisHit.backFace = findExit;
thisHit.inst = inst;
thisHit.fnum = faceIdx;
thisHit.bc = bary;
Point3 worldP = (ray.p + at * ray.dir);
thisHit.p = inst->GetINode()->GetObjectTM(time) * worldP;
thisHit.pc = worldToCam * thisHit.p;
thisHit.mtlNum = inst->mesh->faces[faceIdx].getMatID();
Mtl* mtl = inst->GetINode()->GetMtl();
thisHit.matreq = mtl ? mtl->Requirements(thisHit.mtlNum) : 0;
thisHit.next = nil;
if( thisHit.matreq & (MTLREQ_TRANSP | MTLREQ_ADDITIVE_TRANSP) )
{
// advance the ray and try again. This one goes in the xplist.
ISect* xHit = GetNewISect();
*xHit = thisHit;
xplist.Add(xHit);
const float kAdvanceHack = 0.5f;
Ray newRay;
newRay.p = origRay.p + origRay.dir * (thisHit.t + kAdvanceHack);
newRay.dir = origRay.dir;
IntersectRay(inst, newRay, isct, xplist, findExit);
}
else
{
xplist.Prune(thisHit.t);
isct = thisHit;
}
}
}
BOOL plRenderGlobalContext::IntersectWorld(Ray &ray, int skipID, ISect &hit, ISectList &xplist, int blurFrame)
{
hit.t = -1.f;
xplist.Init();
int i;
for( i = 0; i < fInstList.GetCount(); i++ )
{
if( skipID != i )
{
ISect thisHit;
hit.t = -1.f;
IntersectRay(&fInstList[i], ray, thisHit, xplist, false);
if( thisHit.t >= 0 )
{
if( (hit.t < 0) || (thisHit.t < hit.t) )
{
// grab our new winner.
hit = thisHit;
}
}
}
}
return (hit.t >= 0) || !xplist.IsEmpty();
}

View File

@ -1,57 +1,57 @@
/*==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 <http://www.gnu.org/licenses/>.
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 plRenderGlobalContext_inc
#define plRenderGlobalContext_inc
#include "hsTemplates.h"
#include "plRenderInstance.h"
class plRenderGlobalContext : public RenderGlobalContext
{
protected:
Interface* fInterface;
hsTArray<plRenderInstance> fInstList;
void IMakeRenderInstances(plMaxNode* node, TimeValue t, hsBool isBarney);
public:
plRenderGlobalContext(Interface* ip, TimeValue t);
~plRenderGlobalContext();
void Update(TimeValue t);
void MakeRenderInstances(plMaxNode* root, TimeValue t);
virtual int NumRenderInstances() { return fInstList.GetCount(); }
virtual RenderInstance* GetRenderInstance( int i ) { return i < fInstList.GetCount() ? &fInstList[i] : nil; }
virtual void IntersectRay(RenderInstance *inst, Ray& ray, ISect &isct, ISectList &xpList, BOOL findExit);
virtual BOOL IntersectWorld(Ray &ray, int skipID, ISect &hit, ISectList &xplist, int blurFrame = NO_MOTBLUR);
};
#endif // plRenderGlobalContext_inc
/*==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 <http://www.gnu.org/licenses/>.
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 plRenderGlobalContext_inc
#define plRenderGlobalContext_inc
#include "hsTemplates.h"
#include "plRenderInstance.h"
class plRenderGlobalContext : public RenderGlobalContext
{
protected:
Interface* fInterface;
hsTArray<plRenderInstance> fInstList;
void IMakeRenderInstances(plMaxNode* node, TimeValue t, hsBool isBarney);
public:
plRenderGlobalContext(Interface* ip, TimeValue t);
~plRenderGlobalContext();
void Update(TimeValue t);
void MakeRenderInstances(plMaxNode* root, TimeValue t);
virtual int NumRenderInstances() { return fInstList.GetCount(); }
virtual RenderInstance* GetRenderInstance( int i ) { return i < fInstList.GetCount() ? &fInstList[i] : nil; }
virtual void IntersectRay(RenderInstance *inst, Ray& ray, ISect &isct, ISectList &xpList, BOOL findExit);
virtual BOOL IntersectWorld(Ray &ray, int skipID, ISect &hit, ISectList &xplist, int blurFrame = NO_MOTBLUR);
};
#endif // plRenderGlobalContext_inc

View File

@ -1,300 +1,300 @@
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#include "hsTypes.h"
#include "Max.h"
#include "plRenderInstance.h"
class plNilView : public View
{
public:
Point2 ViewToScreen(Point3 p) { return Point2(p.x,p.y); }
plNilView()
{
projType = 1;
fov = hsScalarPI * 0.25f;
pixelSize = 1.f;
affineTM.IdentityMatrix();
worldToView.IdentityMatrix();
screenW=640.0f; screenH = 480.0f;
}
};
static plNilView nilView;
plRenderInstance::plRenderInstance()
: fNext(nil),
fNode(nil),
fObject(nil),
fDeleteMesh(false)
{
mtl = nil;
mesh = nil;
flags = 0;
wireSize = 1.f;
vis = 1.f;
nodeID = 0;
objMotBlurFrame = 0;
objBlurID = 0;
objToWorld.IdentityMatrix();
objToCam.IdentityMatrix();
normalObjToCam.IdentityMatrix();
camToObj.IdentityMatrix();
obBox.Init();
center = Point3(0,0,0);
radsq = 0;
}
plRenderInstance::~plRenderInstance()
{
}
void plRenderInstance::Cleanup()
{
if( mesh && fDeleteMesh )
{
mesh->DeleteThis();
mesh = nil;
fDeleteMesh = false;
}
}
BOOL plRenderInstance::Update(TimeValue& t)
{
fObject = fNode->EvalWorldState(t).obj;
if( !fObject )
return false;
// this shouldn't happen, we shouldn't be trying to make
// renderinstances from non GEOMOBJECT's
if( fObject->SuperClassID() != GEOMOBJECT_CLASS_ID )
return false;
if( mesh && fDeleteMesh )
{
mesh->DeleteThis();
mesh = nil;
}
fDeleteMesh = false;
mesh = ((GeomObject*)fObject)->GetRenderMesh(t, fNode, nilView, fDeleteMesh);
if( !mesh )
return false;
vis = fNode->GetVisibility(t);
if( vis < 0.0f )
{
vis = 0.0f;
SetFlag(INST_HIDE, 1);
return false;
}
if (vis > 1.0f) vis = 1.0f;
SetFlag(INST_HIDE, 0);
objMotBlurFrame = NO_MOTBLUR;
objBlurID = 0;
objToWorld = fNode->GetObjectTM(t);
objToCam = objToWorld;
camToObj = Inverse(objToCam);
normalObjToCam.IdentityMatrix();
Matrix3 inv = camToObj;
int i;
for( i = 0; i < 3; i++ )
normalObjToCam.SetRow(i, inv.GetColumn3(i));
obBox = mesh->getBoundingBox(nil);
center = obBox.Center();
radsq = LengthSquared(obBox.Width());
return true;
}
BOOL plRenderInstance::GetFromNode(INode* node, TimeValue& t, int idx)
{
fNext = nil;
fValid = Interval(t, t);
fNode = node;
mtl = node->GetMtl();
if( mtl )
{
wireSize = mtl->WireSize();
}
nodeID = idx;
ClearLights();
return Update(t);
}
BOOL plRenderInstance::CastsShadowsFrom(const ObjLightDesc& constLt)
{
ObjLightDesc& lt = const_cast<ObjLightDesc&>(constLt);
if( !fNode->CastShadows() )
return false;
if( !lt.ls.shadow )
return false;
if( lt.GetExclList() && lt.GetExclList()->TestFlag(NT_AFFECT_SHADOWCAST) )
{
int idx = lt.GetExclList()->FindNode(fNode);
BOOL isInc = lt.GetExclList()->TestFlag(NT_INCLUDE);
if( idx >= 0 )
{
return isInc;
}
else
{
return !isInc;
}
}
return true;
}
Point3 plRenderInstance::GetFaceNormal(int fnum)
{
Face* f = &mesh->faces[fnum];
Point3 a = GetCamVert(f->v[1]) - GetCamVert(f->v[0]);
Point3 b = GetCamVert(f->v[2]) - GetCamVert(f->v[0]);
Point3 n = CrossProd(a, b).Normalize();
return n;
}
Point3 plRenderInstance::GetFaceVertNormal(int fnum, int vertNum)
{
Point3 retNorm;
int smGroup=0;
Face* f = &mesh->faces[fnum];
// Get the rendered vertex. Don't use the device position, fPos.
RVertex &rv = mesh->getRVert(f->v[vertNum]);
// Number of normals at the vertex
int numNormalsAtVert = (rv.rFlags & NORCT_MASK);
// Specified normal ?
int specNrml = (rv.rFlags & SPECIFIED_NORMAL);
if (specNrml || (numNormalsAtVert == 1))
{
// The normal case is one normal per vertex (a vertex not beng shared by more than one smoothing group)
// We'll assign vertex normals here.
// If the object is faceted, this will be the same as the face normal.
retNorm = rv.rn.getNormal();
}
else
{
int found = 0;
for(int j=0;j<numNormalsAtVert; j++)
{
smGroup = rv.ern[j].getSmGroup();
// Since this vertex is shared by more than one smoothing group, it has multiple normals.
// This is fairly rare and doesn't occur in faceted objects.
// Just pick the first normal and use that as the vertex normal.
int faceSmGroup = f->getSmGroup();
if ((smGroup & faceSmGroup) == faceSmGroup)
{
retNorm = rv.ern[j].getNormal();
found++;
// NOTE: Remove this to really check smoothing groups
break;
}
}
}
retNorm = retNorm * normalObjToCam;
retNorm.Normalize();
return retNorm;
}
Point3 plRenderInstance::GetCamVert(int vertnum)
{
return objToCam*mesh->verts[vertnum];
}
void plRenderInstance::GetObjVerts(int fnum, Point3 obp[3])
{
Face* f = &mesh->faces[fnum];
obp[0] = mesh->verts[f->v[0]];
obp[1] = mesh->verts[f->v[1]];
obp[2] = mesh->verts[f->v[2]];
}
void plRenderInstance::GetCamVerts(int fnum, Point3 cp[3])
{
Face* f = &mesh->faces[fnum];
cp[0] = objToCam*mesh->verts[f->v[0]];
cp[1] = objToCam*mesh->verts[f->v[1]];
cp[2] = objToCam*mesh->verts[f->v[2]];
}
Mtl* plRenderInstance::GetMtl(int fnum)
{
if( !mtl )
return nil;
if( TestFlag(INST_MTL_BYFACE) )
{
if( mtl->ClassID() != Class_ID(MULTI_CLASS_ID,0) )
return mtl;
Face* f = &mesh->faces[fnum];
int matIndex = f->getMatID();
return mtl->GetSubMtl(matIndex);
}
else
{
return mtl;
}
}
ULONG plRenderInstance::MtlRequirements(int mtlNum, int faceNum)
{
if( !mtl )
return 0;
if( TestFlag(INST_MTL_BYFACE) )
{
Mtl* faceMtl = GetMtl(faceNum);
return faceMtl ? faceMtl->Requirements(mtlNum) : 0;
}
return mtl->Requirements(mtlNum);
/*==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 <http://www.gnu.org/licenses/>.
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==*/
#include "hsTypes.h"
#include "Max.h"
#include "plRenderInstance.h"
class plNilView : public View
{
public:
Point2 ViewToScreen(Point3 p) { return Point2(p.x,p.y); }
plNilView()
{
projType = 1;
fov = hsScalarPI * 0.25f;
pixelSize = 1.f;
affineTM.IdentityMatrix();
worldToView.IdentityMatrix();
screenW=640.0f; screenH = 480.0f;
}
};
static plNilView nilView;
plRenderInstance::plRenderInstance()
: fNext(nil),
fNode(nil),
fObject(nil),
fDeleteMesh(false)
{
mtl = nil;
mesh = nil;
flags = 0;
wireSize = 1.f;
vis = 1.f;
nodeID = 0;
objMotBlurFrame = 0;
objBlurID = 0;
objToWorld.IdentityMatrix();
objToCam.IdentityMatrix();
normalObjToCam.IdentityMatrix();
camToObj.IdentityMatrix();
obBox.Init();
center = Point3(0,0,0);
radsq = 0;
}
plRenderInstance::~plRenderInstance()
{
}
void plRenderInstance::Cleanup()
{
if( mesh && fDeleteMesh )
{
mesh->DeleteThis();
mesh = nil;
fDeleteMesh = false;
}
}
BOOL plRenderInstance::Update(TimeValue& t)
{
fObject = fNode->EvalWorldState(t).obj;
if( !fObject )
return false;
// this shouldn't happen, we shouldn't be trying to make
// renderinstances from non GEOMOBJECT's
if( fObject->SuperClassID() != GEOMOBJECT_CLASS_ID )
return false;
if( mesh && fDeleteMesh )
{
mesh->DeleteThis();
mesh = nil;
}
fDeleteMesh = false;
mesh = ((GeomObject*)fObject)->GetRenderMesh(t, fNode, nilView, fDeleteMesh);
if( !mesh )
return false;
vis = fNode->GetVisibility(t);
if( vis < 0.0f )
{
vis = 0.0f;
SetFlag(INST_HIDE, 1);
return false;
}
if (vis > 1.0f) vis = 1.0f;
SetFlag(INST_HIDE, 0);
objMotBlurFrame = NO_MOTBLUR;
objBlurID = 0;
objToWorld = fNode->GetObjectTM(t);
objToCam = objToWorld;
camToObj = Inverse(objToCam);
normalObjToCam.IdentityMatrix();
Matrix3 inv = camToObj;
int i;
for( i = 0; i < 3; i++ )
normalObjToCam.SetRow(i, inv.GetColumn3(i));
obBox = mesh->getBoundingBox(nil);
center = obBox.Center();
radsq = LengthSquared(obBox.Width());
return true;
}
BOOL plRenderInstance::GetFromNode(INode* node, TimeValue& t, int idx)
{
fNext = nil;
fValid = Interval(t, t);
fNode = node;
mtl = node->GetMtl();
if( mtl )
{
wireSize = mtl->WireSize();
}
nodeID = idx;
ClearLights();
return Update(t);
}
BOOL plRenderInstance::CastsShadowsFrom(const ObjLightDesc& constLt)
{
ObjLightDesc& lt = const_cast<ObjLightDesc&>(constLt);
if( !fNode->CastShadows() )
return false;
if( !lt.ls.shadow )
return false;
if( lt.GetExclList() && lt.GetExclList()->TestFlag(NT_AFFECT_SHADOWCAST) )
{
int idx = lt.GetExclList()->FindNode(fNode);
BOOL isInc = lt.GetExclList()->TestFlag(NT_INCLUDE);
if( idx >= 0 )
{
return isInc;
}
else
{
return !isInc;
}
}
return true;
}
Point3 plRenderInstance::GetFaceNormal(int fnum)
{
Face* f = &mesh->faces[fnum];
Point3 a = GetCamVert(f->v[1]) - GetCamVert(f->v[0]);
Point3 b = GetCamVert(f->v[2]) - GetCamVert(f->v[0]);
Point3 n = CrossProd(a, b).Normalize();
return n;
}
Point3 plRenderInstance::GetFaceVertNormal(int fnum, int vertNum)
{
Point3 retNorm;
int smGroup=0;
Face* f = &mesh->faces[fnum];
// Get the rendered vertex. Don't use the device position, fPos.
RVertex &rv = mesh->getRVert(f->v[vertNum]);
// Number of normals at the vertex
int numNormalsAtVert = (rv.rFlags & NORCT_MASK);
// Specified normal ?
int specNrml = (rv.rFlags & SPECIFIED_NORMAL);
if (specNrml || (numNormalsAtVert == 1))
{
// The normal case is one normal per vertex (a vertex not beng shared by more than one smoothing group)
// We'll assign vertex normals here.
// If the object is faceted, this will be the same as the face normal.
retNorm = rv.rn.getNormal();
}
else
{
int found = 0;
for(int j=0;j<numNormalsAtVert; j++)
{
smGroup = rv.ern[j].getSmGroup();
// Since this vertex is shared by more than one smoothing group, it has multiple normals.
// This is fairly rare and doesn't occur in faceted objects.
// Just pick the first normal and use that as the vertex normal.
int faceSmGroup = f->getSmGroup();
if ((smGroup & faceSmGroup) == faceSmGroup)
{
retNorm = rv.ern[j].getNormal();
found++;
// NOTE: Remove this to really check smoothing groups
break;
}
}
}
retNorm = retNorm * normalObjToCam;
retNorm.Normalize();
return retNorm;
}
Point3 plRenderInstance::GetCamVert(int vertnum)
{
return objToCam*mesh->verts[vertnum];
}
void plRenderInstance::GetObjVerts(int fnum, Point3 obp[3])
{
Face* f = &mesh->faces[fnum];
obp[0] = mesh->verts[f->v[0]];
obp[1] = mesh->verts[f->v[1]];
obp[2] = mesh->verts[f->v[2]];
}
void plRenderInstance::GetCamVerts(int fnum, Point3 cp[3])
{
Face* f = &mesh->faces[fnum];
cp[0] = objToCam*mesh->verts[f->v[0]];
cp[1] = objToCam*mesh->verts[f->v[1]];
cp[2] = objToCam*mesh->verts[f->v[2]];
}
Mtl* plRenderInstance::GetMtl(int fnum)
{
if( !mtl )
return nil;
if( TestFlag(INST_MTL_BYFACE) )
{
if( mtl->ClassID() != Class_ID(MULTI_CLASS_ID,0) )
return mtl;
Face* f = &mesh->faces[fnum];
int matIndex = f->getMatID();
return mtl->GetSubMtl(matIndex);
}
else
{
return mtl;
}
}
ULONG plRenderInstance::MtlRequirements(int mtlNum, int faceNum)
{
if( !mtl )
return 0;
if( TestFlag(INST_MTL_BYFACE) )
{
Mtl* faceMtl = GetMtl(faceNum);
return faceMtl ? faceMtl->Requirements(mtlNum) : 0;
}
return mtl->Requirements(mtlNum);
}

View File

@ -1,87 +1,87 @@
/*==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 <http://www.gnu.org/licenses/>.
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 plRenderInstance_inc
#define plRenderInstance_inc
#include "hsTemplates.h"
class plRenderInstance : public RenderInstance
{
protected:
plRenderInstance* fNext;
Interval fValid;
INode* fNode;
Object* fObject;
BOOL fDeleteMesh;
hsTArray<LightDesc*> fLights;
public:
plRenderInstance();
virtual ~plRenderInstance();
BOOL GetFromNode(INode* node, TimeValue& t, int idx);
BOOL Update(TimeValue& t);
void SetNext(plRenderInstance* n) { fNext = n; }
void Cleanup();
virtual RenderInstance *Next() { return fNext; } // next in list
virtual Interval MeshValidity() { return fValid; }
virtual int NumLights() { return fLights.GetCount(); }
virtual LightDesc *Light(int n) { return fLights[n]; }
virtual void AddLight(LightDesc* l) { fLights.Append(l); }
virtual void ClearLights() { fLights.SetCount(0); }
virtual BOOL CastsShadowsFrom(const ObjLightDesc& lt); // is lt shadowed by this instance?
virtual INode *GetINode() { return fNode; } // get INode for instance
virtual Object *GetEvalObject() { return fObject; } // evaluated object for instance
virtual Point3 GetFaceNormal(int faceNum); // geometric normal in camera coords
virtual Point3 GetFaceVertNormal(int faceNum, int vertNum); // camera coords
virtual void GetFaceVertNormals(int faceNum, Point3 n[3]) // camera coords
{
n[0] = GetFaceVertNormal(faceNum, 0);
n[1] = GetFaceVertNormal(faceNum, 1);
n[2] = GetFaceVertNormal(faceNum, 2);
}
virtual Point3 GetCamVert(int vertnum); // coord for vertex in camera coords
virtual void GetObjVerts(int fnum, Point3 obp[3]); // vertices of face in object coords
virtual void GetCamVerts(int fnum, Point3 cp[3]); // vertices of face in camera(view) coords
// Material-by-face access
// Objects can provide a material as a function of face number via the IChkMtlAPI interface (chkmtlapi.h).
// This method will return RenderInstance::mtl if flag INST_MTL_BYFACE is not set. If INST_MTL_BYFACE is
// set it will return the proper by-face mtl. // DS 4/3/00
virtual Mtl *GetMtl(int faceNum);
virtual ULONG MtlRequirements(int mtlNum, int faceNum); // node's mtl requirements. DS 3/31/00: added faceNum to support mtl-per-face objects
};
#endif // plRenderInstance_inc
/*==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 <http://www.gnu.org/licenses/>.
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 plRenderInstance_inc
#define plRenderInstance_inc
#include "hsTemplates.h"
class plRenderInstance : public RenderInstance
{
protected:
plRenderInstance* fNext;
Interval fValid;
INode* fNode;
Object* fObject;
BOOL fDeleteMesh;
hsTArray<LightDesc*> fLights;
public:
plRenderInstance();
virtual ~plRenderInstance();
BOOL GetFromNode(INode* node, TimeValue& t, int idx);
BOOL Update(TimeValue& t);
void SetNext(plRenderInstance* n) { fNext = n; }
void Cleanup();
virtual RenderInstance *Next() { return fNext; } // next in list
virtual Interval MeshValidity() { return fValid; }
virtual int NumLights() { return fLights.GetCount(); }
virtual LightDesc *Light(int n) { return fLights[n]; }
virtual void AddLight(LightDesc* l) { fLights.Append(l); }
virtual void ClearLights() { fLights.SetCount(0); }
virtual BOOL CastsShadowsFrom(const ObjLightDesc& lt); // is lt shadowed by this instance?
virtual INode *GetINode() { return fNode; } // get INode for instance
virtual Object *GetEvalObject() { return fObject; } // evaluated object for instance
virtual Point3 GetFaceNormal(int faceNum); // geometric normal in camera coords
virtual Point3 GetFaceVertNormal(int faceNum, int vertNum); // camera coords
virtual void GetFaceVertNormals(int faceNum, Point3 n[3]) // camera coords
{
n[0] = GetFaceVertNormal(faceNum, 0);
n[1] = GetFaceVertNormal(faceNum, 1);
n[2] = GetFaceVertNormal(faceNum, 2);
}
virtual Point3 GetCamVert(int vertnum); // coord for vertex in camera coords
virtual void GetObjVerts(int fnum, Point3 obp[3]); // vertices of face in object coords
virtual void GetCamVerts(int fnum, Point3 cp[3]); // vertices of face in camera(view) coords
// Material-by-face access
// Objects can provide a material as a function of face number via the IChkMtlAPI interface (chkmtlapi.h).
// This method will return RenderInstance::mtl if flag INST_MTL_BYFACE is not set. If INST_MTL_BYFACE is
// set it will return the proper by-face mtl. // DS 4/3/00
virtual Mtl *GetMtl(int faceNum);
virtual ULONG MtlRequirements(int mtlNum, int faceNum); // node's mtl requirements. DS 3/31/00: added faceNum to support mtl-per-face objects
};
#endif // plRenderInstance_inc