/*---------------------------------------------------------------------------* Project: NintendoWare File: lyt_DrawerUniform.cpp Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. The content herein is highly confidential and should be handled accordingly. $Revision: 31311 $ *---------------------------------------------------------------------------*/ #include "precompiled.h" #include #include #include #ifdef NW_LYT_DRAWER_ENABLE // MakeUniformDataSelf実装のため #include #include #include namespace nw { namespace lyt { namespace local { namespace { const nw::math::VEC2 Transform( const nw::math::MTX22& mtx, const nw::math::VEC2& vec) { return nw::math::VEC2( mtx.f._00 * vec.x + mtx.f._01 * vec.y, mtx.f._10 * vec.x + mtx.f._11 * vec.y); } }} void Drawer::SetUniformDataEnd() { m_UniformAddr[ m_UniformAddrIndex ] = m_UniformAddress; ++m_UniformAddrIndex; #ifdef NW_FONT_RECTDRAWER_USE_DRAW_BUFFER if ( m_UniformAddrIndex + 1 > UNIFORM_ADDR_NUM || m_UniformMtxIndex + UNIFORM_MTX_USE_MAX > UNIFORM_MTX_NUM || m_UniformDataIndex + UNIFORM_DATA_USE_MAX > UNIFORM_DATA_NUM ) { UniformAndDraw(); } #else UniformAndDraw(); #endif } u8 Drawer::CalcTextureCoords( const Material* pMaterial, const TexCoordQuad* pTexCoordQuad, nw::math::VEC4 texCoords[ TexMapMax * 2 ] ) const { // テクスチャ座標の設定 const u32 num = ut::Min( (u32)pMaterial->GetTexCoordGenNum(), (u32)TexMapMax ); if ( 0 == num ) return 0; // TODO: 中心固定... エディターで編集できて、Materialから取得するようにしたい static const nw::math::VEC2 center( 0.5f, 0.5f ); for ( int i = 0; i < num; ++i ) { const int src = pMaterial->GetTexCoordGen( i ).GetTexGenSrc(); const TexMap& texMap = pMaterial->GetTexMap( i ); const f32 adjust_x = static_cast(texMap.GetWidth()) / texMap.GetRealWidth(); const f32 adjust_y = static_cast(texMap.GetHeight()) / texMap.GetRealHeight(); const TexSRT& texSRT = pMaterial->GetTexSRT( i ); register const f32 rotate = texSRT.rotate; register const f32 scalex = texSRT.scale.x; register const f32 scaley = texSRT.scale.y; if ( rotate != 0.f || scalex != 1.f || scaley != 1.f ) { f32 cos, sin; nw::math::SinCosDeg( &sin, &cos, rotate ); register nw::math::MTX22 srMtx( cos * scalex * adjust_x, -sin * scaley * adjust_x, sin * scalex * adjust_y, cos * scaley * adjust_y ); register nw::math::VEC2 ctrans( ( center.x + texSRT.translate.x ) * adjust_x, ( center.y + texSRT.translate.y ) * adjust_y ); { // 左上、右下 nw::math::VEC4* pTexCoord = &texCoords[ i ]; register nw::math::VEC2 lt( pTexCoordQuad[ src ][ VERTEX_LT ].x, pTexCoordQuad[ src ][ VERTEX_LT ].y); register nw::math::VEC2 rb( pTexCoordQuad[ src ][ VERTEX_RB ].x, pTexCoordQuad[ src ][ VERTEX_RB ].y ); lt = local::Transform(srMtx, lt - center) + ctrans; rb = local::Transform(srMtx, rb - center) + ctrans; pTexCoord->x = lt.x ; pTexCoord->y = 1.f - lt.y; pTexCoord->z = rb.x ; pTexCoord->w = 1.f - rb.y; } { // 左下、右上は、下のほうに詰める nw::math::VEC4* pTexCoord = &texCoords[ i + TexMapMax ]; register nw::math::VEC2 lb( pTexCoordQuad[ src ][ VERTEX_LB ].x, pTexCoordQuad[ src ][ VERTEX_LB ].y ); register nw::math::VEC2 rt( pTexCoordQuad[ src ][ VERTEX_RT ].x, pTexCoordQuad[ src ][ VERTEX_RT ].y ); lb = local::Transform(srMtx, lb - center) + ctrans; rt = local::Transform(srMtx, rt - center) + ctrans; pTexCoord->x = lb.x; pTexCoord->y = 1.f - lb.y; pTexCoord->z = rt.x; pTexCoord->w = 1.f - rt.y; } } else { register const nw::math::VEC2 trans( texSRT.translate.x, texSRT.translate.y ); { // 左上、右下 nw::math::VEC4* pTexCoord = &texCoords[ i ]; pTexCoord->x = ( pTexCoordQuad[ src ][ VERTEX_LT ].x + trans.x ) * adjust_x; pTexCoord->y = 1.f - ( pTexCoordQuad[ src ][ VERTEX_LT ].y + trans.y ) * adjust_y; pTexCoord->z = ( pTexCoordQuad[ src ][ VERTEX_RB ].x + trans.x ) * adjust_x; pTexCoord->w = 1.f - ( pTexCoordQuad[ src ][ VERTEX_RB ].y + trans.y ) * adjust_y; } { // 左下、右上は、下のほうに詰める nw::math::VEC4* pTexCoord = &texCoords[ i + TexMapMax ]; pTexCoord->x = ( pTexCoordQuad[ src ][ VERTEX_LB ].x + trans.x) * adjust_x; pTexCoord->y = 1.f - ( pTexCoordQuad[ src ][ VERTEX_LB ].y + trans.y ) * adjust_y; pTexCoord->z = ( pTexCoordQuad[ src ][ VERTEX_RT ].x + trans.x) * adjust_x; pTexCoord->w = 1.f - ( pTexCoordQuad[ src ][ VERTEX_RT ].y + trans.y ) * adjust_y; } } } // テクスチャ座標を省略できない場合、6レジスタ使用する for ( int i = 0; i < num; ++i ) { if ( texCoords[ i ].x != texCoords[ i + TexMapMax ].x || // 左辺がそろっているかを判定 texCoords[ i ].z != texCoords[ i + TexMapMax ].z || // 右辺がそろっているかを判定 texCoords[ i ].y != texCoords[ i + TexMapMax ].w || // 上辺がそろっているかを判定 texCoords[ i ].w != texCoords[ i + TexMapMax ].y ) // 下辺がそろっているかを判定 { return TexMapMax * 2; } } return num; } void Drawer::SetUpTextureCoords( const nw::math::VEC4 texCoords[ TexMapMax * 2 ], const int texCoordNum ) { if ( texCoordNum != m_TexCoordNum ) { FlushBuffer(); m_TexCoordNum = texCoordNum; } if ( texCoordNum != 0 ) { if ( 2 <= texCoordNum ) { FlushBuffer(); } m_UniformAddress.addrTexCoord = m_UniformDataIndex; nw::math::VEC4* pTexCoord = &m_UniformData[ m_UniformDataIndex ]; std::memcpy( &m_UniformData[ m_UniformDataIndex ], texCoords, sizeof( nw::math::VEC4 ) * texCoordNum ); m_UniformDataIndex += texCoordNum; } } void Drawer::SetCurrentUniformAlpha( const f32 alpha ) { m_UniformAddress.addrColor = alpha; } void Drawer::SetUpMtx( const nw::math::MTX34& __restrict mtx ) { // std::memcpy( &m_UniformMtx[ m_UniformMtxIndex ], &mtx, sizeof(nw::math::MTX34) ); MTX34Copy( ( nw::math::MTX34* )&m_UniformMtx[ m_UniformMtxIndex ], &mtx ); m_UniformAddress.addrMtx = m_UniformMtxIndex; m_UniformMtxIndex += 3; } void Drawer::SetUpQuad( const nw::lyt::Size& __restrict size, const nw::math::VEC2& __restrict basePt ) { nw::math::VEC4* __restrict pQuadInfo = &m_UniformData[ m_UniformDataIndex ]; pQuadInfo->x = size.width; pQuadInfo->y = size.height; pQuadInfo->z = basePt.x; pQuadInfo->w = basePt.y; m_UniformAddress.addrSizeAndVtx = m_UniformDataIndex; ++m_UniformDataIndex; } void Drawer::SetUpVtxColors( const nw::ut::Color8 vtxColors[ VERTEX_MAX ], const u8 globalAlpha ) { register f32 d = 1.f / 255.f; register f32 colors[ VERTEX_MAX ][ 4 ]; bool isWhite = true; register f32 alpha = globalAlpha * d; for ( int i = 0; i < VERTEX_MAX; ++i ) { if ( nw::ut::Color8::WHITE != vtxColors[i] ) { colors[ i ][ 0 ] = vtxColors[ i ].r * d; colors[ i ][ 1 ] = vtxColors[ i ].g * d; colors[ i ][ 2 ] = vtxColors[ i ].b * d; colors[ i ][ 3 ] = vtxColors[ i ].a * d; for ( int j = 0; isWhite && j < i; ++j ) { colors[ j ][ 0 ] = 1.f; colors[ j ][ 1 ] = 1.f; colors[ j ][ 2 ] = 1.f; colors[ j ][ 3 ] = alpha; } isWhite = false; // アルファをかける colors[ i ][ 3 ] *= alpha; } else if ( !isWhite ) { colors[ i ][ 0 ] = 1.f; colors[ i ][ 1 ] = 1.f; colors[ i ][ 2 ] = 1.f; colors[ i ][ 3 ] = alpha; } } if ( isWhite ) { m_UniformAddress.addrColor = alpha; } else { m_UniformAddress.addrColor = m_UniformMtxIndex; for ( int i = 0; i < VERTEX_MAX; ++i ) { m_UniformMtx[ m_UniformMtxIndex + i ].x = colors[ i ][ 0 ]; m_UniformMtx[ m_UniformMtxIndex + i ].y = colors[ i ][ 1 ]; m_UniformMtx[ m_UniformMtxIndex + i ].z = colors[ i ][ 2 ]; m_UniformMtx[ m_UniformMtxIndex + i ].w = colors[ i ][ 3 ]; } m_UniformMtxIndex += VERTEX_MAX; } } //---------------------------------------------------------- // TextBox void TextBox::MakeUniformDataSelf( DrawInfo* pDrawInfo, Drawer* __restrict pDrawer ) const { #ifdef NW_LYT_DRAWER_DISABLE_DRAW_TEXTBOX return; #endif if ( m_TextLen <= 0 || !m_pFont || !m_pMaterial ) { return; } pDrawer->FlushBuffer(); const_cast(this)->UpdateDrawCharDataImpl(pDrawer); pDrawer->SetUpTextBox( this, m_pMaterial, *pDrawInfo ); } //---------------------------------------------------------- // Picture void Picture::MakeUniformDataSelf( DrawInfo* pDrawInfo, Drawer* __restrict pDrawer ) const { NW_UNUSED_VARIABLE( pDrawInfo ); #ifdef NW_LYT_DRAWER_DISABLE_DRAW_PICTURE return; #endif { // TexEnvの設定 pDrawer->SetUpTexEnv( m_pMaterial ); } { // テクスチャの設定 pDrawer->SetUpTextures( m_pMaterial ); } { // テクスチャ座標の設定 if ( !m_IsTexCoordInited || m_pMaterial->IsTextureDirty() ) { m_UniformTexCoordNum = pDrawer->CalcTextureCoords( m_pMaterial, m_TexCoordAry.GetArray(), m_UniformTexCoords ); m_IsTexCoordInited = true; m_pMaterial->SetTextureDirty( false ); } pDrawer->SetUpTextureCoords( m_UniformTexCoords, m_UniformTexCoordNum ); } { // 頂点座標の計算に必要な情報の設定 pDrawer->SetUpMtx( GetGlobalMtx() ); pDrawer->SetUpQuad( GetSize(), GetVtxPos() ); } { // 頂点カラーの設定 pDrawer->SetUpVtxColors( m_VtxColors, GetGlobalAlpha() ); } { // UniformDataの設定終了 pDrawer->SetUniformDataEnd(); } } //---------------------------------------------------------- // Pane void Pane::MakeUniformData( DrawInfo* pDrawInfo, Drawer* __restrict pDrawer ) const { NW_UNUSED_VARIABLE( pDrawInfo ); // 自身の描画 MakeUniformDataSelf( pDrawInfo, pDrawer ); // TODO: 再帰やめたい // 子供の描画 for ( PaneList::ConstIterator child = m_ChildList.begin(); child != m_ChildList.end(); ++child ) { if ( child->IsVisible() ) { child->MakeUniformData( pDrawInfo, pDrawer ); } } } void Pane::MakeUniformDataSelf( DrawInfo* /*pDrawInfo*/, Drawer* /*pDrawer*/ ) const { } }} #endif