📄 chrenderdata.cpp
字号:
all faces have 3 or more vertices, and all vertices are legal in
the context of the current coordinate node. Someday we should put
out insulting messages when this fails, but that's for later. */
if(!state->getTopElement(QvState::Coordinate3Index))
{ // no coordinates!
m_boolValid = false;
return false;
}
QvCoordinate3 *pC3 = (QvCoordinate3*)(state->getTopElement(QvState::Coordinate3Index)->data);
m_boolValid = true;
if(ifs->coordIndex.num < 4)
{
m_boolValid = false;
return false;
}
int vertCount = 0;
int faceCount = 0;
for(int j = 0; j< ifs->coordIndex.num; j++) //coordIndex.values[j] != QV_END_FACE_INDEX
{
if( ifs->coordIndex.values[j] < QV_END_FACE_INDEX)
{
m_boolValid = false; // fail for illegal coord, gotta be -1 or non-neg
break;
}
if( ifs->coordIndex.values[j] >= pC3->point.num)
{
m_boolValid = false; // fail for illegal coord; out of range
break;
}
if( ifs->coordIndex.values[j] != QV_END_FACE_INDEX) vertCount ++;
else
{
if(vertCount < 3)
{
m_boolValid = false; // fail for face with too few points
break;
}
else
{
vertCount = 0; // new face
faceCount++;
}
}
}
if(vertCount > 2)
{
faceCount ++; // accept a trailing unterminated face if it has enough points
vertCount = 0;
}
// fail for trailing trash or no faces
if(vertCount != 0 || faceCount == 0) m_boolValid = false;
return m_boolValid;
}
// Texture render data
ChQvTextureRenderData::ChQvTextureRenderData(QvNode* pTxt) :
ChQvRenderBaseData(pTxt),
m_texture(0),
#if defined(CH_USE_3DR)
m_hRC(0),
#elif (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
m_pImage(0)
#endif
{ }
ChQvTextureRenderData::~ChQvTextureRenderData()
{
#if defined(CH_USE_3DR)
if (m_texture && m_hRC ) R3dFreeTexture( m_hRC, (Dword_t)m_texture);
#else
// delete m_pImage;
if ( m_pImage )
{
m_pImage->Release();
}
m_pImage = 0;
// Textures themselves are usage counted, and we don't have to free them
#endif
m_texture = 0;
}
int ChQvTextureRenderData::GetURL(QvState *qvstate)
{
// return true if this is a spawn request, else false
if( ((ChQvState*)qvstate)->GetType() != ChQvState::spawnRequests)
{
return false;
}
QvTexture2 *pNode = (QvTexture2 *)GetNode();
// Spawn a new http request and add it to the info's list of requests
if(m_strURL.IsEmpty())
{
ChQvSpawnState *state = (ChQvSpawnState *)qvstate;
m_strURL = pNode->filename.value.getString();
// check if we need to fetch a texture from a WWW site
if(!m_strURL.IsEmpty())
{
ChMazeTextureHTTPReq *pHTTPReq = new ChMazeTextureHTTPReq (
state->GetView(), m_strURL, GetNode() );
pHTTPReq->SetPage(state->GetView()->GetCurrentPage());
string defURL = state->GetDefaultURL();
state->GetView()->GetURL( m_strURL, (chparam)pHTTPReq, LPCTSTR(defURL) );
}
else if ( pNode->image.size[0] &&
pNode->image.size[1] &&
pNode->image.numComponents )
{ // We have a field that contains an uncompressed 2-dimensional color or greyscale image
// convert the image to a ChSFImage and load the texture
ChRenderContext *pRenderContext = state->GetView()->GetRenderContext();
if ( pRenderContext )
{ // We have a valid render context, load the texture
ChSFImage *pSFImage = new ChSFImage();
ASSERT( pSFImage );
if ( pSFImage->Create( pNode->image.size[0],
pNode->image.size[1],
pNode->image.numComponents,
pNode->image.bytes ) )
{ // Transparent pixel information is ignored in the current
// implementation
LoadTexture( pRenderContext, pSFImage->GetDibImage(),
0, ChMazeTextureHTTPReq::textureAutoSize );
#if 0
SetTextureHandle( pRenderContext->LoadDIBTexture( pSFImage,
0,
ChMazeTextureHTTPReq::textureShrink ));
#endif
}
delete pSFImage;
}
}
}
return true;
}
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
// Iterator to propagate texture load info
class MyTextureDataIterator: public ChQvRenderBaseDataIterator
{
public:
MyTextureDataIterator( const ChQvTextureRenderData& rbd ) : ChQvRenderBaseDataIterator(rbd) {};
virtual int DoInstance(ChQvInstance& inst)
{
inst.SetTexture((ChQvTextureRenderData*)m_pData);
return true;
};
protected:
private:
/* Disable copy constructor and
assignment operator */
inline MyTextureDataIterator( const MyTextureDataIterator& ) {}
inline MyTextureDataIterator& operator=( const MyTextureDataIterator& )
{
return *this;
}
};
#endif
ChQvTextureRenderData* ChQvTextureRenderData::LoadTexture(ChRenderContext *pContext, ChDib *pDibIn, chuint32 luChromaClr, chuint uOption)
{
#if defined(CH_USE_3DR)
SetTextureHandle( pContext->LoadDIBTexture( pDibIn, luChromaClr, uOption ));
#elif (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
if(m_texture) return this; // Something already there, do nothing for now
bool boolLimit = false; // Should we allow reduction for RLAB??
m_pImage = new ChRLImage(pDibIn, boolLimit, uOption, luChromaClr);
pContext->LockScene();
m_texture = pContext->CreateTexture(pRLImage(*m_pImage));
// Now propagate to all dependents
MyTextureDataIterator iterator(*this);
iterator.IterateDependents();
pContext->UnlockScene();
#endif
return this;
}
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
void NrTextureDestroyCallback(ChNrObject obj, void * arg)
{
}
#endif
#if defined(CH_USE_3DR)
ChQvTextureRenderData* ChQvTextureRenderData::LoadTexture( ChRenderContext *pContext, ChTextureHandle texHandle )
#elif (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
ChQvTextureRenderData* ChQvTextureRenderData::LoadTexture( ChRenderContext *pContext, ChRLImage* pRLImg )
#endif
{
#if defined(CH_USE_3DR)
SetTextureHandle( texHandle );
#elif (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
if(m_texture)
{
// Delete the old texture we have
//delete pRLImg;
pRLImg->Release();
return this; // Something already there, do nothing for now
}
// Need to ask Jim why we are saving RLImage.
m_pImage = pRLImg;
pContext->LockScene();
m_texture = pContext->CreateTexture(pRLImage(*m_pImage));
// Add callback - Just for debugging for now
ChNrObjectAddDestroyCallback(m_texture, NrTextureDestroyCallback, this);
// Now propagate to all dependents
MyTextureDataIterator iterator(*this);
iterator.IterateDependents();
pContext->UnlockScene();
#endif
return this;
}
// Return whether it will -never- have a texture
bool ChQvTextureRenderData::IsEmpty()
{
bool boolEmpty = true;
QvTexture2 *pNode = (QvTexture2 *)GetNode();
string strURL = string(pNode->filename.value.getString());
if(!strURL.IsEmpty()) boolEmpty = false;
if ( pNode->image.size[0] &&
pNode->image.size[0] &&
pNode->image.numComponents ) boolEmpty = false;
return boolEmpty;
}
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D)) || defined(CH_USE_D3D)
bool ChQvTextureRenderData::IsChromaKey()
{
return m_pImage ? m_pImage->IsChromaKey() : false;
};
ChColor ChQvTextureRenderData::GetChromaKey()
{
return m_pImage ? m_pImage->GetChromaKey() : ChColor(0);
};
#endif
/////////////////////////////////////////////////////////////////////////
ChQvTexture2TransformRenderData::ChQvTexture2TransformRenderData(QvNode* pNode) : ChQvRenderBaseData(pNode)
{
SetDirty();
};
ChQvTexture2TransformRenderData *ChQvTexture2TransformRenderData::Transform(float &s, float& t)
{
if(m_boolDefault) return this;
QvTexture2Transform * pNode = (QvTexture2Transform*)m_pNode;
// Far from optimal - need to cache 3x3 homo matrix for better results
float tmp;
s -= pNode->center.value[0];
t -= pNode->center.value[1];
s *= pNode->scaleFactor.value[0];
t *= pNode->scaleFactor.value[1];
tmp = m_cosa * s - m_sina * t;
t = m_sina * s + m_cosa * t;
s = tmp;
s += pNode->center.value[0];
t += pNode->center.value[1];
s += pNode->translation.value[0];
t += pNode->translation.value[1];
return this;
}
ChQvTexture2TransformRenderData *ChQvTexture2TransformRenderData::CheckForDefault()
{
QvTexture2Transform * pNode = (QvTexture2Transform*)m_pNode;
m_boolDefault = true;
if(pNode->scaleFactor.value[0] != 0.0 || pNode->scaleFactor.value[1] != 0.0)
m_boolDefault = false;
if(pNode->rotation.value != 0.0)
m_boolDefault = false;
if(pNode->translation.value[0] != 0.0 || pNode->translation.value[1] != 0.0)
m_boolDefault = false;
return this;
}
void ChQvTexture2TransformRenderData::SetDirty(bool boolDirty )
{
if(boolDirty)
{
QvTexture2Transform * pNode = (QvTexture2Transform*)m_pNode;
m_cosa = cos(pNode->rotation.value);
m_sina = sin(pNode->rotation.value);
CheckForDefault();
}
return;
};
// WWWInline
ChQvWWWInlineRenderData::~ChQvWWWInlineRenderData()
{
if(m_pParseInfo)
{
m_pParseInfo->Abort();
m_pParseInfo->SetUserData(0);
m_pParseInfo = 0;
}
if(GetReq())
{
GetReq()->Cancel();
GetReq()->SetInlineNode(0);
SetReq(0);
}
}
ChQvWWWInlineRenderData* ChQvWWWInlineRenderData::Instantiate(ChMazeWnd * pWnd, QvNode *pNewChild)
{
// Walk the list of WWWInline instances, instantiating the new subtree that came in
if (!m_instances.IsEmpty())
{
ChPosition pos = m_instances.GetHeadPosition();
while(pos)
{
ChQvWWWInlineInstance *pInst = (ChQvWWWInlineInstance *)(m_instances.GetNext(pos));
ChQvBuildState bldIt(pWnd);
bldIt.SetCurrentParent(pInst);
pInst->SetupTraversalState(bldIt);
pNewChild->traverse(&bldIt);
// Now construct them for RLab
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
pWnd->GetRenderContext()->StartConstruction(pInst);
#endif
}
}
return this;
}
/////////////////////////////////////////////////////////////////////////////////
ChQvSwitchRenderData::ChQvSwitchRenderData(QvNode* pNode) :
ChQvGroupRenderData(pNode)
{
#if defined(CH_VRML_EVENTS)
if(!m_pDispatcher)
{
m_pDispatcher = new ChVrmlDispatcher;
Init();
}
#endif
};
void ChQvSwitchRenderData::Init()
{
//ChQvGroupRenderData::Init();
#if defined(CH_VRML_EVENTS)
AddVrmlDispatcher("set_whichChild", SFLong, OnSetWhichChild);
#endif
};
ChQvSwitchRenderData::~ChQvSwitchRenderData()
{
}
void ChQvSwitchRenderData::Term()
{
#if defined(CH_VRML_EVENTS)
delete m_pDispatcher;
m_pDispatcher = 0;
#endif
}
bool ChQvSwitchRenderData::OnSetWhichChild(ChRenderContext *pRC, ChApplet * pApplet, ChIVrmlEvent *pEventList)
{
bool boolSuccess = true;
#if defined(CH_VRML_EVENTS)
long lChild;
ChLongEvent *pEvent = (ChLongEvent *)pEventList;
pEvent->GetValue(lChild);
QvSwitch *pNode = (QvSwitch *)m_pNode;
pNode->whichChild.value = lChild;
// Now the hard part;
// If this is the cameras node, the camera is on our list, so select it there
// Otherwise, if this child contains a camera somewhere, select it. Do not add it
// to the list.
if(lChild >= 0 && lChild < pNode->getNumChildren())
{
if(pNode->getName() == "Cameras")
{
pRC->SelectCamera(int (lChild));
}
else
{
// Search for a camera. If found, set it.
QvNode *pChild = pNode->getChild(int(lChild));
}
}
#endif
return boolSuccess;
}
// Background ala 2.0 render data
ChQvBackgroundData::ChQvBackgroundData() :
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
m_pImage(0)
#endif
{
for(int j=0; j<6; j++)
{
m_panTextures[j] = 0;
}
}
ChQvBackgroundData::~ChQvBackgroundData()
{
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
//delete m_pImage;
if ( m_pImage )
{
m_pImage->Release();
}
m_pImage = 0;
// Textures themselves are usage counted, and we don't have to free them ????
#endif
for(int j=0; j<6; j++)
{
m_panTextures[j] = 0;
}
}
int ChQvBackgroundData::GetURL(QvState *qvstate)
{
// return true if this is a spawn request, else false
if( ((ChQvState*)qvstate)->GetType() != ChQvState::spawnRequests)
{
return false;
}
// Spawn a new http request and add it to the info's list of requests
if(m_strURL.IsEmpty())
{
ChQvSpawnState *state = (ChQvSpawnState *)qvstate;
QvBackground *pNode = (QvBackground *)GetNode();
m_strURL = string(pNode->panorama.values[0].getString());
// check if we need to fetch a texture from a WWW site
if(!m_strURL.IsEmpty())
{
#if NOT_YET
ChMazeTextureHTTPReq *pHTTPReq = new ChMazeTextureHTTPReq (
state->GetView(), m_strURL, m_pTexture2 );
pHTTPReq->SetPage(state->GetView()->GetCurrentPage());
string defURL = state->GetDefaultURL();
state->GetView()->GetURL( m_strURL, (chparam)pHTTPReq, LPCTSTR(defURL) );
#endif
}
}
return true;
}
ChQvBackgroundData* ChQvBackgroundData::LoadTexture(ChRenderContext *pContext, ChDib *pDibIn, chuint32 luChromaClr, chuint uOption)
{
#if defined(CH_USE_3DR)
#elif (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
#if NOT_YET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -