§
    vÛ¾j°  ã                  ó:  — d Z ddlmZ ddlmZ ddlZddlmZmZm	Z	m
Z
  edd¬¦  «         G d„ d	¦  «        ¦   «         Z edd¬¦  «         G d
„ d¦  «        ¦   «         Z edd¬¦  «         G d„ d¦  «        ¦   «         Z	 	 	 	 d,d-d„Zd.d„Z	 	 	 d/d0d%„Z	 	 d1d2d+„ZdS )3zë
FreeExile Viewport Frustum Culling Utilities.
Calculates 2.5D isometric screen projection and 2D AABB-Frustum intersection tests.
Ensures only on-screen entities are dispatched to the render pipeline, protecting 120 FPS frame budget.
é    )Úannotations)Ú	dataclassN)ÚAnyÚDictÚListÚTupleT)ÚslotsÚfrozenc                  ó„   — e Zd ZU dZded<   ded<   ded<   ded<   edd„¦   «         Zedd	„¦   «         Zdd„Zdd„Z	dd„Z
dS )ÚAABBz2D Axis-Aligned Bounding Box.ÚfloatÚmin_xÚmin_yÚmax_xÚmax_yÚreturnc                ó<   — t          d| j        | j        z
  ¦  «        S ©Nç        )Úmaxr   r   ©Úselfs    úDC:\Projects\FreeExile\tools\asset_pipeline\viewport_culling_utils.pyÚwidthz
AABB.width   ó   € å�3˜œ
 T¤ZÑ/Ñ0Ô0Ð0ó    c                ó<   — t          d| j        | j        z
  ¦  «        S r   )r   r   r   r   s    r   ÚheightzAABB.height   r   r   ÚxÚyÚboolc                ój   — | j         |cxk    o
| j        k    nc o| j        |cxk    o
| j        k    nc S ©N)r   r   r   r   )r   r   r    s      r   Úcontains_pointzAABB.contains_point   sM   € ØŒz˜QÐ,Ð,Ò,Ð, $¤*Ò,Ð,Ð,Ð,ÐN°´¸qÐ1NÐ1NÒ1NÐ1NÀDÄJÒ1NÐ1NÐ1NÐ1NÐNr   Úotherc                ó„   — | j         |j        k     p/| j        |j         k    p| j        |j        k     p| j        |j        k     S r#   )r   r   r   r   )r   r%   s     r   Ú
intersectszAABB.intersects"   sM   € àŒJ˜œÒ$ð (ØŒz˜EœKÒ'ð(àŒz˜EœKÒ'ð(ð Œz˜EœKÒ'ð	
ð 	
r   Úpaddingc                óh   — t          | j        |z
  | j        |z
  | j        |z   | j        |z   ¬¦  «        S ©N©r   r   r   r   )r   r   r   r   r   )r   r(   s     r   ÚexpandzAABB.expand*   sA   € ÝØ”*˜wÑ&Ø”*˜wÑ&Ø”*˜wÑ&Ø”*˜wÑ&ð	
ñ 
ô 
ð 	
r   N)r   r   ©r   r   r    r   r   r!   )r%   r   r   r!   )r(   r   r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__Úpropertyr   r   r$   r'   r,   © r   r   r   r      s¾   € € € € € € à'Ð'Ø€L€L�LØ€L€L�LØ€L€L�LØ€L€L�Làð1ð 1ð 1ñ „Xð1ð ð1ð 1ð 1ñ „Xð1ðOð Oð Oð Oð
ð 
ð 
ð 
ð
ð 
ð 
ð 
ð 
ð 
r   r   c                  óZ   — e Zd ZU dZded<   ded<   ded<   ded<   dZded<   dd„Zdd„ZdS )Ú	Frustum2DzH2D Orthographic / Isometric Screen Frustum with optional margin padding.r   r   r   r   r   r   r(   r   r   c                ó�   — t          | j        | j        z
  | j        | j        z
  | j        | j        z   | j        | j        z   ¬¦  «        S r*   )r   r   r(   r   r   r   r   s    r   Úto_aabbzFrustum2D.to_aabb<   sI   € ÝØ”*˜tœ|Ñ+Ø”*˜tœ|Ñ+Ø”*˜tœ|Ñ+Ø”*˜tœ|Ñ+ð	
ñ 
ô 
ð 	
r   r   r    r!   c                óV   — |                       ¦   «         }|                     ||¦  «        S r#   )r8   r$   )r   r   r    Ú	effectives       r   r$   zFrustum2D.contains_pointD   s%   € Ø—L’L‘N”Nˆ	Ø×'Ò'¨¨1Ñ-Ô-Ð-r   N)r   r   r-   )r.   r/   r0   r1   r2   r(   r8   r$   r4   r   r   r6   r6   3   sy   € € € € € € àRÐRØ€L€L�LØ€L€L�LØ€L€L�LØ€L€L�LØ€GÐÐÐÑð
ð 
ð 
ð 
ð.ð .ð .ð .ð .ð .r   r6   c                  ó\   — e Zd ZU dZded<   ded<   ded<   dZded<   d	Zded
<   d	Zded<   dS )ÚEntityBoundsz>Spatial bounding definition for an entity in 2.5D world space.ÚstrÚ	entity_idr   Úworld_xÚworld_yr   Úworld_zç      P@Úscreen_widthÚscreen_heightN)r.   r/   r0   r1   r2   rA   rC   rD   r4   r   r   r<   r<   I   sf   € € € € € € àHÐHØ€N€N�NØ€N€N�NØ€N€N�NØ€GÐÐÐÑØ€LÐÐÐÑØ€MÐÐÐÑÐÐr   r<   r   rB   ç      @@ç      8@r?   r   r@   rA   Útile_wÚtile_hÚz_scaler   úTuple[float, float]c                óB   — | |z
  |dz  z  }| |z   |dz  z  ||z  z
  }||fS )zEProjects 3D world coordinates into 2.5D isometric screen coordinates.ç       @r4   )r?   r@   rA   rG   rH   rI   Úiso_xÚiso_ys           r   Úproject_isorO   T   s>   € ð �wÑ 6¨C¡<Ñ0€EØ�wÑ 6¨C¡<Ñ0°G¸gÑ4EÑF€EØ�%ˆ<Ðr   ÚfrustumÚboxr!   c                óT   — |                       ¦   «         }|                     |¦  «        S )z9Returns True if the 2D frustum intersects the given AABB.)r8   r'   )rP   rQ   Úf_boxs      r   r'   r'   b   s%   € à�OŠOÑÔ€EØ×Ò˜CÑ Ô Ð r   Ú
camera_posÚviewport_sizeÚentitiesúList[EntityBounds]r(   c                ó¢  — | \  }}|\  }}	t          ||d||¦  «        \  }
}|dz  }|	dz  }t          |
|z
  ||z
  |
|z   ||z   |¬¦  «        }g }|D ]}t          |j        |j        |j        ||¦  «        \  }}|j        dz  }|j        dz  }t          ||z
  ||z
  ||z   ||z   ¬¦  «        }t          ||¦  «        r| 	                    |¦  «         Œ€|S )zSFilters a list of entities, returning only those intersecting the viewport frustum.r   rL   )r   r   r   r   r(   r+   )
rO   r6   r?   r@   rA   rC   rD   r   r'   Úappend)rT   rU   rV   r(   rG   rH   Úcam_xÚcam_yÚvwÚvhÚ	cam_iso_xÚ	cam_iso_yÚhalf_vwÚhalf_vhrP   ÚvisibleÚentÚ	ent_iso_xÚ	ent_iso_yÚhwÚhhÚent_boxs                         r   Úcull_entitiesri   h   s'  € ð �L€Eˆ5Ø�F€Bˆå& u¨e°S¸&À&ÑIÔIÑ€IˆyØ�3‰h€GØ�3‰h€GåØ˜'Ñ!Ø˜'Ñ!Ø˜'Ñ!Ø˜'Ñ!Øðñ ô €Gð #%€GØð  ð  ˆÝ*¨3¬;¸¼ÀSÄ[ÐRXÐZ`ÑaÔaÑˆ	�9ØÔ Ñ#ˆØÔ Ñ$ˆÝØ˜b‘.Ø˜b‘.Ø˜b‘.Ø˜b‘.ð	
ñ 
ô 
ˆõ �g˜wÑ'Ô'ð 	 Ø�NŠN˜3ÑÔÐøà€Nr   éè  ©g      ž@g     à�@Únum_entitiesÚintúDict[str, Any]c                óJ  ‡	— ddl }|                     d¦  «        Š	ˆ	fd„t          | ¦  «        D ¦   «         }t          j        ¦   «         }t          d||d¬¦  «        }t          j        ¦   «         |z
  dz  }t          |¦  «        t          |¦  «        z
  }|t          d	t          |¦  «        ¦  «        z  }t          |¦  «        t          |¦  «        |t          |d
z  d¦  «        t          |d¦  «        t          |dz  t          d	t          |¦  «        ¦  «        z  d¦  «        dœS )zMMeasures execution time and culling efficiency over a synthetic distribution.r   Né*   c           
     ó�   •— g | ]B}t          d |› �‰                     dd¦  «        ‰                     dd¦  «        ddd¬¦  «        ‘ŒCS )Úmob_g      IÀg      I@r   rB   )r>   r?   r@   rA   rC   rD   )r<   Úuniform)Ú.0ÚiÚrngs     €r   ú
<listcomp>z%benchmark_culling.<locals>.<listcomp>™   sn   ø€ ð 
ð 
ð 
ð õ 	Ø ˜Q�j�jØ—K’K  tÑ,Ô,Ø—K’K  tÑ,Ô,ØØØð	
ñ 	
ô 	
ð
ð 
ð 
r   )r   r   rE   )rT   rU   rV   r(   g     @�@é   g      Y@é   é   )Útotal_entitiesÚvisible_entitiesÚculled_entitiesÚculled_percentageÚ
elapsed_msÚper_entity_us)	ÚrandomÚRandomÚrangeÚtimeÚperf_counterri   Úlenr   Úround)
rl   rU   r�   rV   Ústartrb   r   Úculled_countÚculled_ratiorv   s
            @r   Úbenchmark_cullingr‹   ‘   s7  ø€ ð
 €M€M€MØ
�-Š-˜Ñ
Ô
€Cð
ð 
ð 
ð 
õ �|Ñ$Ô$ð
ñ 
ô 
€Hõ ÔÑÔ€EÝØØ#ØØð	ñ ô €Gõ Ô#Ñ%Ô%¨Ñ-°Ñ7€Jå�x‘=”=¥3 w¡<¤<Ñ/€LØ¥# a­¨X©¬Ñ"7Ô"7Ñ7€Lõ ˜h™-œ-Ý ™LœLØ'Ý" <°%Ñ#7¸Ñ;Ô;Ý˜J¨Ñ*Ô*Ý 
¨VÑ 3µs¸1½cÀ(¹m¼mÑ7LÔ7LÑLÈaÑPÔPðð ð r   )r   rB   rE   rF   )r?   r   r@   r   rA   r   rG   r   rH   r   rI   r   r   rJ   )rP   r6   rQ   r   r   r!   )rE   rB   rE   )rT   rJ   rU   rJ   rV   rW   r(   r   rG   r   rH   r   r   rW   )rj   rk   )rl   rm   rU   rJ   r   rn   )r1   Ú
__future__r   Údataclassesr   r„   Útypingr   r   r   r   r   r6   r<   rO   r'   ri   r‹   r4   r   r   ú<module>r�      sº  ððð ð #Ð "Ð "Ð "Ð "Ð "à !Ð !Ð !Ð !Ð !Ð !Ø €€€Ø )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )Ð )ð €�˜dÐ#Ñ#Ô#ð 
ð  
ð  
ð  
ð  
ñ  
ô  
ñ $Ô#ð 
ðF €�˜dÐ#Ñ#Ô#ð.ð .ð .ð .ð .ñ .ô .ñ $Ô#ð.ð* €�˜dÐ#Ñ#Ô#ð ð  ð  ð  ð  ñ  ô  ñ $Ô#ð ð ØØØðð ð ð ð ð!ð !ð !ð !ð ØØð&ð &ð &ð &ð &ðT Ø)9ð'ð 'ð 'ð 'ð 'ð 'ð 'r   