You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2103 lines
61 KiB
2103 lines
61 KiB
/*==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/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
#include "HeadSpin.h" |
|
#include "plRealTimeLightBase.h" |
|
#include "iparamm2.h" |
|
#include "resource.h" |
|
#include "decomp.h" |
|
#include "hsv.h" |
|
#include "target.h" |
|
#include "../MaxPlasmaMtls/Layers/plLayerTex.h" |
|
#include "../MaxPlasmaMtls/Layers/plLayerTexBitmapPB.h" |
|
|
|
|
|
static int GetTargetPoint(TimeValue t, INode *inode, Point3& p) |
|
{ |
|
Matrix3 tmat; |
|
if (inode->GetTargetTM(t,tmat)) |
|
{ |
|
p = tmat.GetTrans(); |
|
return 1; |
|
} |
|
else |
|
return 0; |
|
} |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
//// plBaseLightProc Functions //////////////////////////////////////////////// |
|
/////////////////////////////////////////////////////////////////////////////// |
|
// This class provides the base functionality for all the dialog procs for |
|
// the ParamBlock rollouts for each light |
|
|
|
void plBaseLightProc::ILoadComboBox( HWND hComboBox, const char *names[] ) |
|
{ |
|
SendMessage(hComboBox, CB_RESETCONTENT, 0, 0); |
|
for (int i = 0; names[i]; i++) |
|
SendMessage(hComboBox, CB_ADDSTRING, 0, (LPARAM)names[i]); |
|
SendMessage(hComboBox, CB_SETCURSEL, 0, 0); |
|
} |
|
|
|
void plBaseLightProc::IBuildLightMesh( plRTLightBase *base, float coneSize ) |
|
{ |
|
base->BuildSpotMesh( coneSize ); |
|
base->fMesh = base->spotMesh; |
|
} |
|
|
|
BOOL plBaseLightProc::DlgProc( TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) |
|
{ |
|
IParamBlock2 *pb = map->GetParamBlock(); |
|
plRTLightBase *gl = (plRTLightBase *) pb->GetOwner(); |
|
|
|
|
|
switch( msg ) |
|
{ |
|
case WM_INITDIALOG: |
|
{ |
|
HWND DecayTypeCombo = GetDlgItem(hWnd, IDC_LIGHT_DECAY); |
|
HWND ShadowStateCombo = GetDlgItem(hWnd, IDC_SHADOW_TYPE); |
|
|
|
map->Invalidate(plRTLightBase::kProjMapTexButton); |
|
} |
|
break; |
|
|
|
case WM_COMMAND: |
|
break; |
|
} |
|
return false; |
|
} |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
//// plLightTexPBAccessor Class Functions ///////////////////////////////////// |
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
|
plLightTexPBAccessor plLightTexPBAccessor::fAccessor; |
|
|
|
void plLightTexPBAccessor::Set( PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t ) |
|
{ |
|
plRTLightBase* Obj = (plRTLightBase*)owner; |
|
IParamBlock2 *pb = Obj->fLightPB; |
|
|
|
switch (id) |
|
{ |
|
case plRTLightBase::kProjMapTexButton: |
|
if (1) //(val.bm)->bm) |
|
{ |
|
if (pb->GetMap()) |
|
pb->GetMap()->Invalidate(plRTLightBase::kProjMapTexButton); |
|
//pb->SetValue(plRTLightBase::kProjMapTexButton, Obj->fIP->GetTime(), val.bm); |
|
PBBitmap* ThisMap = val.bm; |
|
Obj->SetProjMap(&ThisMap->bi); |
|
break; |
|
} |
|
default: |
|
break; |
|
|
|
} |
|
} |
|
|
|
void plLightTexPBAccessor::Get( PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid ) |
|
{ |
|
} |
|
|
|
|
|
//////////////////////////////////////////////////////////// |
|
// |
|
// Mouse creation callback class for this plug-in |
|
|
|
class RTLightMouseCallBack : public CreateMouseCallBack |
|
{ |
|
plRTLightBase *ob; |
|
public: |
|
int proc(ViewExp *vpt, int msg, int point, int flags, IPoint2 m, Matrix3 &mat); |
|
void SetObj(plRTLightBase *obj) { ob = obj; } |
|
}; |
|
static RTLightMouseCallBack gRTMouseCallback; |
|
|
|
|
|
int RTLightMouseCallBack::proc(ViewExp *vpt, int msg, int point, int flags, IPoint2 m, Matrix3 &mat) |
|
{ |
|
switch (msg) |
|
{ |
|
case MOUSE_POINT: |
|
case MOUSE_MOVE: |
|
switch (point) |
|
{ |
|
case 0: |
|
mat.SetTrans(vpt->SnapPoint(m,m,NULL,SNAP_IN_PLANE)); |
|
break; |
|
|
|
case 1: |
|
mat.SetTrans(vpt->SnapPoint(m,m,NULL,SNAP_IN_PLANE)); |
|
if (msg == MOUSE_POINT) |
|
return 0; |
|
break; |
|
} |
|
break; |
|
|
|
case MOUSE_ABORT: |
|
return CREATE_ABORT; |
|
} |
|
|
|
return CREATE_CONTINUE; |
|
} |
|
|
|
static RTLightMouseCallBack sRTBaseLgtCreateCB; |
|
|
|
CreateMouseCallBack* plRTLightBase::GetCreateMouseCallBack() |
|
{ |
|
sRTBaseLgtCreateCB.SetObj(this); |
|
|
|
return &sRTBaseLgtCreateCB; |
|
} |
|
///////////////////////////////////////////////////////////////////////////// |
|
|
|
#if 0 |
|
plRTLightBase::plRTLightBase() : fIP(nil), fClassDesc(nil), fLightPB(nil) |
|
{ |
|
fColor = Color(0.5f, 0.5f, 1.f); |
|
} |
|
#endif |
|
|
|
|
|
|
|
void plRTLightBase::SetHSVColor(TimeValue t, Point3 &hsv) |
|
{ |
|
DWORD rgb = HSVtoRGB ((int)(hsv[0]*255.0f), (int)(hsv[1]*255.0f), (int)(hsv[2]*255.0f)); |
|
Point3 temp = fLightPB->GetPoint3(kLightColor, t); |
|
Point3 rgbf; |
|
rgbf[0] = temp.x / 255.0f; |
|
rgbf[1] = temp.y / 255.0f; |
|
rgbf[2] = temp.z / 255.0f; |
|
SetRGBColor(t, rgbf); |
|
} |
|
|
|
|
|
Point3 plRTLightBase::GetHSVColor(TimeValue t, Interval& b) |
|
{ |
|
int h, s, v; |
|
Point3 rgbf = GetRGBColor(t, b); |
|
DWORD rgb = RGB((int)(rgbf[0]*255.0f), (int)(rgbf[1]*255.0f), (int)(rgbf[2]*255.0f)); |
|
RGBtoHSV (rgb, &h, &s, &v); |
|
return Point3(h/255.0f, s/255.0f, v/255.0f); |
|
|
|
|
|
} |
|
|
|
#define FZ (0.0f) |
|
|
|
#define SET_QUAD(face, v0, v1, v2, v3) \ |
|
staticMesh[RT_OMNI +1].faces[face].setVerts(v0, v1, v2); \ |
|
staticMesh[RT_OMNI +1].faces[face].setEdgeVisFlags(1,1,0); \ |
|
staticMesh[RT_OMNI +1].faces[face+1].setVerts(v0, v2, v3); \ |
|
staticMesh[RT_OMNI +1].faces[face+1].setEdgeVisFlags(0,1,1); |
|
|
|
void plRTLightBase::BuildStaticMeshes() |
|
{ |
|
if(!meshBuilt) { |
|
int nverts = 6; |
|
int nfaces = 8; |
|
// Build a leetle octahedron |
|
staticMesh[RT_OMNI].setNumVerts(nverts); |
|
staticMesh[RT_OMNI].setNumFaces(nfaces); |
|
float s = 8.0f; |
|
staticMesh[RT_OMNI].setVert(0, Point3( FZ,FZ, -s)); |
|
staticMesh[RT_OMNI].setVert(1, Point3( s, FZ, FZ)); |
|
staticMesh[RT_OMNI].setVert(2, Point3( FZ, s, FZ)); |
|
staticMesh[RT_OMNI].setVert(3, Point3(-s, FZ, FZ)); |
|
staticMesh[RT_OMNI].setVert(4, Point3( FZ,-s, FZ)); |
|
staticMesh[RT_OMNI].setVert(5, Point3( FZ,FZ, s)); |
|
staticMesh[RT_OMNI].faces[0].setVerts(0,1,4); |
|
staticMesh[RT_OMNI].faces[1].setVerts(0,4,3); |
|
staticMesh[RT_OMNI].faces[2].setVerts(0,3,2); |
|
staticMesh[RT_OMNI].faces[3].setVerts(0,2,1); |
|
staticMesh[RT_OMNI].faces[4].setVerts(5,1,2); |
|
staticMesh[RT_OMNI].faces[5].setVerts(5,2,3); |
|
staticMesh[RT_OMNI].faces[6].setVerts(5,3,4); |
|
staticMesh[RT_OMNI].faces[7].setVerts(5,4,1); |
|
for (int i=0; i<nfaces; i++) { |
|
staticMesh[RT_OMNI].faces[i].setSmGroup(i); |
|
staticMesh[RT_OMNI].faces[i].setEdgeVisFlags(1,1,1); |
|
} |
|
staticMesh[RT_OMNI].buildNormals(); |
|
staticMesh[RT_OMNI].EnableEdgeList(1); |
|
|
|
// Build an "arrow" |
|
nverts = 13; |
|
nfaces = 16; |
|
staticMesh[RT_OMNI+1].setNumVerts(nverts); |
|
staticMesh[RT_OMNI+1].setNumFaces(nfaces); |
|
s = 4.0f; |
|
float s4 = 16.0f; |
|
staticMesh[RT_OMNI+1].setVert( 0, Point3( -s,-s, FZ)); |
|
staticMesh[RT_OMNI+1].setVert( 1, Point3( s,-s, FZ)); |
|
staticMesh[RT_OMNI+1].setVert( 2, Point3( s, s, FZ)); |
|
staticMesh[RT_OMNI+1].setVert( 3, Point3( -s, s, FZ)); |
|
staticMesh[RT_OMNI+1].setVert( 4, Point3( -s,-s, -s4)); |
|
staticMesh[RT_OMNI+1].setVert( 5, Point3( s,-s, -s4)); |
|
staticMesh[RT_OMNI+1].setVert( 6, Point3( s, s, -s4)); |
|
staticMesh[RT_OMNI+1].setVert( 7, Point3( -s, s, -s4)); |
|
s *= (float)2.0; |
|
staticMesh[RT_OMNI+1].setVert( 8, Point3( -s,-s, -s4)); |
|
staticMesh[RT_OMNI+1].setVert( 9, Point3( s,-s, -s4)); |
|
staticMesh[RT_OMNI+1].setVert(10, Point3( s, s, -s4)); |
|
staticMesh[RT_OMNI+1].setVert(11, Point3( -s, s, -s4)); |
|
staticMesh[RT_OMNI+1].setVert(12, Point3( FZ,FZ, -s4-s)); |
|
SET_QUAD( 0, 1, 0, 4, 5); |
|
SET_QUAD( 2, 0, 3, 7, 4); |
|
SET_QUAD( 4, 3, 2, 6, 7); |
|
SET_QUAD( 6, 2, 1, 5, 6); |
|
SET_QUAD( 8, 0, 1, 2, 3); |
|
SET_QUAD(10, 8, 9, 10, 11); |
|
staticMesh[RT_OMNI+1].faces[12].setVerts(8,12,9); |
|
staticMesh[RT_OMNI+1].faces[12].setEdgeVisFlags(1,1,1); |
|
staticMesh[RT_OMNI+1].faces[13].setVerts(9,12,10); |
|
staticMesh[RT_OMNI+1].faces[13].setEdgeVisFlags(1,1,1); |
|
staticMesh[RT_OMNI+1].faces[14].setVerts(10,12,11); |
|
staticMesh[RT_OMNI+1].faces[14].setEdgeVisFlags(1,1,1); |
|
staticMesh[RT_OMNI+1].faces[15].setVerts(11,12,8); |
|
staticMesh[RT_OMNI+1].faces[15].setEdgeVisFlags(1,1,1); |
|
for (int i=0; i<nfaces; i++) |
|
staticMesh[RT_OMNI+1].faces[i].setSmGroup(i); |
|
staticMesh[RT_OMNI+1].buildNormals(); |
|
staticMesh[RT_OMNI+1].EnableEdgeList(1); |
|
|
|
meshBuilt = 1; |
|
} |
|
} |
|
|
|
|
|
void plRTLightBase::BuildSpotMesh(float coneSize) |
|
{ |
|
// build a cone |
|
if(coneSize < 0.0f) |
|
return; |
|
int nverts = 9; |
|
int nfaces = 8; |
|
spotMesh.setNumVerts(nverts); |
|
spotMesh.setNumFaces(nfaces); |
|
double radang = 3.1415926 * coneSize / 360.0; |
|
float h = 20.0f; // hypotenuse |
|
float d = -h * (float)cos(radang); // dist from origin to cone circle |
|
float r = h * (float)sin(radang); // radius of cone circle |
|
float s = 0.70711f * r; // sin(45) * r |
|
spotMesh.setVert(0, Point3( FZ, FZ, FZ)); |
|
spotMesh.setVert(1, Point3( -r, FZ, d)); |
|
spotMesh.setVert(2, Point3( -s, -s, d)); |
|
spotMesh.setVert(3, Point3( FZ, -r, d)); |
|
spotMesh.setVert(4, Point3( s, -s, d)); |
|
spotMesh.setVert(5, Point3( r, FZ, d)); |
|
spotMesh.setVert(6, Point3( s, s, d)); |
|
spotMesh.setVert(7, Point3( FZ, r, d)); |
|
spotMesh.setVert(8, Point3( -s, s, d)); |
|
spotMesh.faces[0].setVerts(0,1,2); |
|
spotMesh.faces[1].setVerts(0,2,3); |
|
spotMesh.faces[2].setVerts(0,3,4); |
|
spotMesh.faces[3].setVerts(0,4,5); |
|
spotMesh.faces[4].setVerts(0,5,6); |
|
spotMesh.faces[5].setVerts(0,6,7); |
|
spotMesh.faces[6].setVerts(0,7,8); |
|
spotMesh.faces[7].setVerts(0,8,1); |
|
for (int i=0; i<nfaces; i++) { |
|
spotMesh.faces[i].setSmGroup(i); |
|
spotMesh.faces[i].setEdgeVisFlags(1,1,1); |
|
} |
|
spotMesh.buildNormals(); |
|
spotMesh.EnableEdgeList(1); |
|
//fMesh = spotMesh; |
|
} |
|
|
|
plRTLightBase::~plRTLightBase() |
|
{ |
|
DeleteAllRefsFromMe(); |
|
fLightPB = NULL; |
|
if( fTex ) |
|
delete fTex; |
|
} |
|
|
|
IParamBlock2* plRTLightBase::GetParamBlock2() |
|
{ |
|
return fLightPB; |
|
} |
|
|
|
IParamBlock2* plRTLightBase::GetParamBlockByID( short id ) |
|
{ |
|
if( id == fLightPB->ID() ) |
|
return fLightPB; |
|
else |
|
return nil; |
|
} |
|
|
|
IParamBlock2 *plRTLightBase::GetParamBlock( int i ) |
|
{ |
|
switch( i ) |
|
{ |
|
case 0: return fLightPB; |
|
default: return nil; |
|
} |
|
} |
|
|
|
|
|
// So our animatables will show up in the trackview |
|
int plRTLightBase::NumSubs() |
|
{ |
|
return 1; |
|
} |
|
Animatable *plRTLightBase::SubAnim(int i) |
|
{ |
|
return (Animatable *)fLightPB; |
|
|
|
switch(i) |
|
{ |
|
/* kRefProjMap, |
|
kRefShadowProjMap, |
|
kRefShadowType, |
|
kRefOmniLight, |
|
kRefSpotLight, |
|
kRefTSpotLight, |
|
kRefDirLight, |
|
kRefTDirLight |
|
*/ |
|
case kRefOmniLight: |
|
case kRefSpotLight: |
|
case kRefTSpotLight: |
|
case kRefDirLight: |
|
case kRefTDirLight: |
|
case kRefProjDirLight: |
|
return (Animatable*)fLightPB; |
|
case kRefProjMap: |
|
Texmap* MyMap; |
|
return (Animatable*) fLightPB->GetValue(kProjMapTexButton, 0, MyMap, FOREVER); |
|
case kRefShadowType: |
|
return NULL; |
|
default: return NULL; |
|
|
|
} |
|
|
|
//return (Animatable*) fLightPB; |
|
} |
|
|
|
TSTR plRTLightBase::SubAnimName(int i) |
|
{ |
|
return fLightPB->GetLocalName(); |
|
switch(i) |
|
{ |
|
|
|
case kRefOmniLight:return _T(""); |
|
case kRefSpotLight: return TSTR(GetString(IDS_DB_FSPOT)); |
|
case kRefTSpotLight:return _T(""); |
|
case kRefDirLight:return _T(""); |
|
case kRefTDirLight:return _T(""); |
|
case kRefProjMap: return TSTR(GetString(IDS_DS_PROJMAP)); |
|
case kRefShadowType: return _T(""); |
|
default: return _T(""); |
|
|
|
/* case PBLOCK_REF: return TSTR(GetString(IDS_RB_PARAMETERS)); |
|
case PROJMAP_REF: return TSTR(GetString(IDS_DS_PROJMAP)); |
|
case SHADPROJMAP_REF: return TSTR(GetString(IDS_DS_SHADPROJMAP)); |
|
case SHADTYPE_REF: return TSTR(GetString(IDS_DS_SHAD_GEN)); |
|
case EMITTER_REF: |
|
if ( IsCompatibleRenderer ()) |
|
return TSTR(GetString(IDS_EMITTER)); |
|
else |
|
return _T(""); |
|
default: return _T(""); |
|
*/ |
|
} |
|
} |
|
|
|
#if 0 |
|
RefTargetHandle plRTSpotLight::Clone(RemapDir &remap) |
|
{ |
|
plRTLightBase *obj = TRACKED_NEW plRTSpotLight; |
|
|
|
obj->GetParamBlock2->SetValue(kLightOn, t, fLightPB->GetInt(kLightOn, t)); |
|
// obj->fLightPB->SetValue(kLightType, t, fLightPB->GetInt(kLightType, t)); |
|
obj->fLightPB->SetValue(kLightColor, t, fLightPB->GetInt(kLightOn, t)); |
|
obj->fLightPB->SetValue(kCastShadows, t, fLightPB->GetInt(kLightOn, t)); |
|
//obj->fLightPB->SetValue(kContrast, t, fLightPB->GetInt(kLightOn, t)); |
|
//obj->fLightPB->SetValue(kDiffSoft, t, fLightPB->GetInt(kLightOn, t)); |
|
//obj->fLightPB->SetValue(kDiffOn, t, fLightPB->GetInt(kLightOn, t)); |
|
obj->fLightPB->SetValue(kSpec, t, fLightPB->GetInt(kLightOn, t)); |
|
obj->fLightPB->SetValue(kSpecularColorSwatch, t, fLightPB->GetInt(kLightOn, t)); |
|
obj->fLightPB->SetValue(kIntensity, t, fLightPB->GetInt(kLightOn, t)); |
|
|
|
if( IHasAttenuation() ) |
|
{ |
|
obj->fLightPB->SetValue(kUseAttenuationBool, t, fLightPB->GetInt(kLightType, t)); |
|
obj->fLightPB->SetValue(kAttenMaxFalloffEdit, t, fLightPB->GetInt(kLightOn, t)); |
|
obj->fLightPB->SetValue(kAttenTypeRadio, t, fLightPB->GetInt(kLightOn, t)); |
|
obj->fLightPB->SetValue(kShowConeBool, t, fLightPB->GetInt(kLightOn, t)); |
|
obj->fLightPB->SetValue(kHotSpot, t, fLightPB->GetInt(kLightOn, t)); |
|
obj->fLightPB->SetValue(kAttenMaxFalloffEdit, fLightPB->GetInt(kLightType, t)); |
|
obj->fLightPB->SetValue(kFallOff, t, fLightPB->GetInt(kLightOn, t)); |
|
|
|
obj->fLightPB->SetValue(kUseProjectorBool, t, fLightPB->GetInt(kLightOn, t)); |
|
obj->fLightPB->SetValue(kProjMapTexButton, t, fLightPB->GetInt(kLightOn, t)); |
|
} |
|
obj->ReplaceReference(kRefSpotLight,fLightPB->Clone(remap)); |
|
/* |
|
GeneralLight* newob = TRACKED_NEW GeneralLight(type); |
|
newob->enable = enable; |
|
newob->coneDisplay = coneDisplay; |
|
newob->useLight = useLight; |
|
newob->attenDisplay = attenDisplay; |
|
newob->useAtten = useAtten; |
|
newob->useAttenNear = useAttenNear; |
|
newob->attenNearDisplay = attenNearDisplay; |
|
newob->decayDisplay = decayDisplay; |
|
newob->shape = shape; |
|
newob->shadow = shadow; |
|
newob->shadowType = shadowType; |
|
newob->overshoot = overshoot; |
|
newob->projector = projector; |
|
newob->absMapBias = absMapBias; |
|
newob->exclList = exclList; |
|
newob->softenDiffuse = softenDiffuse; |
|
newob->affectDiffuse = affectDiffuse; |
|
newob->affectSpecular = affectSpecular; |
|
newob->ambientOnly = ambientOnly; |
|
newob->decayType = decayType; |
|
newob->atmosShadows = atmosShadows; |
|
newob->atmosOpacity = atmosOpacity; |
|
newob->atmosColAmt = atmosColAmt; |
|
newob->ReplaceReference(PBLOCK_REF,pblock->Clone(remap)); |
|
if (projMap) newob->ReplaceReference(PROJMAP_REF,projMap->Clone(remap)); |
|
if (shadProjMap) newob->ReplaceReference(SHADPROJMAP_REF,shadProjMap->Clone(remap)); |
|
if (shadType) newob->ReplaceReference(SHADTYPE_REF,shadType->Clone(remap)); |
|
if (emitter) newob->ReplaceReference(EMITTER_REF ,emitter->Clone(remap)); |
|
BaseClone(this, newob, remap); |
|
return(newob); |
|
*/ |
|
|
|
//plRTLightBase *obj = (plRTLightBase*) fClassDesc->Create(false); |
|
//obj->ReplaceReference(kRefComp, fLightPB->Clone(remap)); |
|
return obj; |
|
} |
|
#endif |
|
|
|
|
|
void plRTLightBase::FreeCaches() |
|
{ |
|
// fMesh.FreeAll(); |
|
} |
|
|
|
|
|
|
|
void plRTLightBase::BoxCircle(TimeValue t, float r, float d, Box3& box, int extraPt, Matrix3 *tm) |
|
{ |
|
Point3 q[3*NUM_CIRC_PTS]; |
|
int npts; |
|
float asp; |
|
if ( 1 /*Circle Object*/) { npts = NUM_CIRC_PTS+extraPt; asp = -1.0f; } |
|
else { npts = 4+extraPt; asp = -1.0; } |
|
GetConePoints(t, asp , r, d, q); |
|
box.IncludePoints(q,npts,tm); |
|
} |
|
|
|
void plRTLightBase::BoxDirPoints(TimeValue t, float angle, float dist, Box3 &box, Matrix3 *tm) |
|
{ |
|
int npts; |
|
Point3 q[3*NUM_CIRC_PTS]; |
|
npts = 1 /*Circle Object*/? GetCirXPoints(t,angle,dist,q): GetRectXPoints(t,angle,dist,q); |
|
box.IncludePoints(q,npts,tm); |
|
} |
|
|
|
|
|
void plRTLightBase::BoxPoints(TimeValue t, float angle, float dist, Box3 &box, Matrix3 *tm) |
|
{ |
|
if (IsDir()) |
|
BoxCircle(t, angle, dist, box, 0,tm); |
|
else |
|
BoxDirPoints(t, angle, dist, box, tm); |
|
} |
|
|
|
|
|
void plRTLightBase::BoxLight(TimeValue t, INode *inode, Box3& box, Matrix3 *tm) |
|
{ |
|
Point3 pt; |
|
float d; |
|
if (GetTargetPoint(t, inode, pt)) |
|
{ |
|
Point3 loc = inode->GetObjectTM(t).GetTrans(); |
|
d = FLength(loc - pt) / FLength(inode->GetObjectTM(t).GetRow(2)); |
|
box += tm? (*tm)*Point3(0.0f, 0.0f, -d): Point3(0.0f, 0.0f, -d); |
|
} |
|
else |
|
{ |
|
d = GetTDist(t); |
|
// if(fLightPB->GetInt(kLightType) == RT_FREE_DIR) |
|
// d = GetFallsize(t); |
|
if(IsSpot()) |
|
box += tm? (*tm)*Point3(0.0f, 0.0f, -d): Point3(0.0f, 0.0f, -d); |
|
if(IsDir()) |
|
{ |
|
d = GetFallsize(t); |
|
box += tm? (*tm)*Point3(0.0f, 0.0f, -d): Point3(0.0f, 0.0f, -d); |
|
|
|
} |
|
} |
|
if( this->ClassID() == RTSPOT_LIGHT_CLASSID ) |
|
// if (fLightPB->GetInt(kLightType) == RT_FREE_SPOT || fLightPB->GetInt(kLightType) == RT_TARGET_SPOT) |
|
if((fLightPB->GetInt(kShowConeBool,t)) || (extDispFlags & EXT_DISP_ONLY_SELECTED)) |
|
{ |
|
float rad = MaxF(GetHotspot(t), GetFallsize(t)); |
|
if (IsDir()) |
|
BoxCircle(t,rad,0.0f,box,1,tm); |
|
BoxCircle(t,rad,d,box,1,tm); |
|
} |
|
if( this->ClassID() == RTDIR_LIGHT_CLASSID |
|
|| this->ClassID() == RTPDIR_LIGHT_CLASSID ) |
|
// if (fLightPB->GetInt(kLightType) == RT_FREE_DIR || fLightPB->GetInt(kLightType) == RT_TARGET_DIR) |
|
if((extDispFlags & EXT_DISP_ONLY_SELECTED)) |
|
{ |
|
float rad = MaxF(GetHotspot(t), GetFallsize(t)); |
|
if (IsDir()) |
|
BoxCircle(t,rad,0.0f,box,1,tm); |
|
BoxCircle(t,rad,2.82841*GetFallsize(t),box,1,tm); //hack, hack. Do 2root2 at corners... |
|
} |
|
BOOL dispAtten = false; |
|
BOOL dispAttenNear = false; |
|
BOOL dispDecay = false; |
|
if( this->ClassID() == RTOMNI_LIGHT_CLASSID || this->ClassID() == RTSPOT_LIGHT_CLASSID ) |
|
{ |
|
dispAtten = fLightPB->GetInt(kUseAttenuationBool,t); |
|
dispAttenNear = 0; //attenNearDisplay; |
|
|
|
dispDecay = (GetDecayType()&&(extDispFlags & EXT_DISP_ONLY_SELECTED)); |
|
} |
|
if( dispAtten || dispDecay) |
|
{ |
|
if( this->ClassID() == RTOMNI_LIGHT_CLASSID ) |
|
{ |
|
Point3 q[3*NUM_CIRC_PTS]; |
|
float rad = 0; |
|
if (dispAtten) |
|
rad = MaxF(GetAtten(t, ATTEN_START), GetAtten(t, ATTEN_END)); |
|
if (dispDecay) rad = MaxF(rad,0.0/*GetDecayRadius(t)*/); |
|
GetAttenPoints(t, rad, q); |
|
box.IncludePoints(q,3*NUM_CIRC_PTS,tm); |
|
} |
|
if( this->ClassID() == RTSPOT_LIGHT_CLASSID ) |
|
{ |
|
if (dispAtten) |
|
{ |
|
BoxPoints(t, GetFallsize(t), GetAtten(t,ATTEN_END), box, tm); |
|
BoxPoints(t, GetFallsize(t), GetAtten(t,ATTEN_START), box, tm); |
|
} |
|
if (dispDecay) |
|
BoxPoints(t, GetFallsize(t), 0.0/*GetDecayRadius(t)*/, box, tm); |
|
} |
|
} |
|
|
|
} |
|
|
|
int plRTLightBase::GetRectXPoints(TimeValue t, float angle, float dist, Point3 *q) |
|
{ |
|
int i; |
|
if(dist==0.0f) dist = .00001f; |
|
float ang = DegToRad(angle)/2.0f; |
|
float da,sn,cs,x,y,z,a; |
|
float aspect = GetAspect(t); |
|
float w = dist * (float)tan(ang) * (float)sqrt((double)aspect); |
|
float h = w/aspect; |
|
float wang = (float)atan(w/dist); |
|
float hang = (float)atan(h/dist); |
|
float aw = float(atan(w/dist)*cos(hang)); // half-angle of top and bottom arcs |
|
float ah = float(atan(h/dist)*cos(wang)); // half-angle of left and right arcs |
|
int j = 0; |
|
|
|
// draw horizontal and vertical center lines |
|
da = wang/float(NUM_HALF_ARC); |
|
for(i = -NUM_HALF_ARC, a = -wang; i<= NUM_HALF_ARC; i++, a+=da) |
|
q[j++] = Point3(dist*(float)sin(a), 0.0f, -dist*(float)cos(a)); |
|
da = hang/float(NUM_HALF_ARC); |
|
for(i = -NUM_HALF_ARC, a = -hang; i<= NUM_HALF_ARC; i++, a+=da) |
|
q[j++] = Point3(0.0f, dist*(float)sin(a), -dist*(float)cos(a)); |
|
|
|
|
|
// draw top and bottom arcs |
|
da = aw/float(NUM_HALF_ARC); |
|
sn = (float)sin(hang); |
|
cs = (float)cos(hang); |
|
for (i = -NUM_HALF_ARC, a = -aw; i<= NUM_HALF_ARC; i++, a+=da) |
|
{ |
|
x = dist*(float)sin(a); |
|
z = -dist*(float)cos(a); |
|
q[j] = Point3(x, z*sn, z*cs); |
|
q[j+NUM_ARC_PTS] = Point3(x,-z*sn, z*cs); |
|
j++; |
|
} |
|
|
|
j+= NUM_ARC_PTS; |
|
|
|
// draw left and right arcs |
|
da = ah/float(NUM_HALF_ARC); |
|
sn = (float)sin(wang); |
|
cs = (float)cos(wang); |
|
for (i = -NUM_HALF_ARC, a = -ah; i<= NUM_HALF_ARC; i++, a+=da) |
|
{ |
|
y = dist*(float)sin(a); |
|
z = -dist*(float)cos(a); |
|
q[j] = Point3( z*sn, y, z*cs); |
|
q[j+NUM_ARC_PTS] = Point3(-z*sn, y, z*cs); |
|
j++; |
|
} |
|
|
|
return 6*NUM_ARC_PTS; |
|
} |
|
|
|
int plRTLightBase::GetCirXPoints(TimeValue t, float angle, float dist, Point3 *q) |
|
{ |
|
int i; |
|
float ang = DegToRad(angle)/2.0f; |
|
float da = ang/float(NUM_HALF_ARC); |
|
// first draw circle: |
|
float d = dist*(float)cos(ang); |
|
GetConePoints(t, -1.0f, angle, d, q); |
|
int j=NUM_CIRC_PTS; |
|
// then draw Arc X |
|
float a = -ang; |
|
for(i = -NUM_HALF_ARC; i<= NUM_HALF_ARC; i++, a+=da) |
|
q[j++] = Point3(0.0f, dist*(float)sin(a), -dist*(float)cos(a)); |
|
a = -ang; |
|
for(i = -NUM_HALF_ARC; i<= NUM_HALF_ARC; i++, a+=da) |
|
q[j++] = Point3(dist*(float)sin(a), 0.0f, -dist*(float)cos(a)); |
|
return NUM_CIRC_PTS + 2*NUM_ARC_PTS; |
|
} |
|
|
|
void plRTLightBase::DrawX(TimeValue t, float asp, int npts, float dist, GraphicsWindow *gw, int indx) |
|
{ |
|
Point3 q[3*NUM_CIRC_PTS+1]; |
|
Point3 u[2]; |
|
GetConePoints(t, asp, GetFallsize(t), dist, q); |
|
gw->polyline(npts, q,NULL, NULL, TRUE, NULL); |
|
u[0] = q[0]; u[1] = q[2*indx]; |
|
gw->polyline(2, u,NULL, NULL, FALSE, NULL); |
|
u[0] = q[indx]; u[1] = q[3*indx]; |
|
gw->polyline(2, u,NULL, NULL, FALSE, NULL); |
|
} |
|
|
|
|
|
|
|
void plRTLightBase::GetAttenPoints(TimeValue t, float rad, Point3 *q) |
|
{ |
|
double a; |
|
float sn, cs; |
|
for(int i = 0; i < NUM_CIRC_PTS; i++) |
|
{ |
|
a = (double)i * 2.0 * 3.1415926 / (double)NUM_CIRC_PTS; |
|
sn = rad * (float)sin(a); |
|
cs = rad * (float)cos(a); |
|
q[i+0*NUM_CIRC_PTS] = Point3(sn, cs, 0.0f); |
|
q[i+1*NUM_CIRC_PTS] = Point3(sn, 0.0f, cs); |
|
q[i+2*NUM_CIRC_PTS] = Point3(0.0f, sn, cs); |
|
} |
|
} |
|
|
|
|
|
// Draw warped rectangle |
|
void plRTLightBase::DrawWarpRect(TimeValue t, GraphicsWindow *gw, float angle, float dist, Point3 *q) |
|
{ |
|
GetRectXPoints(t, angle,dist,q); |
|
for (int i=0; i<6; i++) |
|
gw->polyline(NUM_ARC_PTS, q+i*NUM_ARC_PTS,NULL, NULL, FALSE, NULL); |
|
} |
|
|
|
void plRTLightBase::DrawCircleX(TimeValue t, GraphicsWindow *gw, float angle, float dist, Point3 *q) |
|
{ |
|
GetCirXPoints(t, angle,dist,q); |
|
gw->polyline(NUM_CIRC_PTS, q,NULL, NULL, TRUE, NULL); // circle |
|
gw->polyline(NUM_ARC_PTS, q+NUM_CIRC_PTS,NULL, NULL, FALSE, NULL); // vert arc |
|
gw->polyline(NUM_ARC_PTS, q+NUM_CIRC_PTS+NUM_ARC_PTS,NULL, NULL, FALSE, NULL); // horiz arc |
|
} |
|
|
|
void plRTLightBase::DrawSphereArcs(TimeValue t, GraphicsWindow *gw, float r, Point3 *q) |
|
{ |
|
GetAttenPoints(t, r, q); |
|
gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL); |
|
gw->polyline(NUM_CIRC_PTS, q+NUM_CIRC_PTS, NULL, NULL, TRUE, NULL); |
|
gw->polyline(NUM_CIRC_PTS, q+2*NUM_CIRC_PTS,NULL, NULL, TRUE, NULL); |
|
} |
|
|
|
// |
|
|
|
void plRTLightBase::DrawAttenCirOrRect(TimeValue t, GraphicsWindow *gw, float dist, BOOL froze, int uicol) |
|
{ |
|
if (!froze) gw->setColor( LINE_COLOR, GetUIColor(uicol)); |
|
if (IsDir()) |
|
{ |
|
int npts,indx; |
|
float asp; |
|
npts = NUM_CIRC_PTS; asp = -1.0f; indx = SEG_INDEX; |
|
DrawX(t, asp, npts, dist, gw, indx); |
|
} |
|
else |
|
{ |
|
Point3 q[3*NUM_CIRC_PTS+1]; |
|
if( this->ClassID() == RTOMNI_LIGHT_CLASSID ) |
|
DrawSphereArcs(t, gw, dist, q); |
|
else |
|
DrawCircleX(t, gw, GetFallsize(t),dist,q); |
|
|
|
} |
|
} |
|
|
|
|
|
int plRTLightBase::DrawAtten(TimeValue t, INode *inode, GraphicsWindow *gw) |
|
{ |
|
BOOL dispAtten = false; |
|
BOOL dispDecay = false; |
|
if( this->ClassID() == RTOMNI_LIGHT_CLASSID || this->ClassID() == RTSPOT_LIGHT_CLASSID ) |
|
{ |
|
dispAtten = (fLightPB->GetInt(kUseAttenuationBool,t) && (extDispFlags & EXT_DISP_ONLY_SELECTED)); |
|
//BOOL dispAttenNear = (fLightPB->GetInt(kUseNearAtten) && (extDispFlags & EXT_DISP_ONLY_SELECTED))?TRUE:fLightPB->GetInt(kShowFarAttenRanges); |
|
dispDecay = (GetDecayType() && (extDispFlags & EXT_DISP_ONLY_SELECTED)); |
|
} |
|
if (dispAtten || dispDecay) |
|
{ |
|
Matrix3 tm = inode->GetObjectTM(t); |
|
gw->setTransform(tm); |
|
BOOL froze = inode->IsFrozen() && !inode->Dependent(); |
|
if (dispAtten) |
|
{ |
|
DrawAttenCirOrRect(t, gw, GetAtten(t,ATTEN_START), froze, COLOR_START_RANGE); |
|
DrawAttenCirOrRect(t, gw, GetAtten(t,ATTEN_END), froze, COLOR_END_RANGE); |
|
} |
|
|
|
if (dispDecay) |
|
{ |
|
DrawAttenCirOrRect(t, gw, 0.0 /*DecayRadius() Stuff here */, froze, COLOR_DECAY_RADIUS); |
|
} |
|
} |
|
return 0; |
|
} |
|
|
|
void plRTLightBase::GetLocalBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box) |
|
{ |
|
//BuildMeshes(t); |
|
//box = fMesh.getBoundingBox(); |
|
// int nv; |
|
// Matrix3 tm; |
|
// GetMat(t, node,vpt,tm); |
|
// Point3 loc = tm.GetTrans(); |
|
// nv = fMesh.getNumVerts(); |
|
// box.Init(); |
|
// if(!(extDispFlags & EXT_DISP_ZOOM_EXT)) |
|
// box.IncludePoints(fMesh.verts,nv,&tm); |
|
// else |
|
// box += loc; |
|
// tm = node->GetObjectTM(t); |
|
// BoxLight(t, node, box, &tm); |
|
Point3 loc = node->GetObjectTM(t).GetTrans(); |
|
float scaleFactor = vpt->NonScalingObjectSize()*vpt->GetVPWorldWidth(loc) / 360.0f; |
|
box = fMesh.getBoundingBox(); |
|
box.Scale(scaleFactor); |
|
BoxLight(t, node, box, NULL); |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
RefTargetHandle Clone(RemapDir &remap = NoRemap()) |
|
{ |
|
|
|
plRTLightBase* newOb = TRACKED_NEW plRTLightBase; |
|
newOb->fLightPB->SetValue(kLightOn, 0, this->fLightPB->GetInt(kLightOn, 0)); |
|
newOb->fLightPB->SetValue(kLightColor, 0, this->fLightPB->GetValue(kLightColor, 0)); |
|
newOb->fLightPB->SetValue(kLightExclude, 0, this->fLightPB->GetValue(kLightExclude, 0)); |
|
newOb->fLightPB->SetValue(kRed, 0, this->fLightPB->GetInt(kRed, 0)); |
|
newOb->fLightPB->SetValue(kGreen, 0, this->fLightPB->GetInt(kGreen, 0)); |
|
newOb->fLightPB->SetValue(kBlue, 0, this->fLightPB->GetInt(kBlue, 0)); |
|
newOb->fLightPB->SetValue(kHue, 0, this->fLightPB->GetInt(kHue, 0)); |
|
newOb->fLightPB->SetValue(kSat, 0, this->fLightPB->GetInt(kSat, 0)); |
|
newOb->fLightPB->SetValue(kVal, 0, this->fLightPB->GetInt(kVal, 0)); |
|
newOb->fLightPB->SetValue(kIntensity, 0, this->fLightPB->GetFloat(kIntensity, 0)); |
|
newOb->fLightPB->SetValue(kContrast, 0, this->fLightPB->GetFloat(kContrast, 0)); |
|
newOb->fLightPB->SetValue(kDiffSoft, 0, this->fLightPB->GetFloat(kDiffSoft, 0)); |
|
newOb->fLightPB->SetValue(kDiffOn, 0, this->fLightPB->GetInt(kDiffOn, 0)); |
|
newOb->fLightPB->SetValue(kStartAttenNear, 0, this->fLightPB->GetFloat(kStartAttenNear, 0)); |
|
newOb->fLightPB->SetValue(kAmbiOnly, 0, this->fLightPB->GetInt(kAmbiOnly, 0)); |
|
newOb->fLightPB->SetValue(kEndAttenNear, 0, this->fLightPB->GetFloat(kEndAttenNear, 0)); |
|
newOb->fLightPB->SetValue(kUseNearAtten, 0, this->fLightPB->GetInt(kUseNearAtten, 0)); |
|
newOb->fLightPB->SetValue(kShowNearAttenRanges, 0, this->fLightPB->GetInt(kShowNearAttenRanges, 0)); |
|
newOb->fLightPB->SetValue(kStartAttenFar, 0, this->fLightPB->GetFloat(kStartAttenFar, 0)); |
|
newOb->fLightPB->SetValue(kEndAttenFar, 0, this->fLightPB->GetFloat(kEndAttenFar, 0)); |
|
|
|
newOb->fLightPB->SetValue(kUseFarAtten, 0, this->fLightPB->GetInt(kUseFarAtten, 0)); |
|
newOb->fLightPB->SetValue(kShowFarAttenRanges, 0, this->fLightPB->GetInt(kShowFarAttenRanges, 0)); |
|
newOb->fLightPB->SetValue(kLightDecay, 0, this->fLightPB->GetInt(kLightDecay, 0)); |
|
newOb->fLightPB->SetValue(kRed, 0, this->fLightPB->GetInt(kRed, 0)); |
|
newOb->fLightPB->SetValue(kGreen, 0, this->fLightPB->GetInt(kGreen, 0)); |
|
newOb->fLightPB->SetValue(kBlue, 0, this->fLightPB->GetInt(kBlue, 0)); |
|
newOb->fLightPB->SetValue(kHue, 0, this->fLightPB->GetInt(kHue, 0)); |
|
newOb->fLightPB->SetValue(kSat, 0, this->fLightPB->GetInt(kSat, 0)); |
|
newOb->fLightPB->SetValue(kVal, 0, this->fLightPB->GetInt(kVal, 0)); |
|
newOb->fLightPB->SetValue(kIntensity, 0, this->fLightPB->GetFloat(kIntensity, 0)); |
|
newOb->fLightPB->SetValue(kContrast, 0, this->fLightPB->GetFloat(kContrast, 0)); |
|
newOb->fLightPB->SetValue(kDiffSoft, 0, this->fLightPB->GetFloat(kDiffSoft, 0)); |
|
newOb->fLightPB->SetValue(kDiffOn, 0, this->fLightPB->GetInt(kDiffOn, 0)); |
|
newOb->fLightPB->SetValue(kStartAttenNear, 0, this->fLightPB->GetFloat(kStartAttenNear, 0)); |
|
newOb->fLightPB->SetValue(kAmbiOnly, 0, this->fLightPB->GetInt(kAmbiOnly, 0)); |
|
newOb->fLightPB->SetValue(kEndAttenNear, 0, this->fLightPB->GetFloat(kEndAttenNear, 0)); |
|
newOb->fLightPB->SetValue(kUseNearAtten, 0, this->fLightPB->GetInt(kUseNearAtten, 0)); |
|
newOb->fLightPB->SetValue(kShowNearAttenRanges, 0, this->fLightPB->GetInt(kShowNearAttenRanges, 0)); |
|
newOb->fLightPB->SetValue(kStartAttenFar, 0, this->fLightPB->GetFloat(kStartAttenFar, 0)); |
|
newOb->fLightPB->SetValue(kEndAttenFar, 0, this->fLightPB->GetFloat(kEndAttenFar, 0)); |
|
|
|
*/ |
|
|
|
/* |
|
|
|
|
|
kLightType, //Inserted in v1 |
|
kLightOn, //Inserted in v1 |
|
kLightColor, //Inserted in v1 |
|
kLightExclude, //Inserted in v1 |
|
kRed, //Inserted in v1 |
|
kGreen, //Inserted in v1 |
|
kBlue, //Inserted in v1 |
|
kHue, //Inserted in v1 |
|
kSat, //Inserted in v1 |
|
kVal, //Inserted in v1 |
|
kIntensity, //Inserted in v1 |
|
kContrast, //Inserted in v1 |
|
kDiffSoft, //Inserted in v1 |
|
kDiffOn, //Inserted in v1 |
|
kSpec, //Inserted in v1 |
|
kAmbiOnly, //Inserted in v1 |
|
kStartAttenNear, //Inserted in v1 |
|
kEndAttenNear, //Inserted in v1 |
|
kUseNearAtten, //Inserted in v1 |
|
kShowNearAttenRanges,//Inserted in v1 |
|
kStartAttenFar, //Inserted in v1 |
|
kEndAttenFar, //Inserted in v1 |
|
kUseFarAtten, //Inserted in v1 |
|
kShowFarAttenRanges, //Inserted in v1 |
|
kLightDecay, //Inserted in v1 |
|
kDecayEdit, //Inserted in v1 |
|
kShowDecay, //Inserted in v1 |
|
kUseProjectBool, //Inserted in v1 |
|
kProjMapTexButton, //Inserted in v1 |
|
kShowConeBool, //Inserted in v1 |
|
kOvershootBool, //Inserted in v1 |
|
kHotSpot, //Inserted in v1 |
|
kFallOff, //Inserted in v1 |
|
kLightShapeRadio, //Inserted in v1 |
|
kAspect, //Inserted in v1 |
|
kUseProjectorBool, //Inserted in v1 |
|
kProjMapTexButton2, //Inserted in v1 |
|
kTargetDist //Inserted in v1 |
|
GeneralLight* newob = TRACKED_NEW GeneralLight(type); |
|
newob->enable = enable; |
|
newob->coneDisplay = coneDisplay; |
|
newob->useLight = useLight; |
|
newob->attenDisplay = attenDisplay; |
|
newob->useAtten = useAtten; |
|
newob->useAttenNear = useAttenNear; |
|
newob->attenNearDisplay = attenNearDisplay; |
|
newob->decayDisplay = decayDisplay; |
|
newob->shape = shape; |
|
newob->shadow = shadow; |
|
newob->shadowType = shadowType; |
|
newob->overshoot = overshoot; |
|
newob->projector = projector; |
|
newob->absMapBias = absMapBias; |
|
newob->exclList = exclList; |
|
newob->softenDiffuse = softenDiffuse; |
|
newob->affectDiffuse = affectDiffuse; |
|
newob->affectSpecular = affectSpecular; |
|
newob->ambientOnly = ambientOnly; |
|
newob->decayType = decayType; |
|
newob->atmosShadows = atmosShadows; |
|
newob->atmosOpacity = atmosOpacity; |
|
newob->atmosColAmt = atmosColAmt; |
|
newob->ReplaceReference(PBLOCK_REF,pblock->Clone(remap)); |
|
if (projMap) newob->ReplaceReference(PROJMAP_REF,projMap->Clone(remap)); |
|
if (shadProjMap) newob->ReplaceReference(SHADPROJMAP_REF,shadProjMap->Clone(remap)); |
|
if (shadType) newob->ReplaceReference(SHADTYPE_REF,shadType->Clone(remap)); |
|
if (emitter) newob->ReplaceReference(EMITTER_REF ,emitter->Clone(remap)); |
|
BaseClone(this, newob, remap); |
|
return(newob); |
|
} |
|
*/ |
|
|
|
|
|
|
|
//} |
|
|
|
|
|
|
|
|
|
|
|
void plRTLightBase::GetWorldBoundBox(TimeValue t, INode *node, ViewExp *vpt, Box3 &box) |
|
{ |
|
GetLocalBoundBox( t, node, vpt, box ); |
|
box = box * node->GetObjectTM( t ); |
|
} |
|
|
|
void plRTLightBase::GetDeformBBox(TimeValue t, Box3& box, Matrix3 *tm, BOOL useSel ) |
|
{ |
|
box = fMesh.getBoundingBox(tm); |
|
} |
|
|
|
|
|
|
|
int plRTLightBase::Display(TimeValue t, INode *node, ViewExp *vpt, int flags) |
|
{ |
|
|
|
|
|
Matrix3 m; |
|
// if (!enable) |
|
// return 0; |
|
GraphicsWindow *gw = vpt->getGW(); |
|
GetMat(t,node,vpt,m); |
|
gw->setTransform(m); |
|
DWORD rlim = gw->getRndLimits(); |
|
gw->setRndLimits(GW_WIREFRAME|GW_BACKCULL|(gw->getRndMode() & GW_Z_BUFFER)); |
|
if (node->Selected()) |
|
gw->setColor( LINE_COLOR, GetSelColor()); |
|
else if(!node->IsFrozen() && !node->Dependent()) |
|
{ |
|
if(fLightPB->GetInt(kLightOn)) |
|
gw->setColor( LINE_COLOR, GetUIColor(COLOR_LIGHT_OBJ)); |
|
// I un-commented this line DS 6/11/99 |
|
else |
|
gw->setColor( LINE_COLOR, 0.0f, 0.0f, 0.0f); |
|
} |
|
|
|
fMesh.render( gw, gw->getMaterial(), |
|
(flags&USE_DAMAGE_RECT) ? &vpt->GetDammageRect() : NULL, COMP_ALL); |
|
|
|
DrawConeAndLine(t, node, gw, 1); |
|
// DrawAtten(t, node, gw); |
|
gw->setRndLimits(rlim); |
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static void RemoveScaling(Matrix3 &tm) |
|
{ |
|
AffineParts ap; |
|
decomp_affine(tm, &ap); |
|
tm.IdentityMatrix(); |
|
tm.SetRotate(ap.q); |
|
tm.SetTrans(ap.t); |
|
} |
|
|
|
void plRTLightBase::GetMat(TimeValue t, INode* inode, ViewExp *vpt, Matrix3& tm) |
|
{ |
|
tm = inode->GetObjectTM(t); |
|
// tm.NoScale(); |
|
RemoveScaling(tm); |
|
float scaleFactor = vpt->NonScalingObjectSize()*vpt->GetVPWorldWidth(tm.GetTrans())/(float)360.0; |
|
tm.Scale(Point3(scaleFactor,scaleFactor,scaleFactor)); |
|
} |
|
|
|
|
|
void plRTLightBase::GetConePoints(TimeValue t, float aspect, float angle, float dist, Point3 *q) |
|
{ |
|
float ta = (float)tan(0.5*DegToRad(angle)); |
|
if(1 /*fLightPB->GetFloat(kAspect, t) <= 0.0f*/) |
|
{ |
|
// CIRCULAR |
|
float rad = dist * ta; |
|
double a; |
|
if(IsDir()) |
|
rad = angle; |
|
int i; |
|
for(i = 0; i < NUM_CIRC_PTS; i++) { |
|
a = (double)i * 2.0 * 3.1415926 / (double)NUM_CIRC_PTS; |
|
q[i] = Point3(rad*(float)sin(a), rad*(float)cos(a), -dist); |
|
} |
|
q[i] = q[0] + Point3(0.0f, 15.0f, 0.0f); |
|
} |
|
else |
|
{ |
|
// RECTANGULAR |
|
float w = IsDir()? angle : dist * ta * (float)sqrt((double)aspect); |
|
float h = w / aspect; |
|
q[0] = Point3( w, h,-dist); |
|
q[1] = Point3(-w, h,-dist); |
|
q[2] = Point3(-w,-h,-dist); |
|
q[3] = Point3( w,-h,-dist); |
|
q[4] = Point3( 0.0f, h+15.0f, -dist); |
|
q[5] = Point3( 0.0f, h, -dist); |
|
} |
|
} |
|
|
|
#define HOTCONE 0 |
|
#define FALLCONE 1 |
|
|
|
void plRTLightBase::DrawCone(TimeValue t, GraphicsWindow *gw, float dist) |
|
{ |
|
Point3 q[NUM_CIRC_PTS+1], u[3]; |
|
int dirLight = IsDir(); |
|
int i; |
|
BOOL dispAtten = false; |
|
BOOL dispDecay = false; |
|
if( this->ClassID() == RTOMNI_LIGHT_CLASSID || this->ClassID() == RTSPOT_LIGHT_CLASSID ) |
|
{ |
|
dispAtten = (fLightPB->GetInt(kUseAttenuationBool, t) && (extDispFlags & EXT_DISP_ONLY_SELECTED));//attenDisplay; |
|
dispDecay = (/*fLightPB->GetInt(kAttenTypeRadio, t)*/GetDecayType() && (extDispFlags & EXT_DISP_ONLY_SELECTED)); |
|
} |
|
if(!IsDir()) |
|
GetConePoints(t, -1.0f, GetHotspot(t), dist, q); |
|
else |
|
GetConePoints(t, -1.0f, 20.0, dist, q); |
|
|
|
gw->setColor( LINE_COLOR, GetUIColor(COLOR_HOTSPOT)); |
|
if(1 /*Circular Hack*/) { |
|
// CIRCULAR |
|
if(GetHotspot(t) >= GetFallsize(t)) |
|
{ |
|
// draw (far) hotspot circle |
|
u[0] = q[0]; |
|
u[1] = q[NUM_CIRC_PTS]; |
|
gw->polyline( 2, u, NULL, NULL, FALSE, NULL); |
|
} |
|
gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL); |
|
if (dirLight) |
|
{ |
|
// draw 4 axial hotspot lines |
|
for (i = 0; i < NUM_CIRC_PTS; i += SEG_INDEX) |
|
{ |
|
u[0] = q[i]; u[1] = q[i]; u[1].z += dist; |
|
gw->polyline( 2, u, NULL, NULL, FALSE, NULL ); |
|
} |
|
GetConePoints(t, -1.0f, 20/*GetHotspot(t)*/, 0.0f, q); |
|
// draw (near) hotspot circle |
|
gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL); |
|
} |
|
else |
|
{ |
|
// draw 4 axial lines |
|
u[0] = Point3(0,0,0); |
|
for (i = 0; i < NUM_CIRC_PTS; i += SEG_INDEX) |
|
{ |
|
u[1] = q[i]; |
|
gw->polyline( 2, u, NULL, NULL, FALSE, NULL ); |
|
} |
|
} |
|
if(!IsDir()) |
|
GetConePoints(t, -1.0f, GetFallsize(t), dist, q); |
|
else |
|
GetConePoints(t, -1.0f, 200.0, dist, q); |
|
gw->setColor( LINE_COLOR, GetUIColor(COLOR_FALLOFF)); |
|
if(GetHotspot(t) < GetFallsize(t)) |
|
{ |
|
// draw (far) fallsize circle |
|
u[0] = q[0]; u[1] = q[NUM_CIRC_PTS]; |
|
gw->polyline( 2, u, NULL, NULL, FALSE, NULL); |
|
u[0] = Point3(0,0,0); |
|
} |
|
gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL); |
|
if (dirLight) |
|
{ |
|
float dfar = q[0].z; |
|
float dnear = 0.0f; |
|
if (dispAtten) |
|
{ |
|
dfar = MinF(-GetAtten(t,ATTEN_END),dfar); |
|
/// dnear = MaxF(-GetAtten(t,ATTEN_START),dnear); |
|
} |
|
if (dispDecay) { |
|
dfar = MinF(/*-GetDecayRadius(t)*/ 0.0,dfar); |
|
} |
|
|
|
// draw axial fallsize lines |
|
for (i = 0; i < NUM_CIRC_PTS; i += SEG_INDEX) |
|
{ |
|
u[0] = q[i]; u[0].z = dfar; u[1] = q[i]; u[1].z = dnear; |
|
gw->polyline( 2, u, NULL, NULL, FALSE, NULL ); |
|
} |
|
|
|
GetConePoints(t, -1.0f, 10000.0, 0.0f, q); |
|
// draw (near) fallsize circle |
|
gw->polyline(NUM_CIRC_PTS, q, NULL, NULL, TRUE, NULL); |
|
|
|
} |
|
else |
|
{ |
|
float cs = (float)cos(DegToRad(GetFallsize(t)*0.5f)); |
|
float dfar = q[0].z; |
|
if (dispAtten) |
|
dfar = MinF(-cs*GetAtten(t,ATTEN_END),dfar); |
|
if (dispDecay) |
|
dfar = MinF(/*-cs*GetDecayRadius(t)*/0.0,dfar); |
|
|
|
for (i = 0; i < NUM_CIRC_PTS; i += SEG_INDEX) |
|
{ |
|
u[1] = -q[i]*dfar/dist; |
|
gw->polyline( 2, u, NULL, NULL, FALSE, NULL ); |
|
} |
|
} |
|
} |
|
|
|
} |
|
|
|
|
|
int plRTLightBase::DrawConeAndLine(TimeValue t, INode* inode, GraphicsWindow *gw, int drawing ) |
|
{ |
|
if(!IsSpot() && !IsDir()) |
|
return 0; |
|
Matrix3 tm = inode->GetObjectTM(t); |
|
gw->setTransform(tm); |
|
gw->clearHitCode(); |
|
if( 0 ) |
|
{ |
|
Point3 pt,v[3]; |
|
if (GetTargetPoint(t, inode, pt)) |
|
{ |
|
float den = FLength(tm.GetRow(2)); |
|
float dist = (den!=0) ? FLength(tm.GetTrans()-pt) / den : 0.0f; |
|
fLightPB->SetValue(kAttenMaxFalloffEdit, t, dist); |
|
|
|
//fLightPB->SetValue(kTargetDist, t, dist); |
|
//if (hSpotLight&&(currentEditLight==this)) { |
|
// TCHAR buf[40]; |
|
// _stprintf(buf,_T("%0.3f"),targDist); |
|
// SetWindowText(GetDlgItem(hSpotLight,IDC_TARG_DISTANCE),buf); |
|
// } |
|
|
|
if ((drawing != -1) && (fLightPB->GetInt(kShowConeBool, t) || (extDispFlags & EXT_DISP_ONLY_SELECTED))) |
|
DrawCone(t, gw, dist); |
|
if(!inode->IsFrozen() && !inode->Dependent()) |
|
gw->setColor( LINE_COLOR, GetUIColor(COLOR_TARGET_LINE)); |
|
v[0] = Point3(0,0,0); |
|
v[1] = Point3(0.0f, 0.0f, (drawing == -1)? (-0.9f * dist): -dist); |
|
gw->polyline( 2, v, NULL, NULL, FALSE, NULL ); |
|
} |
|
|
|
} |
|
else if( this->ClassID() == RTSPOT_LIGHT_CLASSID ) |
|
{ |
|
if ((drawing != -1) && (fLightPB->GetInt(kShowConeBool, t) || (extDispFlags & EXT_DISP_ONLY_SELECTED))) |
|
DrawCone(t, gw, fLightPB->GetFloat( kAttenMaxFalloffEdit, t ) ); |
|
} |
|
else if( this->ClassID() == RTDIR_LIGHT_CLASSID ) |
|
{ |
|
if ((extDispFlags & EXT_DISP_ONLY_SELECTED)) |
|
DrawCone(t, gw, 500/*GetTDist(t)*/); |
|
} |
|
return gw->checkHitCode(); |
|
} |
|
|
|
|
|
//// DrawArrow /////////////////////////////////////////////////////////////// |
|
|
|
void plRTLightBase::DrawArrow( TimeValue t, GraphicsWindow *gw, Point3 &direction, float dist ) |
|
{ |
|
Point3 pts[ 5 ]; |
|
|
|
|
|
pts[ 0 ] = Point3( 0, 0, 0 ); |
|
pts[ 1 ] = direction * dist; |
|
pts[ 3 ] = pts[ 1 ] - direction * 10.f; |
|
pts[ 2 ] = pts[ 3 ] + Point3( direction.y, direction.z, direction.x ) * 5.f; |
|
|
|
gw->polyline( 4, pts, nil, nil, true, nil ); |
|
} |
|
|
|
int plRTLightBase::HitTest(TimeValue t, INode *node, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt) |
|
{ |
|
DWORD savedLimits; |
|
GraphicsWindow *gw = vpt->getGW(); |
|
HitRegion hitRegion; |
|
int res; |
|
Matrix3 m; |
|
MakeHitRegion(hitRegion, type, crossing, 4, p); |
|
Material *mtl = gw->getMaterial(); |
|
|
|
gw->setRndLimits( ((savedLimits = gw->getRndLimits()) | GW_PICK) & ~(GW_ILLUM|GW_BACKCULL)); |
|
GetMat(t,node,vpt,m); |
|
|
|
//BuildMeshes(t); |
|
gw->setTransform(m); |
|
res = fMesh.select( gw, mtl, &hitRegion, flags & HIT_ABORTONHIT); |
|
// if not, check the target line, and set the pair flag if it's hit |
|
if( !res ) |
|
{ |
|
// this special case only works with point selection of targeted lights |
|
if((type != HITTYPE_POINT) || !node->GetTarget()) |
|
return 0; |
|
// don't let line be active if only looking at selected stuff and target isn't selected |
|
if((flags & HIT_SELONLY) && !node->GetTarget()->Selected() ) |
|
return 0; |
|
gw->clearHitCode(); |
|
if(res = DrawConeAndLine(t, node, gw, -1)) |
|
node->SetTargetNodePair(1); |
|
} |
|
gw->setRndLimits(savedLimits); |
|
return res; |
|
|
|
//return fMesh.select(gw,node->Mtls(),&hitRegion,flags & HIT_ABORTONHIT,node->NumMtls()); |
|
} |
|
static void GenericSnap(TimeValue t, INode* inode, SnapInfo *snap, IPoint2 *p, ViewExp *vpt) |
|
{ |
|
// Make sure the vertex priority is active and at least as important as the best snap so far |
|
if(snap->vertPriority > 0 && snap->vertPriority <= snap->priority) |
|
{ |
|
Matrix3 tm = inode->GetObjectTM(t); |
|
GraphicsWindow *gw = vpt->getGW(); |
|
|
|
gw->setTransform(tm); |
|
|
|
Point2 fp = Point2((float)p->x, (float)p->y); |
|
IPoint3 screen3; |
|
Point2 screen2; |
|
Point3 vert(0.0f,0.0f,0.0f); |
|
|
|
gw->wTransPoint(&vert,&screen3); |
|
|
|
screen2.x = (float)screen3.x; |
|
screen2.y = (float)screen3.y; |
|
|
|
// Are we within the snap radius? |
|
int len = (int)Length(screen2 - fp); |
|
if(len <= snap->strength) |
|
{ |
|
// Is this priority better than the best so far? |
|
if(snap->vertPriority < snap->priority) |
|
{ |
|
snap->priority = snap->vertPriority; |
|
snap->bestWorld = vert * tm; |
|
snap->bestScreen = screen2; |
|
snap->bestDist = len; |
|
} |
|
// Closer than the best of this priority? |
|
else if(len < snap->bestDist) |
|
{ |
|
snap->priority = snap->vertPriority; |
|
snap->bestWorld = vert * tm; |
|
snap->bestScreen = screen2; |
|
snap->bestDist = len; |
|
} |
|
} |
|
} |
|
} |
|
|
|
void plRTLightBase::Snap(TimeValue t, INode* inode, SnapInfo *snap, IPoint2 *p, ViewExp *vpt) |
|
{ |
|
GenericSnap(t,inode,snap,p,vpt); |
|
} |
|
// This generic snap routine is used to snap to the 0,0,0 point of the given node. For lights, |
|
// this works to snap all types. |
|
|
|
|
|
|
|
RefTargetHandle plRTLightBase::GetReference(int i) |
|
{ |
|
/* |
|
kRefProjMap, |
|
kRefShadowProjMap, |
|
kRefShadowType, |
|
*///Texmap* MyMap; |
|
switch(i) |
|
{ |
|
case kRefGeneralLightProp: |
|
return NULL; |
|
case kRefProjMap: |
|
//if(fLightPB->GetTexmap(kProjMapTexButton, 0) != NULL) |
|
//{ |
|
// MyMap = fLightPB->GetTexmap(kProjMapTexButton, 0); |
|
//return (RefTargetHandle) MyMap; |
|
//}else |
|
return NULL; |
|
case kRefShadowProjMap: |
|
return NULL; |
|
case kRefShadowType: |
|
return NULL; |
|
case kRefOmniLight: |
|
case kRefSpotLight: |
|
case kRefTSpotLight: |
|
case kRefDirLight: |
|
case kRefTDirLight: |
|
case kRefProjDirLight: |
|
return (RefTargetHandle)fLightPB; |
|
default: |
|
return NULL; |
|
} |
|
|
|
} |
|
|
|
void plRTLightBase::SetReference(int ref, RefTargetHandle rtarg) |
|
{ |
|
//Texmap* MyMap; |
|
switch(ref) |
|
{ |
|
case kRefGeneralLightProp: |
|
return; |
|
case kRefProjMap: |
|
|
|
//MyMap = (Texmap *)rtarg; |
|
//fLightPB->SetValue(kProjMapTexButton, 0, MyMap); |
|
|
|
//if (projMapName) |
|
// projMapName->SetText(projMap?projMap->GetFullName().data():GetString(IDS_DB_NONE)); |
|
return; |
|
|
|
case kRefShadowProjMap: |
|
return; |
|
case kRefShadowType: |
|
return; |
|
case kRefOmniLight: |
|
case kRefSpotLight: |
|
case kRefTSpotLight: |
|
case kRefDirLight: |
|
case kRefTDirLight: |
|
case kRefProjDirLight: |
|
fLightPB = (IParamBlock2*)rtarg; break; |
|
} |
|
//fLightPB = (IParamBlock2*)rtarg; |
|
} |
|
|
|
RefResult plRTLightBase::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message) |
|
{ |
|
if( fLightPB ) |
|
{ |
|
ParamID param = fLightPB->LastNotifyParamID(); |
|
|
|
if( param == kAmbientOnlyStub ) |
|
{ |
|
fLightPB->EnableNotifications( false ); |
|
fLightPB->SetValue( kAmbientOnlyStub, TimeValue( 0 ), false ); |
|
// Assume this was true, since, well, we're IN NotifyRefChanged.... |
|
fLightPB->EnableNotifications( true ); |
|
|
|
return REF_SUCCEED; |
|
} |
|
} |
|
|
|
return REF_SUCCEED; |
|
} |
|
|
|
void plRTLightBase::BeginEditParams(IObjParam *ip, ULONG flags, Animatable *prev) |
|
{ |
|
fIP = ip; |
|
fClassDesc->BeginEditParams(ip, this, flags, prev); |
|
} |
|
|
|
void plRTLightBase::EndEditParams(IObjParam *ip, ULONG flags, Animatable *next) |
|
{ |
|
GenLight::EndEditParams( ip, flags, next ); |
|
fIP = NULL; |
|
fClassDesc->EndEditParams(ip, this, flags, next); |
|
} |
|
|
|
RefResult plRTLightBase::EvalLightState(TimeValue t, Interval& valid, LightState *ls) |
|
{ |
|
//t uselight; |
|
//#if 0 //fLightPB->GetInt(kLightOn, t); |
|
if(fLightPB->GetInt(kLightOn, t) == true) |
|
ls->color = GetRGBColor(t,valid); |
|
else |
|
ls->color = Color(0,0,0); |
|
ls->on = fLightPB->GetInt(kLightOn, t); |
|
ls->intens = GetIntensity(t, valid); |
|
if( this->ClassID() == RTSPOT_LIGHT_CLASSID || this->ClassID() == RTOMNI_LIGHT_CLASSID ) |
|
{ |
|
ls->hotsize = GetHotspot(t, valid); |
|
ls->fallsize = GetFallsize(t, valid); |
|
ls->useNearAtten = GetUseAttenNear(); |
|
ls->useAtten = GetUseAtten(); |
|
ls->attenStart = GetAtten(t, ATTEN_START, valid); |
|
ls->attenEnd = GetAtten(t, ATTEN_END, valid); |
|
}else |
|
{ |
|
ls->hotsize = 20; |
|
ls->fallsize = 10000; |
|
ls->useNearAtten = false; //GetUseAttenNear(); |
|
ls->useAtten = false; //GetUseAtten(); |
|
//ls->attenStart = GetAtten(t, ATTEN_START, valid); |
|
//ls->attenEnd = GetAtten(t, ATTEN_END, valid); |
|
|
|
|
|
} |
|
ls->shape = GW_SHAPE_CIRCULAR; //fLightPB->GetInt(kLightShapeRadio); |
|
|
|
ls->aspect = -1.0;//GetAspect(t, valid); |
|
ls->overshoot = false; //GetOvershoot(); |
|
ls->shadow = GetShadow(); |
|
ls->ambientOnly = false; //fLightPB->GetValue( kAmbiOnly,t, ls->ambientOnly, valid); //ls->ambientOnly = fLightP.AmbiOnly; |
|
ls->affectDiffuse = true; //fLightPB->GetInt(kDiffOn,t); //ls->affectDiffusey = fLightP.AmbiOnly; |
|
ls->affectSpecular = fLightPB->GetInt(kSpec,t); //ls- = fLightP.DiffOn;; |
|
|
|
//ls-> |
|
|
|
if( this->ClassID() == RTOMNI_LIGHT_CLASSID ) |
|
ls->type = OMNI_LGT; |
|
else if( this->ClassID() == RTDIR_LIGHT_CLASSID || this->ClassID() == RTPDIR_LIGHT_CLASSID ) |
|
ls->type = DIRECT_LGT; |
|
else |
|
ls->type = SPOT_LGT; |
|
|
|
return REF_SUCCEED; |
|
} |
|
|
|
|
|
#if 0 |
|
#define PLASMAOBJ_DATA_CHUNK 1 |
|
|
|
IOResult plRTLightBase::Save(ISave* isave) |
|
{ |
|
return IO_OK; |
|
} |
|
|
|
IOResult plRTLightBase::Load(ILoad* iload) |
|
{ |
|
ULONG nb; |
|
IOResult res; |
|
int numrefs = 0; |
|
|
|
while (IO_OK == (res = iload->OpenChunk())) |
|
{ |
|
if (iload->CurChunkID() == PLASMAOBJ_DATA_CHUNK) |
|
res = iload->Read(&numrefs, sizeof(int), &nb); |
|
iload->CloseChunk(); |
|
|
|
if (res != IO_OK) |
|
return res; |
|
} |
|
|
|
return IO_OK; |
|
} |
|
|
|
#endif |
|
|
|
|
|
ObjLightDesc *plRTLightBase::CreateLightDesc(INode *n, BOOL forceShadowBuf) |
|
{ |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
void plRTLightBase::SetHotspot(TimeValue t, float f) |
|
{ |
|
if(!IsSpot()) |
|
return; |
|
if(f < 0.5f) |
|
f = 0.5f; |
|
if(!IsDir() && (f > 179.5f)) |
|
f = 179.5f; |
|
//pblock->SetValue( PB_HOTSIZE, t, f ); |
|
fLightPB->SetValue(kHotSpot, t, f); |
|
|
|
//fLightP.HotSpot = f; |
|
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); |
|
} |
|
|
|
float plRTLightBase::GetHotspot(TimeValue t, Interval& valid) |
|
{ |
|
Interval iv; |
|
|
|
if(!IsSpot() && !IsDir()) |
|
return -1.0f; |
|
float f; |
|
//pblock->GetValue( PB_HOTSIZE, t, f, valid ); |
|
if(IsSpot()) |
|
fLightPB->GetValue(kHotSpot, t, f, FOREVER); |
|
else |
|
f = 20.0; |
|
|
|
if(GetFallsize(t, iv) < f ) |
|
return GetFallsize(t, iv) - 2.0; |
|
return f; |
|
} |
|
|
|
void plRTLightBase::SetRGBColor(TimeValue t, Point3& rgb) |
|
{ |
|
//fLightPB->SetValue(plRTLightBase::kRed, t, rgb.x); |
|
//fLightPB->SetValue(plRTLightBase::kGreen, t, rgb.y); |
|
//fLightPB->SetValue(plRTLightBase::kBlue, t, rgb.z); |
|
fLightPB->SetValue(kLightColor, t, rgb ); |
|
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); |
|
|
|
|
|
} |
|
|
|
Point3 plRTLightBase::GetRGBColor(TimeValue t, Interval &valid) |
|
{ |
|
//Point3 Foo = Point3(fLightPB->GetInt(plRTLightBase::kRed, t), fLightPB->GetInt(plRTLightBase::kGreen, t), fLightPB->GetInt(plRTLightBase::kBlue, t)); |
|
Point3 rgb; |
|
fLightPB->GetValue( kLightColor, t, rgb, valid ); |
|
return rgb; |
|
} |
|
|
|
|
|
|
|
void plRTLightBase::SetFallsize(TimeValue t, float f) |
|
{ |
|
if(!IsSpot() ) |
|
return; |
|
if(f < 0.5f) |
|
f = 0.5f; |
|
if(!IsDir() && (f > 179.5f)) |
|
f = 179.5f; |
|
//pblock->SetValue( PB_FALLSIZE, t, f ); |
|
fLightPB->SetValue(kFallOff, t, f); |
|
|
|
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); |
|
} |
|
|
|
float plRTLightBase::GetFallsize(TimeValue t, Interval& valid) |
|
{ |
|
if(!IsSpot() && !IsDir()) |
|
return -1.0f; |
|
float f; |
|
|
|
//pblock->GetValue( PB_FALLSIZE, t, f, valid ); |
|
if(IsSpot()) |
|
fLightPB->GetValue(kFallOff, t, f, valid); |
|
else |
|
f = 200.0; |
|
return f; |
|
} |
|
|
|
|
|
void plRTLightBase::SetAtten(TimeValue t, int which, float f) |
|
{ |
|
|
|
if(which != ATTEN_START) |
|
fLightPB->SetValue(kAttenMaxFalloffEdit, t, f); |
|
|
|
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); |
|
} |
|
|
|
|
|
float plRTLightBase::GetAtten(TimeValue t, int which, Interval& valid) |
|
{ |
|
float f = 0.0; |
|
//if(fLightPB->GetInt(kEndAttenFar, t) == 1) |
|
//if(LyteType == RT_OMNI) |
|
// fLightPB->GetValue(kStartAttenFar, t, f, FOREVER); |
|
//else |
|
// fLightPB->GetValue(kStartAttenNear, t, f, FOREVER); |
|
if(which == LIGHT_ATTEN_START) |
|
return f; |
|
else |
|
return( fLightPB->GetFloat(kAttenMaxFalloffEdit, t)); |
|
|
|
//return f; |
|
} |
|
|
|
|
|
void plRTLightBase::SetTDist(TimeValue t, float f) |
|
{ |
|
// int i; |
|
// fLightPB->GetInt(kLightType, t, i); |
|
|
|
//pblock->SetValue( PB_TDIST, t, f ); |
|
//To be implemented. |
|
if( IHasAttenuation() ) |
|
fLightPB->SetValue(kAttenMaxFalloffEdit, t, f); |
|
//fLightPB->SetValue(kTargetDist, t, f); |
|
|
|
NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); |
|
} |
|
|
|
float plRTLightBase::GetTDist(TimeValue t, Interval& valid) |
|
{ |
|
if(!IsSpot()) |
|
return -1.0f; |
|
// int i; |
|
//fLightPB->GetValue(kLightType, t, i, valid); |
|
float f = -1.0; |
|
|
|
fLightPB->GetFloat( kAttenMaxFalloffEdit, t ); |
|
|
|
//pblock->GetValue( PB_TDIST, t, f, valid ); |
|
//fLightPB->GetValue(kTargetDist, t, f, valid); |
|
return f; |
|
} |
|
|
|
void plRTLightBase::SetConeDisplay(int s, int notify) |
|
{ |
|
if(!IsDir()) |
|
fLightPB->SetValue(kShowConeBool, 0, s); |
|
if(notify && IsSpot()) |
|
NotifyDependents(FOREVER, PART_OBJ, REFMSG_CHANGE); |
|
} |
|
|
|
BOOL plRTLightBase::GetConeDisplay(void) |
|
{ |
|
if(!IsDir()) |
|
return fLightPB->GetInt(kShowConeBool); |
|
return |
|
false; |
|
} |
|
|
|
|
|
void plRTLightBase::SetProjMap(BitmapInfo* pmap) |
|
{ |
|
//plLayerTex* MyMap = TRACKED_NEW plLayerTex; |
|
if(!fTex) |
|
fTex = TRACKED_NEW plLayerTex; |
|
fTex->SetBitmap(pmap); |
|
ReplaceReference(kRefProjMap,fTex); |
|
|
|
IParamBlock2 *bitmapPB = fTex->GetParamBlockByID(plLayerTex::kBlkBitmap); |
|
bitmapPB->SetValue(kBmpUseBitmap, 0, 1); |
|
|
|
// This is set in the call to fTex->SetBitmap(pmap) |
|
//PBBitmap pbb(*pmap); |
|
//bitmapPB->SetValue(kBmpBitmap, 0, &pbb); |
|
|
|
//Texmap* MyMap; |
|
//fLightPB->GetValue(kProjMapTexButton, 0, MyMap, FOREVER); |
|
if (fTex) fLightPB->SetValue(kUseProjectorBool, 0, true); |
|
NotifyDependents(FOREVER,0,REFMSG_SUBANIM_STRUCTURE_CHANGED); |
|
if( fLightPB->GetMap() ) |
|
{ |
|
fLightPB->GetMap()->Invalidate(kProjMapTexButton); |
|
fLightPB->GetMap()->Invalidate(kUseProjectorBool); |
|
} |
|
|
|
} |
|
|
|
|
|
BOOL plRTLightBase::GetShadow() |
|
{ |
|
return fLightPB->GetInt(kCastShadows); |
|
} |
|
|
|
void plRTLightBase::SetShadow(int a) |
|
{ |
|
fLightPB->SetValue(kCastShadows, 0, 1); |
|
} |
|
|
|
Texmap* plRTLightBase::GetProjMap() |
|
{ |
|
if( !fLightPB->GetInt(kUseProjectorBool) ) |
|
return NULL; |
|
|
|
if( GetTex() ) |
|
{ |
|
const char* dbgTexName = GetTex()->GetName(); |
|
|
|
IParamBlock2 *bitmapPB = fTex->GetParamBlockByID(plLayerTex::kBlkBitmap); |
|
hsAssert(bitmapPB, "LayerTex with no param block"); |
|
|
|
int noCompress = fLightPB->GetInt(kProjNoCompress); |
|
int noMip = fLightPB->GetInt(kProjNoMip); |
|
bitmapPB->SetValue(kBmpNonCompressed, TimeValue(0), noCompress); |
|
bitmapPB->SetValue(kBmpNoFilter, TimeValue(0), noMip); |
|
} |
|
|
|
return (Texmap*) GetTex(); |
|
} |
|
|
|
void plRTLightBase::UpdateTargDistance(TimeValue t, INode* inode) |
|
{ |
|
if( this->ClassID() == RTSPOT_LIGHT_CLASSID ) |
|
{ |
|
Point3 pt,v[3]; |
|
if (GetTargetPoint(t, inode, pt)) |
|
{ |
|
Matrix3 tm = inode->GetObjectTM(t); |
|
float den = FLength(tm.GetRow(2)); |
|
float dist = (den!=0) ? FLength(tm.GetTrans()-pt) / den : 0.0f; |
|
fLightPB->SetValue(kAttenMaxFalloffEdit, t, dist); |
|
|
|
// fLightPB->SetValue(kTargetDist, t, dist); |
|
//TCHAR buf[40]; |
|
//_stprintf(buf,_T("%0.3f"),targDist); |
|
//SetWindowText(GetDlgItem(hSpotLight,IDC_TARG_DISTANCE),buf); |
|
} |
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// |
|
// |
|
// |
|
// Target Creation for Targeted Lights... |
|
// |
|
// |
|
// |
|
|
|
|
|
#if 0 |
|
class TSpotCreationManager : public MouseCallBack, ReferenceMaker |
|
{ |
|
private: |
|
CreateMouseCallBack *createCB; |
|
INode *lgtNode,*targNode; |
|
plRTLightBase *lgtObject; |
|
TargetObject *targObject; |
|
int attachedToNode; |
|
IObjCreate *createInterface; |
|
ClassDesc *cDesc; |
|
Matrix3 mat; // the nodes TM relative to the CP |
|
IPoint2 pt0; |
|
int ignoreSelectionChange; |
|
int lastPutCount; |
|
|
|
void CreateNewObject(); |
|
|
|
int NumRefs() { return 1; } |
|
RefTargetHandle GetReference(int i) { return (RefTargetHandle)lgtNode; } |
|
void SetReference(int i, RefTargetHandle rtarg) { lgtNode = (INode *)rtarg; } |
|
|
|
// StdNotifyRefChanged calls this, which can change the partID to new value |
|
// If it doesnt depend on the particular message& partID, it should return |
|
// REF_DONTCARE |
|
RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, |
|
PartID& partID, RefMessage message); |
|
|
|
public: |
|
void Begin( IObjCreate *ioc, ClassDesc *desc ); |
|
void End(); |
|
|
|
TSpotCreationManager() { ignoreSelectionChange = FALSE; } |
|
int proc( HWND hwnd, int msg, int point, int flag, IPoint2 m ); |
|
BOOL SupportAutoGrid(){return TRUE;} |
|
}; |
|
|
|
|
|
#define CID_TSPOTCREATE CID_USER + 3 |
|
|
|
class TSpotCreateMode : public CommandMode { |
|
TSpotCreationManager proc; |
|
public: |
|
void Begin( IObjCreate *ioc, ClassDesc *desc ) { proc.Begin( ioc, desc ); } |
|
void End() { proc.End(); } |
|
|
|
int Class() { return CREATE_COMMAND; } |
|
int ID() { return CID_TSPOTCREATE; } |
|
MouseCallBack *MouseProc(int *numPoints) { *numPoints = 1000000; return &proc; } |
|
ChangeForegroundCallback *ChangeFGProc() { return CHANGE_FG_SELECTED; } |
|
BOOL ChangeFG( CommandMode *oldMode ) { return (oldMode->ChangeFGProc() != CHANGE_FG_SELECTED); } |
|
void EnterMode() { |
|
} |
|
void ExitMode() { |
|
} |
|
BOOL IsSticky() { return FALSE; } |
|
}; |
|
|
|
static TSpotCreateMode theTSpotCreateMode; |
|
|
|
#endif |
|
|
|
#if 0 |
|
void TSpotCreationManager::Begin( IObjCreate *ioc, ClassDesc *desc ) |
|
{ |
|
createInterface = ioc; |
|
cDesc = desc; |
|
attachedToNode = FALSE; |
|
createCB = NULL; |
|
lgtNode = NULL; |
|
targNode = NULL; |
|
lgtObject = NULL; |
|
targObject = NULL; |
|
CreateNewObject(); |
|
} |
|
|
|
void TSpotCreationManager::End() |
|
{ |
|
if ( lgtObject ) { |
|
lgtObject->EndEditParams( (IObjParam*)createInterface, END_EDIT_REMOVEUI, NULL); |
|
if ( !attachedToNode ) { |
|
// RB 4-9-96: Normally the hold isn't holding when this |
|
// happens, but it can be in certain situations (like a track view paste) |
|
// Things get confused if it ends up with undo... |
|
theHold.Suspend(); |
|
//delete lgtObject; |
|
lgtObject->DeleteThis(); // JBW 11.1.99, this allows scripted plugin lights to delete cleanly |
|
lgtObject = NULL; |
|
theHold.Resume(); |
|
// RB 7/28/97: If something has been put on the undo stack since this object was created, we have to flush the undo stack. |
|
if (theHold.GetGlobalPutCount()!=lastPutCount) { |
|
GetSystemSetting(SYSSET_CLEAR_UNDO); |
|
} |
|
macroRec->Cancel(); // JBW 4/23/99 |
|
} |
|
else if ( lgtNode ) { |
|
// Get rid of the reference. |
|
DeleteReference(0); // sets lgtNode = NULL |
|
} |
|
} |
|
} |
|
|
|
RefResult TSpotCreationManager::NotifyRefChanged( |
|
Interval changeInt, |
|
RefTargetHandle hTarget, |
|
PartID& partID, |
|
RefMessage message) |
|
{ |
|
switch (message) { |
|
|
|
case REFMSG_PRENOTIFY_PASTE: |
|
case REFMSG_TARGET_SELECTIONCHANGE: |
|
if ( ignoreSelectionChange ) { |
|
break; |
|
} |
|
if (lgtObject && lgtNode==hTarget) { |
|
// this will set camNode== NULL; |
|
DeleteReference(0); |
|
goto endEdit; |
|
} |
|
// fall through |
|
|
|
case REFMSG_TARGET_DELETED: |
|
if ( lgtObject && lgtNode==hTarget ) { |
|
endEdit: |
|
lgtObject->EndEditParams( (IObjParam*)createInterface, 0, NULL); |
|
lgtObject = NULL; |
|
lgtNode = NULL; |
|
CreateNewObject(); |
|
attachedToNode = FALSE; |
|
} |
|
else if (targNode==hTarget) { |
|
targNode = NULL; |
|
targObject = NULL; |
|
} |
|
break; |
|
} |
|
return REF_SUCCEED; |
|
} |
|
|
|
|
|
void TSpotCreationManager::CreateNewObject() |
|
{ |
|
lgtObject = (plRTLightBase *)cDesc->Create(); |
|
lastPutCount = theHold.GetGlobalPutCount(); |
|
|
|
macroRec->BeginCreate(cDesc); // JBW 4/23/99 |
|
|
|
// Start the edit params process |
|
if ( lgtObject ) { |
|
lgtObject->BeginEditParams( (IObjParam*)createInterface, BEGIN_EDIT_CREATE, NULL ); |
|
} |
|
} |
|
|
|
static void whoa(){}; |
|
|
|
static BOOL needToss; |
|
|
|
int TSpotCreationManager::proc( |
|
HWND hwnd, |
|
int msg, |
|
int point, |
|
int flag, |
|
IPoint2 m ) |
|
{ |
|
int res; |
|
TSTR targName; |
|
ViewExp *vpx = createInterface->GetViewport(hwnd); |
|
assert( vpx ); |
|
|
|
switch ( msg ) { |
|
case MOUSE_POINT: |
|
switch ( point ) { |
|
case 0: |
|
pt0 = m; |
|
assert( lgtObject ); |
|
vpx->CommitImplicitGrid(m, flag); //KENNY MERGE |
|
if ( createInterface->SetActiveViewport(hwnd) ) { |
|
return FALSE; |
|
} |
|
|
|
if (createInterface->IsCPEdgeOnInView()) { |
|
res = FALSE; |
|
goto done; |
|
} |
|
|
|
// if lights were hidden by category, re-display them |
|
GetCOREInterface()->SetHideByCategoryFlags( |
|
GetCOREInterface()->GetHideByCategoryFlags() & ~HIDE_LIGHTS); |
|
|
|
if ( attachedToNode ) { |
|
// send this one on its way |
|
lgtObject->EndEditParams( (IObjParam*)createInterface, 0, NULL); |
|
macroRec->EmitScript(); // JBW 4/23/99 |
|
|
|
// Get rid of the reference. |
|
if (lgtNode) |
|
DeleteReference(0); |
|
|
|
// new object |
|
CreateNewObject(); // creates lgtObject |
|
} |
|
|
|
needToss = theHold.GetGlobalPutCount()!=lastPutCount; |
|
|
|
theHold.Begin(); // begin hold for undo |
|
mat.IdentityMatrix(); |
|
|
|
// link it up |
|
lgtNode = createInterface->CreateObjectNode( lgtObject); |
|
attachedToNode = TRUE; |
|
assert( lgtNode ); |
|
createCB = lgtObject->GetCreateMouseCallBack(); |
|
createInterface->SelectNode( lgtNode ); |
|
|
|
// Create target object and node |
|
targObject = TRACKED_NEW TargetObject; |
|
assert(targObject); |
|
targNode = createInterface->CreateObjectNode( targObject); |
|
assert(targNode); |
|
targName = lgtNode->GetName(); |
|
targName += GetString(IDS_DB_DOT_TARGET); |
|
targNode->SetName(targName); |
|
|
|
// hook up camera to target using lookat controller. |
|
createInterface->BindToTarget(lgtNode,targNode); |
|
|
|
// Reference the new node so we'll get notifications. |
|
MakeRefByID( FOREVER, 0, lgtNode); |
|
|
|
// Position camera and target at first point then drag. |
|
mat.IdentityMatrix(); |
|
//mat[3] = vpx->GetPointOnCP(m); |
|
#ifdef _3D_CREATE |
|
mat.SetTrans( vpx->SnapPoint(m,m,NULL,SNAP_IN_3D) ); |
|
#else |
|
mat.SetTrans(vpx->SnapPoint(m,m,NULL,SNAP_IN_PLANE)); |
|
#endif |
|
createInterface->SetNodeTMRelConstPlane(lgtNode, mat); |
|
createInterface->SetNodeTMRelConstPlane(targNode, mat); |
|
lgtObject->Enable(1); |
|
|
|
ignoreSelectionChange = TRUE; |
|
createInterface->SelectNode( targNode,0); |
|
ignoreSelectionChange = FALSE; |
|
res = TRUE; |
|
break; |
|
|
|
case 1: |
|
if (Length(m-pt0)<2) |
|
goto abort; |
|
//mat[3] = vpx->GetPointOnCP(m); |
|
#ifdef _3D_CREATE |
|
mat.SetTrans( vpx->SnapPoint(m,m,NULL,SNAP_IN_3D) ); |
|
#else |
|
mat.SetTrans(vpx->SnapPoint(m,m,NULL,SNAP_IN_PLANE)); |
|
#endif |
|
macroRec->Disable(); // JBW 4/23/99 |
|
createInterface->SetNodeTMRelConstPlane(targNode, mat); |
|
macroRec->Enable(); |
|
|
|
ignoreSelectionChange = TRUE; |
|
createInterface->SelectNode( lgtNode); |
|
ignoreSelectionChange = FALSE; |
|
|
|
theHold.Accept(IDS_DS_CREATE); |
|
|
|
createInterface->AddLightToScene(lgtNode); |
|
createInterface->RedrawViews(createInterface->GetTime()); |
|
|
|
res = FALSE; // We're done |
|
break; |
|
} |
|
break; |
|
|
|
case MOUSE_MOVE: |
|
//mat[3] = vpx->GetPointOnCP(m); |
|
#ifdef _3D_CREATE |
|
mat.SetTrans( vpx->SnapPoint(m,m,NULL,SNAP_IN_3D) ); |
|
#else |
|
mat.SetTrans(vpx->SnapPoint(m,m,NULL,SNAP_IN_PLANE)); |
|
#endif |
|
macroRec->Disable(); // JBW 4/23/99 |
|
createInterface->SetNodeTMRelConstPlane(targNode, mat); |
|
macroRec->Enable(); |
|
createInterface->RedrawViews(createInterface->GetTime()); |
|
|
|
macroRec->SetProperty(lgtObject, _T("target"), // JBW 4/23/99 |
|
mr_create, Class_ID(TARGET_CLASS_ID, 0), GEOMOBJECT_CLASS_ID, 1, _T("transform"), mr_matrix3, &mat); |
|
|
|
res = TRUE; |
|
break; |
|
|
|
case MOUSE_FREEMOVE: |
|
SetCursor(LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CROSS_HAIR))); |
|
#ifdef _OSNAP |
|
//Snap Preview |
|
#ifdef _3D_CREATE |
|
vpx->SnapPreview(m,m,NULL, SNAP_IN_3D); |
|
#else |
|
vpx->SnapPreview(m,m,NULL, SNAP_IN_PLANE); |
|
#endif |
|
#endif |
|
vpx->TrackImplicitGrid(m); //KENNY MERGE |
|
break; |
|
|
|
case MOUSE_PROPCLICK: |
|
// right click while between creations |
|
createInterface->RemoveMode(NULL); |
|
break; |
|
|
|
case MOUSE_ABORT: |
|
abort: |
|
assert( lgtObject ); |
|
lgtObject->EndEditParams( (IObjParam*)createInterface,0,NULL); |
|
// Toss the undo stack if param changes have been made |
|
macroRec->Cancel(); // JBW 4/23/99 |
|
theHold.Cancel(); // deletes both the camera and target. |
|
if (needToss) |
|
GetSystemSetting(SYSSET_CLEAR_UNDO); |
|
lgtNode = NULL; |
|
targNode = NULL; |
|
createInterface->RedrawViews(createInterface->GetTime()); |
|
CreateNewObject(); |
|
attachedToNode = FALSE; |
|
res = FALSE; |
|
} |
|
|
|
done: |
|
//KENNY MERGE |
|
if ((res == CREATE_STOP)||(res==CREATE_ABORT)) |
|
vpx->ReleaseImplicitGrid(); |
|
createInterface->ReleaseViewport(vpx); |
|
return res; |
|
} |
|
|
|
|
|
#endif
|
|
|