#include "ROcclusion.h" /* void ROcclusion::CheckCulling(LPDIRECT3DDEVICE8 ,ROcclusionUnit *list,int num,float camera_x,float camera_y,float camera_z); void ROcclusion::SortList(ROcclusionUnit *,int num,float camerax,float cameray,float cameraz,LPDIRECT3DDEVICE8 ); void ROcclusion::HorizonCull(LPDIRECT3DDEVICE8 ,ROcclusionUnit *,int listnum); void ROcclusion::Hculling(ROcclusionUnit *list,int listnum,int start_index,float ,float ,float ); void ROcclusion::InitVolume(); */ ROcclusionVolume *ROcclusion::m_Volume; unsigned long ROcclusion::m_VWidth; unsigned long ROcclusion::m_VHeight; int ROcclusion::m_ViewObject; int ROcclusion::m_HidenObject; /////////////////////////////// ROcclusionUnit //////////////////////////////////// void ROcclusionUnit::FindPoint(D3DXVECTOR3 *point) { int i; D3DXVECTOR3 tmp_sum = D3DXVECTOR3(0.0f,0.0f,0.0f); D3DXVECTOR3 tmp_cube[8]; int min_index = 0; int max_index = 0; int zover_count = 0; int zover_count2 = 0; unsigned long Screen_width = 0; unsigned long Screen_height = 0; D3DXMATRIX t_project; D3DXMATRIX t_view; D3DXMATRIX t_world; D3DXVECTOR3 view_vec[3]; D3DXVECTOR4 view_vec2[3]; D3DVIEWPORT8 t_viewport; D3DXVECTOR3 min_value,max_value,target_value; m_Device->GetTransform(D3DTS_VIEW,&t_view); m_Device->GetViewport(&t_viewport); m_Device->GetTransform(D3DTS_WORLD,&t_world); m_Device->GetTransform(D3DTS_PROJECTION,&t_project); Screen_width = t_viewport.Width; Screen_height = t_viewport.Height; for( i=0; i < 8; i++ ) { tmp_cube[i] = D3DXVECTOR3(m_Cube.m_vecVertex[i].x,m_Cube.m_vecVertex[i].y,m_Cube.m_vecVertex[i].z); tmp_sum += tmp_cube[i]; D3DXVec3Project(&(view_vec[0]), &(tmp_cube[min_index]), &t_viewport, &t_project, &t_view, &t_world); D3DXVec3Project(&(view_vec[1]), &(tmp_cube[i]), &t_viewport, &t_project, &t_view, &t_world); D3DXVec3Project(&(view_vec[2]), &(tmp_cube[max_index]), &t_viewport, &t_project, &t_view, &t_world); max_value = view_vec[2]; min_value = view_vec[0]; target_value = view_vec[1]; //z value 0 ~ 1 Ѿ ȭ ̴ if( target_value.z > 1.0f || target_value.z < 0.0f ) { zover_count++; zover_count2++; continue; } if( min_value.z > 1.0f || min_value.z <0.0f ) { min_index = i; zover_count++; } if( max_value.z > 1.0f || max_value.z <0.0f ) { max_index = i; zover_count2++; } if( min_value.x > target_value.x ) { //min value min_index = i; } else if( min_value.x == target_value.x ) { if( min_value.y > target_value.y ) min_index = i; } if( max_value.x == target_value.x ) //max value { if( max_value.y > target_value.y ) max_index = i; } else if( max_value.x < target_value.x ) { max_index = i; } }//for tmp_sum /=8; point[2] = tmp_sum; if(zover_count >= 8) // min value overflow point[0] = D3DXVECTOR3(FAIL,FAIL,FAIL); else point[0] = tmp_cube[min_index]; if(zover_count2 >= 8) // max value overflow point[1] = D3DXVECTOR3(FAIL,FAIL,FAIL); else point[1] = tmp_cube[max_index]; } void ROcclusionUnit::Create(LPDIRECT3DDEVICE8 device) { m_Device = device; D3DXVECTOR3 Point[3]; D3DXVECTOR3 min; D3DXVECTOR3 max; D3DXVECTOR3 center; FindPoint(Point); min = Point[0]; max = Point[1]; center = Point[2]; // ȭ ٱ if( min.x == FAIL && min.y == FAIL && min.z == FAIL ) (*m_bVis) = false; if( max.x == FAIL && max.y == FAIL && max.z == FAIL ) (*m_bVis) = false; // CreateOccBox(min,max,center,false); } //int projected arg == min,max ̹ Ǿִ.. void ROcclusionUnit::CreateOccBox(D3DXVECTOR3 min,D3DXVECTOR3 max,D3DXVECTOR3 center,bool projected) { m_OccBox.m_vecCenter = center; if(!projected) //world axis min max point input { // min point,max point setting D3DXVECTOR3 projectedpoint[2]; D3DXMATRIX t_project; D3DXMATRIX t_view; D3DXMATRIX t_world; D3DVIEWPORT8 t_viewport; m_Device->GetViewport(&t_viewport); m_Device->GetTransform(D3DTS_WORLD,&t_world); m_Device->GetTransform(D3DTS_VIEW,&t_view); m_Device->GetTransform(D3DTS_PROJECTION,&t_project); //projected 2d space D3DXVec3Project(&(projectedpoint[0]), &(min), &t_viewport, &t_project, &t_view, &t_world); D3DXVec3Project(&(projectedpoint[1]), &(max), &t_viewport, &t_project, &t_view, &t_world); m_OccBox.m_vecMin.x = projectedpoint[0].x; m_OccBox.m_vecMin.y = projectedpoint[0].y; m_OccBox.m_vecMax.x = projectedpoint[1].x; m_OccBox.m_vecMax.y = projectedpoint[1].y; } else //̹ projection · { m_OccBox.m_vecMin.x = min.x; m_OccBox.m_vecMin.y = min.y; m_OccBox.m_vecMax.x = max.x; m_OccBox.m_vecMax.y = max.y; } } //////////////////////////////////////////////////////////////////////////////// int OcclusionHCompare(const void *arg1,const void *arg2) { if(((ROcclusionUnit *)arg1)->m_OccBox.m_fZValue > ((ROcclusionUnit *)arg2)->m_OccBox.m_fZValue) return 1; else if(((ROcclusionUnit *)arg1)->m_OccBox.m_fZValue < ((ROcclusionUnit *)arg2)->m_OccBox.m_fZValue) return -1; return 0; } //camera ġ list sort void ROcclusion::SortList(ROcclusionUnit *list,int num,float camerax,float cameray,float cameraz,LPDIRECT3DDEVICE8 device) { int i; D3DXMATRIX cameratm; D3DXMATRIX invcamera; device->GetTransform(D3DTS_VIEW,&cameratm); D3DXMatrixInverse(&invcamera,NULL,&cameratm); D3DXVECTOR4 src,dst; for( i=0; i < num; i++ ) { D3DXVec3Transform(&src,&list[i].m_OccBox.m_vecCenter,&cameratm); list[i].m_OccBox.m_fZValue = src.z; } qsort((void *)list,(size_t)num, sizeof(ROcclusionUnit),OcclusionHCompare); } void ROcclusion::CheckCulling(LPDIRECT3DDEVICE8 device,ROcclusionUnit *list,int num,float camera_x,float camera_y,float camera_z) { int i; for( i = 0; i < num ; i++) list[i].Create(device); // 2D Box Create SortList(list,num,camera_x,camera_y,camera_z,device); HorizonCull(device,list,num); m_ViewObject = m_HidenObject = 0; //culling info set for( i = 0; i < num; i++ ) { if( (*list[i].m_bVis) ) m_ViewObject++; else m_HidenObject++; } } void ROcclusion::InitVolume() // Screen Volume Init { for(int k=0;k<(int)m_VWidth;k++) m_Volume[k].m_Height = (float)m_VHeight; } // Ͽ culling void ROcclusion::Hculling(ROcclusionUnit *list,int listnum,int start_index,float camerax,float cameray,float cameraz) { for( int i = start_index; i < listnum; i++ ) { if( (*list[i].m_bVis) ) // ˻ ̴ ü ˻ { int count = 0; if( list[i].m_OccBox.m_vecMin.x > list[i].m_OccBox.m_vecMax.x ) { float tmp_index = list[i].m_OccBox.m_vecMin.x; list[i].m_OccBox.m_vecMin.x = list[i].m_OccBox.m_vecMax.x; list[i].m_OccBox.m_vecMax.x = tmp_index; } // list[i].m_OccBox.m_vecMin.y = ( list[i].m_OccBox.m_vecMin.y > list[i].m_OccBox.m_vecMax.y ) ? list[i].m_OccBox.m_vecMin.y : list[i].m_OccBox.m_vecMax.y; list[i].m_OccBox.m_vecMax.y = list[i].m_OccBox.m_vecMin.y; list[i].m_OccBox.m_vecMin.y = list[i].m_OccBox.m_vecMax.y = ( list[i].m_OccBox.m_vecMin.y > m_VHeight ) ? m_VHeight : ( (list[i].m_OccBox.m_vecMin.y < 0) ? 0 : list[i].m_OccBox.m_vecMin.y); list[i].m_OccBox.m_vecMin.x = (list[i].m_OccBox.m_vecMin.x < 0 ) ? 0 : ((list[i].m_OccBox.m_vecMin.x > m_VWidth) ? (float)m_VWidth : list[i].m_OccBox.m_vecMin.x); list[i].m_OccBox.m_vecMax.x = (list[i].m_OccBox.m_vecMax.x < 0 ) ? 0 : ((list[i].m_OccBox.m_vecMax.x > m_VWidth) ? (float)m_VWidth : list[i].m_OccBox.m_vecMax.x); int min_index = (int)list[i].m_OccBox.m_vecMin.x; int max_index = (int)list[i].m_OccBox.m_vecMax.x; int width = max_index - min_index; for(int k=min_index;k= width) // 2d box ΰ ٸ (*list[i].m_bVis) = false; else (*list[i].m_bVis) = true; } } } // ̹ ī޶ Ÿ sort ڹǷ ȴ void ROcclusion::HorizonCull(LPDIRECT3DDEVICE8 device,ROcclusionUnit *list,int listnum) { if( m_Volume == NULL ) // ó Volume Create Ҷ. { D3DVIEWPORT8 t_viewport; device->GetViewport(&t_viewport); m_VWidth = t_viewport.Width; // Screen ǥ ´ m_VHeight = t_viewport.Height; m_Volume = new ROcclusionVolume[m_VWidth]; } else { InitVolume(); // Volume ʱȭ } for(int i=0;i list[i].m_OccBox.m_vecMax.x ) { float tmp_index = list[i].m_OccBox.m_vecMin.x; list[i].m_OccBox.m_vecMin.x = list[i].m_OccBox.m_vecMax.x; list[i].m_OccBox.m_vecMax.x = tmp_index; } // list[i].m_OccBox.m_vecMin.y = ( list[i].m_OccBox.m_vecMin.y > list[i].m_OccBox.m_vecMax.y ) ? list[i].m_OccBox.m_vecMin.y : list[i].m_OccBox.m_vecMax.y; list[i].m_OccBox.m_vecMax.y = list[i].m_OccBox.m_vecMin.y; if(list[i].m_OccBox.m_vecMin.y == 0 && list[i].m_OccBox.m_vecMax.y == 0) continue; list[i].m_OccBox.m_vecMin.y = list[i].m_OccBox.m_vecMax.y = ( list[i].m_OccBox.m_vecMin.y > m_VHeight ) ? m_VHeight : ( (list[i].m_OccBox.m_vecMin.y < 0) ? 0 : list[i].m_OccBox.m_vecMin.y ); list[i].m_OccBox.m_vecMin.x = (list[i].m_OccBox.m_vecMin.x < 0 ) ? 0 : ((list[i].m_OccBox.m_vecMin.x > m_VWidth) ? (float)m_VWidth : list[i].m_OccBox.m_vecMin.x); list[i].m_OccBox.m_vecMax.x = (list[i].m_OccBox.m_vecMax.x < 0 ) ? 0 : ((list[i].m_OccBox.m_vecMax.x > m_VWidth) ? (float)m_VWidth : list[i].m_OccBox.m_vecMax.x); int min_index = (int)list[i].m_OccBox.m_vecMin.x; int max_index = (int)list[i].m_OccBox.m_vecMax.x + 1; ////// int width = max_index - min_index; for(int j=min_index;j<=max_index;j++) { if(m_Volume[j].m_Height >= list[i].m_OccBox.m_vecMin.y) m_Volume[j].m_Height = list[i].m_OccBox.m_vecMin.y; } // culling D3DXMATRIX view; D3DXMATRIX inv; device->GetTransform(D3DTS_VIEW,&view); D3DXMatrixInverse(&inv,NULL,&view); Hculling(list,listnum,i+1,inv._41,inv._42,inv._43); } } }