📄 ch3rendr.cpp
字号:
/*----------------------------------------------------------------------------
_ _ _
/\ | | | (_)
/ \ _ __ __| |_ __ ___ _ __ ___ ___ __| |_ __ _
/ /\ \ | '_ \ / _` | '__/ _ \| '_ ` _ \ / _ \/ _` | |/ _` |
/ ____ \| | | | (_| | | | (_) | | | | | | __/ (_| | | (_| |
/_/ \_\_| |_|\__,_|_| \___/|_| |_| |_|\___|\__,_|_|\__,_|
The contents of this file are subject to the Andromedia Public
License Version 1.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.andromedia.com/APL/
Software distributed under the License is distributed on an
"AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is Pueblo client code, released November 4, 1998.
The Initial Developer of the Original Code is Andromedia Incorporated.
Portions created by Andromedia are Copyright (C) 1998 Andromedia
Incorporated. All Rights Reserved.
Andromedia Incorporated 415.365.6700
818 Mission Street - 2nd Floor 415.365.6701 fax
San Francisco, CA 94103
Contributor(s):
--------------------------------------------------------------------------
Chaco team: Dan Greening, Glenn Crocker, Jim Doubek,
Coyote Lussier, Pritham Shetty.
Wrote and designed original codebase.
------------------------------------------------------------------------------
Implementation for the ChRenderContext class for Intel 3DR.
----------------------------------------------------------------------------*/
// $Header: /home/cvs/chaco/modules/client/msw/ChGraphx/Ch3Rendr.cpp,v 2.109 1996/09/26 02:06:59 pritham Exp $
#include "grheader.h"
#include <QvInfo.h>
#include <QvState.h>
#include "ChMaze.h"
#include "ChRenderData.h"
#include "ChMazDep.h"
#include "CvConvrt.h"
#include "CvTrnsfm.h"
#include "CvNormal.h"
#include "CvInstnc.h"
#include "CvTextur.h"
#include "CvType.h"
#include "CvHitTst.h"
#include "CvMaterl.h"
#include "ChSphere.h"
#include "ChRLImg.h"
#include <ChSFImage.h>
#include "ChCollision.h"
#if defined(CH_USE_D3D)
#include <d3d.h>
#endif
#include <malloc.h>
#if defined(WIN32)
#include <sys/timeb.h>
#endif
#include <ChCore.h>
#include <ChUtil.h>
// Even if we render purely retained, we need this if we use RL
#if (defined(CH_USE_RLAB))
#include "imode.h"
#endif
// Use our debugging allocator - caution do not use for production
// it's too slow and probably won't work for 2 dlls
//#define USE_OUR_RL_ALLOC 1
#define new DEBUG_NEW
#if (defined(CH_USE_RLAB))
const ChNrRenderQuality stdQuality = RenderGouraud ; // // RLRenderPhong
//const ChNrColorModel stdColorModel = RLColourRGB; // RLColourRamp
const ChNrColorModel stdColorModel = RLColourRamp; // RLColourRGB
#if defined(_DEBUG) && defined(USE_OUR_RL_ALLOC)
void* ChRLAlloc(size_t);
void* ChRLRealloc(void*, size_t);
void ChRLFree(void*);
#endif // defined(_DEBUG) && defined(USE_OUR_RL_ALLOC)
#elif defined(CH_USE_D3D)
const ChNrRenderQuality stdQuality = RenderGouraud | D3DRMLIGHT_ON | D3DRMFILL_SOLID; // // RLRenderPhong
//const ChNrColorModel stdColorModel = RLColourRGB; // RLColourRamp
//const ChNrColorModel stdColorModel = RLColourRamp; // RLColourRGB
#endif
class ChCameraEntry
{
protected:
string m_name;
QvNode *m_pCamera;
ChGraphicPageID m_page;
public:
ChCameraEntry(string name, QvNode *pCamera, ChGraphicPageID page) :
m_name(name), m_pCamera(pCamera), m_page(page) {};
string &GetName() {return m_name;};
QvNode *GetCamera(){ return m_pCamera;};
};
ChRenderContext::ChRenderContext() :
#if defined(CH_USE_3DR)
m_hGC(0),
m_numLightsOn(0),
#else
m_pStack(0),
m_sceneFrame(0),
m_cameraFrame(0),
m_headlightFrame(0),
m_viewport(0),
m_boolContinueConstruction( true ),
m_pCollisionSensor(0),
m_maxTransparency(false),
m_pBackgroundTexture(0),
m_pBackGroundNode(0),
m_backgroundFrame(0),
#endif
#if defined(CH_USE_D3D)
m_DD(0),
m_D3D(0),
m_D3DRM(0),
m_DDClipper(0),
#endif
m_hRC(0),
m_hDC(0),
m_pWnd(0),
m_userShading( defaultShading ),
m_pRootInstance(0),
m_cameraCount(0),
m_pCamera(0),
m_pDefaultCamera(0),
m_boolDirty(false),
m_boolSettingsDirty(false),
m_boolAnimating(false),
m_ppDefaults(0),
m_iShapeCount( 0 ),
m_iFrameCount( 0 ),
m_iTotalWork( 0 )
{
for(int j=0; j<CH_MAX_SPHERE_LEVEL+1; j++)
{
m_pSpheres[j] = 0;
}
#if (defined(CH_USE_RLAB))
#if defined(_DEBUG) && defined(USE_OUR_RL_ALLOC)
RLSetAllocator(ChRLAlloc, ChRLRealloc, ChRLFree );
#endif // defined(_DEBUG) && defined(USE_OUR_RL_ALLOC)
#else
m_boolThreaded = false;
#endif
m_boolThreaded = !!(ChUtil::GetSystemProperties() & CH_PROP_MULTITHREADED);
if(IsThreaded())
{
::InitializeCriticalSection(&m_sceneCriticalSection);
::InitializeCriticalSection(&m_qvCriticalSection);
::InitializeCriticalSection(&m_constructionCriticalSection);
::InitializeCriticalSection(&m_reconstructionCriticalSection);
// Reconstruction thread events
m_hReconstructEvents[reconstructInstance] = ::CreateEvent( 0, false, false, 0 );
ASSERT( m_hReconstructEvents[reconstructInstance] );
m_hReconstructEvents[abortReconstruct] = ::CreateEvent( 0, false, false, 0 );
ASSERT( m_hReconstructEvents[abortReconstruct] );
m_hReconstructEvents[endThread] = ::CreateEvent( 0, false, false, 0 );
ASSERT( m_hReconstructEvents[endThread] );
// Start the reconstruction thread
CWinThread *pThread = ::AfxBeginThread(ReConstructInstanceThread,
(void*)this, THREAD_PRIORITY_BELOW_NORMAL );
ASSERT( pThread );
// end of construction event
m_hConstructDoneEvent = ::CreateEvent( 0, false, false, 0 );
ASSERT( m_hConstructDoneEvent );
}
}
#if defined(_DEBUG) && defined(USE_OUR_RL_ALLOC)
static int numRLAllocs = 0;
static int numRLBytes = 0;
void* ChRLAlloc(size_t size)
{
numRLAllocs++;
numRLBytes+=size;
if(!(numRLAllocs % 100))
{
TRACE2("Number RL allocs: %d, bytes %d\n", numRLAllocs, numRLBytes);
}
char *bytes = new char[size+8];
int *pSize = (int*)bytes;
*pSize++ = 0xcacacaca;
*pSize = size;
return (bytes+8);
}
void* ChRLRealloc(void* ptr, size_t size)
{
// Not optimal - just for debugging
char *bytes = new char[size+8];
int *pSize = (int*)bytes;
*pSize++ = 0xcacacaca;
*pSize = size;
char *oldPtr = ((char*)ptr)-8;
int *pTag = (int*)oldPtr;
if(*pTag == 0xcacacaca)
{
if(bytes)
{
int oldSize = *(((int*)oldPtr)+1);
memcpy(bytes + 8, oldPtr + 8, min(size_t(oldSize), size));
numRLBytes+=size;
numRLBytes-=oldSize;
}
delete [] oldPtr;
}
else
{
TRACE("Attempt to resize block that's not ours!\n");
}
return (bytes+8);
}
void ChRLFree(void* ptr)
{
numRLAllocs--;
char *oldPtr = ((char*)ptr)-8;
int *pSize = (int*)oldPtr;
int oldSize = pSize[1];
if(*pSize == 0xcacacaca)
{
delete [] oldPtr;
numRLBytes-=oldSize;
}
}
#endif // defined(_DEBUG) && defined(USE_OUR_RL_ALLOC)
ChRenderContext::~ChRenderContext()
{
RemoveCameras();
#if (defined(CH_USE_D3D) || defined(CH_USE_RLAB))
// cleanup the synchronization objects
if(IsThreaded())
{
::CloseHandle( m_hReconstructEvents[reconstructInstance] );
::CloseHandle( m_hReconstructEvents[abortReconstruct] );
::CloseHandle( m_hReconstructEvents[endThread] );
::CloseHandle( m_hConstructDoneEvent);
::DeleteCriticalSection(&m_sceneCriticalSection);
::DeleteCriticalSection(&m_qvCriticalSection);
::DeleteCriticalSection(&m_constructionCriticalSection);
::DeleteCriticalSection(&m_reconstructionCriticalSection);
}
delete m_pCollisionSensor; // delete the collision sensor viewport
m_pCollisionSensor = 0;
#endif
if ( ChMazeWnd::GetNumMazeObjects() == 0 )
{ // This is the last object, cleanup all static renderdata objects
ChQvRenderBaseData::Term();
}
#if (defined(CH_USE_D3D))
// Clean up interfaces
RELEASE_INTERFACE(m_DDClipper);
RELEASE_INTERFACE(m_D3DRM);
RELEASE_INTERFACE(m_D3D);
RELEASE_INTERFACE(m_DD);
#endif
}
ChRenderContext* ChRenderContext::SetRoot(ChQvInstance *pRootInstance)
{
if(m_pRootInstance != pRootInstance && m_pRootInstance) m_pRootInstance->Release();
m_pRootInstance = pRootInstance;
return this;
};
#if ((defined(CH_USE_RLAB)) || defined(CH_USE_D3D))
#if (defined(CH_USE_RLAB))
void CameraCallback(ChNrFrame frame, void * arg)
#else
void CameraCallback(ChNrFrame frame, void * arg, float delta)
#endif
{
#if 1
//ASSERT(arg);
if(arg)
{
QvNode *pCamera = ((ChRenderContext*)arg)->GetCurrentCamera();
if(pCamera)
{
ChQvPCameraRenderData *pRenderData = (ChQvPCameraRenderData *)(pCamera->GetRenderData());
pRenderData->OnTick();
}
}
#endif
}
#endif
#if 0 && defined(_DEBUG)
int GetHeapDetails(HANDLE heap, int &numBlocks, int &numBytes)
{
numBlocks = 0;
numBytes = 0;
PROCESS_HEAP_ENTRY entry;
entry.lpData = 0;
HeapLock(heap);
while(HeapWalk(heap, &entry))
{
numBlocks ++;
numBytes += entry.cbData;
}
HeapUnlock(heap);
return numBlocks;
}
void CheckMemory()
{
#if 0 && defined(_DEBUG)
HANDLE heaps[200];
int numHeaps = GetProcessHeaps( sizeof(heaps) / sizeof(heaps[0]), heaps);
TRACE1("Number of heaps = %d\n", numHeaps);
HANDLE sysHeap = GetProcessHeap();
int numBytes, numBlocks;
for(int j=0; j < numHeaps; j++)
{
GetHeapDetails(heaps[j], numBlocks, numBytes);
TRACE2("Heap blocks = %d, bytes = %d", numBlocks, numBytes);
if(heaps[j] == sysHeap) TRACE(" (process heap)");
if(!HeapValidate(heaps[j], 0, 0)) TRACE(" INVALID HEAP!");
TRACE("\n");
}
_HEAPINFO heapInfo;
int heapRet;
numBlocks = numBytes = 0;
int numInUseBlocks = 0, numInUseBytes = 0;
memset(&heapInfo, 0, sizeof(heapInfo));
while((heapRet = _heapwalk( &heapInfo)) == _HEAPOK)
{
numBlocks ++;
numBytes += heapInfo._size;
if(heapInfo._useflag)
{
numInUseBlocks ++;
numInUseBytes += heapInfo._size;
}
}
TRACE2("CRT Heap total blocks = %d, bytes = %d", numBlocks, numBytes);
TRACE("\n");
TRACE2("CRT Heap in use blocks = %d, bytes = %d", numInUseBlocks, numInUseBytes);
TRACE("\n");
if(heapRet != _HEAPEND) TRACE("CRT Heap invalid!\n");
char *p = (char*)malloc(2);
free(p);
static int passCount = 0;
static CMemoryState msLast;
passCount++;
if (passCount >= 3)
{
//AfxDumpMemoryLeaks();
CMemoryState msNow;
msNow.Checkpoint();
if (msNow.m_lCounts[CMemoryState::objectBlock] != 0 ||
msNow.m_lCounts[CMemoryState::bitBlock] != 0)
{
// dump objects since since difference detected.
TRACE0("Detected memory growth!\n");
afxDump.SetDepth(1); // just 1 line each
//CMemoryState msEmpty; // construct empty memory state object
msLast.DumpAllObjectsSince();
}
msLast.Checkpoint();
}
#endif
}
#else
#define CheckMemory()
#endif
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
void SceneDestroyCallback(ChNrObject obj, void * arg)
{
//TRACE("Scene Destroyed\n");
}
void ViewportDestroyCallback(ChNrObject obj, void * arg)
{
//TRACE("Viewport Destroyed\n");
}
void CameraDestroyCallback(ChNrObject obj, void * arg)
{
//TRACE("Camera frame Destroyed\n");
}
#endif
ChRenderContext* ChRenderContext::ResetScene()
{
// Before we reset the scene we need to terminate all threads currently
// running for this instance
#if (defined(CH_USE_RLAB)) || defined(CH_USE_D3D)
// Stop all currently active construction threads because we have a new scene
AbortConstruction();
// at this point there should be only one
// thread running
#endif
CheckMemory();
// remove all textures in our queue for this scene
if ( !m_textureQueue.IsEmpty() )
{
ChPosition pos = m_textureQueue.GetHeadPosition();
while( pos )
{
ChMazeTextureHTTPReq* pReq = m_textureQueue.GetNext( pos );
#if defined(CH_USE_3DR)
#pragma message("3DR textures leak")
#elif (defined(CH_USE_RLAB)) || defined(CH_USE_D3D)
//delete ((ChRLImage *)pReq->GetTextureHandle())->Release();
if ( pReq->GetTextureHandle() )
{
((ChRLImage *)pReq->GetTextureHandle())->Release();
}
#endif
delete pReq;
}
m_textureQueue.Empty();
}
SetRoot(0);
m_iShapeCount = 0; // This will be incremented by the construction thread
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -