Advertisement
Guest User

Untitled

a guest
Apr 3rd, 2021
153
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.61 KB | None | 0 0
  1.  
  2. #define CLIPCODE_X_GREATER (1 << 0)
  3. #define CLIPCODE_X_LOWER   (1 << 1)
  4. #define CLIPCODE_X_INSIDE  (1 << 2)
  5.  
  6. #define CLIPCODE_Y_GREATER (1 << 3)
  7. #define CLIPCODE_Y_LOWER   (1 << 4)
  8. #define CLIPCODE_Y_INSIDE  (1 << 5)
  9.  
  10. #define CLIPCODE_Z_GREATER (1 << 6)
  11. #define CLIPCODE_Z_LOWER   (1 << 7)
  12. #define CLIPCODE_Z_INSIDE  (1 << 8)
  13.  
  14. enum
  15. {
  16.     Clipping_CheckX = 0,
  17.     Clipping_CheckY,
  18.     Clipping_CheckZ,
  19. };
  20.  
  21.  
  22. struct triangle
  23. {
  24.     v3 Vertex[3];
  25.     u32 Color;
  26. };
  27.  
  28.  
  29. global u32 gTrianglesCount;
  30. global triangle gTriangles[MAX_TRIANGLES];
  31.  
  32. bool
  33. IsTrivialReject(u32 *ClipCode, u32 Dim)
  34. {
  35.    
  36.     if(Dim == 0)
  37.     {
  38.         if((IsBitSet(ClipCode[0],0) &&
  39.             IsBitSet(ClipCode[1],0) &&
  40.             IsBitSet(ClipCode[2],0)) ||
  41.            
  42.            (IsBitSet(ClipCode[0],1) &&
  43.             IsBitSet(ClipCode[1],1) &&
  44.             IsBitSet(ClipCode[2],1)))
  45.         {
  46.             return true;
  47.         }
  48.        
  49.     }
  50.     else if(Dim == 1)
  51.     {
  52.         if((IsBitSet(ClipCode[0],3)  &&
  53.             IsBitSet(ClipCode[1],3)  &&
  54.             IsBitSet(ClipCode[2],3)) ||
  55.            
  56.            (IsBitSet(ClipCode[0],4) &&
  57.             IsBitSet(ClipCode[1],4) &&
  58.             IsBitSet(ClipCode[2],4)))
  59.         {
  60.             return true;
  61.         }
  62.     }
  63.     else if(Dim == 2)
  64.     {
  65.         if((IsBitSet(ClipCode[0],6)  &&
  66.             IsBitSet(ClipCode[1],6)  &&
  67.             IsBitSet(ClipCode[2],6)) ||
  68.            
  69.            (IsBitSet(ClipCode[0],7) &&
  70.             IsBitSet(ClipCode[1],7) &&
  71.             IsBitSet(ClipCode[2],7)))
  72.         {
  73.             return true;
  74.         }
  75.     }
  76.     else
  77.     {
  78.         assert(!"Unexpected Dim!");
  79.     }
  80.     return false;
  81. }
  82.  
  83.  
  84. void
  85. TransformIntoClipSpace(f32 FOV,f32 n,f32 f,f32 AspectRatio,
  86.                        v3 RawV0, v3 RawV1, v3 RawV2,
  87.                        v4 *ClipSpaceV0Out, v4 *ClipSpaceV1Out, v4 *ClipSpaceV2Out)
  88. {
  89.    
  90.     f32 TanHalfFov = tanf(Radians(FOV * 0.5f));
  91.     f32 XScale = 1.0f / (TanHalfFov * AspectRatio);
  92.     f32 YScale = 1.0f / TanHalfFov;
  93.     f32 a = f/(f-n);
  94.     f32 b = -2*n*f / (f - n);
  95.    
  96.     ClipSpaceV0Out->x = RawV0.x * XScale;
  97.     ClipSpaceV0Out->y = RawV0.y * YScale;
  98.     ClipSpaceV0Out->z = RawV0.z * a + b;
  99.     ClipSpaceV0Out->w = RawV0.z;
  100.    
  101.     ClipSpaceV1Out->x = RawV1.x * XScale;
  102.     ClipSpaceV1Out->y = RawV1.y * YScale;
  103.     ClipSpaceV1Out->z = RawV1.z * a + b;
  104.     ClipSpaceV1Out->w = RawV1.z;
  105.    
  106.     ClipSpaceV2Out->x = RawV2.x * XScale;
  107.     ClipSpaceV2Out->y = RawV2.y * YScale;
  108.     ClipSpaceV2Out->z = RawV2.z * a + b;
  109.     ClipSpaceV2Out->w = RawV2.z;
  110.    
  111. }
  112.  
  113. void
  114. TransformHomogeneousToNDC(v4 HomoV0, v4 HomoV1,v4 HomoV2,
  115.                           v3 *NdcV0Out,v3 *NdcV1Out,v3 *NdcV2Out)
  116. {
  117.     NdcV0Out->x = HomoV0.x / HomoV0.w;
  118.     NdcV0Out->y = HomoV0.y / HomoV0.w;
  119.     NdcV0Out->z = HomoV0.z / HomoV0.w;
  120.    
  121.     NdcV1Out->x = HomoV1.x / HomoV1.w;
  122.     NdcV1Out->y = HomoV1.y / HomoV1.w;
  123.     NdcV1Out->z = HomoV1.z / HomoV1.w;
  124.    
  125.     NdcV2Out->x = HomoV2.x / HomoV2.w;
  126.     NdcV2Out->y = HomoV2.y / HomoV2.w;
  127.     NdcV2Out->z = HomoV2.z / HomoV2.w;
  128. }
  129.  
  130. void
  131. Viewport(v3 NdcV0,v3 NdcV1,v3 NdcV2,
  132.          v3 *WinPV0Out,v3 *WinPV1Out,v3 *WinPV2Out,
  133.          f32 ClipV0Z,f32 ClipV1Z,f32 ClipV2Z)
  134. {
  135.    
  136.     WinPV0Out->x = (NdcV0.x + 1.0f)*WINDOW_WIDTH*0.5f;
  137.     WinPV0Out->y = (NdcV0.y + 1.0f)*WINDOW_HEIGHT*0.5f;
  138.     WinPV0Out->z = ClipV0Z;
  139.    
  140.     WinPV1Out->x = (NdcV1.x + 1.0f)*WINDOW_WIDTH*0.5f;
  141.     WinPV1Out->y = (NdcV1.y + 1.0f)*WINDOW_HEIGHT*0.5f;
  142.     WinPV1Out->z = ClipV1Z;
  143.    
  144.     WinPV2Out->x = (NdcV2.x + 1.0f)*WINDOW_WIDTH*0.5f;
  145.     WinPV2Out->y = (NdcV2.y + 1.0f)*WINDOW_HEIGHT*0.5f;
  146.     WinPV2Out->z = ClipV2Z;
  147.    
  148. }
  149.  
  150.  
  151. internal void
  152. AddTriangle(v3 V0, v3 V1, v3 V2, u32 Color)
  153. {
  154.     //assert(gTrianglesCount < MAX_TRIANGLES);
  155.     triangle *Triangle = &gTriangles[gTrianglesCount++];
  156.    
  157.     Triangle->Vertex[0] = V0;
  158.     Triangle->Vertex[1] = V1;
  159.     Triangle->Vertex[2] = V2;
  160.     Triangle->Color = Color;
  161. }
  162.  
  163.  
  164. void
  165. GameUpdateAndRender(game_backbuffer *Backbuffer, controller *Input)
  166. {
  167.     if(!gIsInit)
  168.     {
  169.         gIsInit = true;
  170.     }
  171.    
  172.     gTrianglesCount = 0; // NOTE(shvayko): Reset
  173. #if 0
  174.     // NOTE(shvayko): Test Cube
  175.     v3 FrontFaceV0 = v3f(-10.0f, 10.0f, 20.0f);
  176.     v3 FrontFaceV1 = v3f( 10.0f, 10.0f, 20.0f);
  177.     v3 FrontFaceV2 = v3f(-10.0f, -10.0f,20.0f);
  178.     AddTriangle(FrontFaceV0,FrontFaceV1,FrontFaceV2, 0x0000FF);
  179.    
  180.     v3 FrontFaceV00 = v3f(10.0f, 10.0f, 20.0f);
  181.     v3 FrontFaceV01 = v3f(10.0f, -10.0f, 20.0f);
  182.     v3 FrontFaceV02 = v3f(-10.0f, -10.0f,20.0f);
  183.     AddTriangle(FrontFaceV00,FrontFaceV01,FrontFaceV02,0x000FF);
  184.    
  185.    
  186.     v3 RightFaceV0 = v3f(10.0f, -10.0f, 20.0f);
  187.     v3 RightFaceV1 = v3f(10.0f, 10.0f,  20.0f);
  188.     v3 RightFaceV2 = v3f(10.0f, -10.0f, 25.0f);
  189.     AddTriangle(RightFaceV0,RightFaceV1,RightFaceV2,0x00FF00);
  190.    
  191.     v3 RightFaceV00 = v3f(10.0f, 10.0f, 20.0f);
  192.     v3 RightFaceV01 = v3f(10.0f, 10.0f,  25.0f);
  193.     v3 RightFaceV02 = v3f(10.0f, -10.0f, 25.0f);
  194.     AddTriangle(RightFaceV00,RightFaceV01,RightFaceV02,0xFF0000);
  195.    
  196.    
  197.     v3 BackFaceV0 = v3f(10.0f, 10.0f,  25.0f);
  198.     v3 BackFaceV1 = v3f(10.0f, -10.0f, 25.0f);
  199.     v3 BackFaceV2 = v3f(-10.0f, 10.0f, 25.0f);
  200.     AddTriangle(BackFaceV0,BackFaceV1,BackFaceV2,0xFFFF00);
  201.    
  202.     v3 BackFaceV00 = v3f(10.0f, -10.0f, 25.0f);
  203.     v3 BackFaceV01 = v3f(-10.0f, -10.0f,  25.0f);
  204.     v3 BackFaceV02 = v3f(-10.0f, 10.0f, 25.0f);
  205.     AddTriangle(BackFaceV00,BackFaceV01,BackFaceV02,0xFF0000);
  206.    
  207.     v3 LeftFaceV0 = v3f(-10.0f, 10.0f, 20.0f);
  208.     v3 LeftFaceV1 = v3f(-10.0f, -10.0f,20.0f);
  209.     v3 LeftFaceV2 = v3f(-10.0f, 10.0f, 25.0f);
  210.     AddTriangle(LeftFaceV0,LeftFaceV1,LeftFaceV2,0xF0000F);
  211.    
  212.     v3 LeftFaceV00 = v3f(-10.0f, -10.0f, 20.0f);
  213.     v3 LeftFaceV01 = v3f(-10.0f, -10.0f,  25.0f);
  214.     v3 LeftFaceV02 = v3f(-10.0f, 10.0f, 25.0f);
  215.     AddTriangle(LeftFaceV00,LeftFaceV01,LeftFaceV02,0x00FFFF);
  216. #else
  217.     // NOTE(shvayko): Test triangle where 2 vertices beyond near clipping plane
  218.     v3 LeftFaceV00 = v3f(5.0f, -10.0f, 20.0f);
  219.     v3 LeftFaceV01 = v3f(10.0f, -10.0f, 1.0f);
  220.     v3 LeftFaceV02 = v3f(5.0f, 10.0f,   1.0f);
  221.     AddTriangle(LeftFaceV00,LeftFaceV01,LeftFaceV02,0x00FFFF);
  222. #endif
  223.     ClearBackbuffer(Backbuffer);
  224.    
  225.     persist f32 dZ = 1.0f;
  226.     persist f32 dX = 1.0f;
  227.     if(IsButtonDown(ButtonUp))
  228.     {
  229.         dZ += 0.01f;
  230.     }
  231.     if(IsButtonDown(ButtonDown))
  232.     {
  233.         dZ -= 0.01f;
  234.     }
  235.     if(IsButtonDown(ButtonLeft))
  236.     {
  237.         dX -= 0.01f;
  238.     }
  239.     if(IsButtonDown(ButtonRight))
  240.     {
  241.         dX += 0.01f;
  242.     }
  243.    
  244. #if 1
  245.    
  246.     MoveTriangle(0,dX,0,dZ);
  247.     MoveTriangle(1,dX,0,dZ);
  248.     MoveTriangle(2,dX,0,dZ);
  249.     MoveTriangle(3,dX,0,dZ);
  250.     MoveTriangle(4,dX,0,dZ);
  251.     MoveTriangle(5,dX,0,dZ);
  252.     MoveTriangle(6,dX,0,dZ);
  253.     MoveTriangle(7,dX,0,dZ);
  254.     MoveTriangle(8,dX,0,dZ);
  255.    
  256. #if 0
  257.     static f32 Angle = 0.001f;
  258.     Angle += 0.001f;
  259.     // NOTE(shvayko): Testing rotations
  260.     for(u32 Index = 0;
  261.         Index < 8;
  262.         Index++)
  263.     {
  264.         for(u32 VertexIndex = 0;
  265.             VertexIndex < 3;
  266.             VertexIndex++)
  267.         {
  268.             gTriangles[Index].Vertex[VertexIndex] = RotateZAroundPoint(Angle, gTriangles[Index].Vertex[VertexIndex], v3f(1,1,0));
  269.         }
  270.     }
  271. #endif
  272.    
  273. #endif
  274.    
  275.     f32 FOV = 90.0f; // NOTE(shvayko):
  276.     f32 n = 1.0f; // NOTE: Near plane
  277.     f32 f = 15.0f; // NOTE: Far plane
  278.     f32 AspectRatio = (f32)WINDOW_WIDTH / (f32)WINDOW_HEIGHT;
  279.     for(u32 TriangleIndex = 0;
  280.         TriangleIndex < gTrianglesCount;
  281.         TriangleIndex++)
  282.     {
  283.         triangle *Triangle = &gTriangles[TriangleIndex];
  284.         v3 V0 = Triangle->Vertex[0];
  285.         v3 V1 = Triangle->Vertex[1];
  286.         v3 V2 = Triangle->Vertex[2];
  287.        
  288.         // NOTE(shvayko): Transform to clip space
  289.         v4 ClipV0,ClipV1,ClipV2;
  290.         TransformIntoClipSpace(FOV,n,f,AspectRatio,V0,V1,V2,
  291.                                &ClipV0, &ClipV1, &ClipV2);
  292.        
  293.         // NOTE(shvayko): Clipping  -1 <= x/w <= 1 ==> -w <= x <= w
  294.        
  295.         // NOTE(shvayko): Clipcode for every vertex
  296.         u32 ClipCode[3];
  297.         memset(ClipCode,0,4*3);
  298.         // NOTE(shvayko): Count how much vertices have Z > NearPlane
  299.         u32 VerticesInsideZRange = 0;
  300.         v4 TestVertices[3] = {ClipV0,ClipV1,ClipV2};
  301.        
  302.         for(u32 VertexIndex = 0;
  303.             VertexIndex < 3;
  304.             VertexIndex++)
  305.         {
  306.             v4 CurrentTestVertex = TestVertices[VertexIndex];
  307.             if(CurrentTestVertex.x > CurrentTestVertex.w)
  308.             {
  309.                 ClipCode[VertexIndex] |= CLIPCODE_X_GREATER;
  310.             }
  311.             else if(CurrentTestVertex.x < -CurrentTestVertex.w)
  312.             {
  313.                 ClipCode[VertexIndex] |= CLIPCODE_X_LOWER;
  314.             }
  315.             else
  316.             {
  317.                 ClipCode[VertexIndex] |= CLIPCODE_X_INSIDE;
  318.             }
  319.            
  320.             if(CurrentTestVertex.y > CurrentTestVertex.w)
  321.             {
  322.                 ClipCode[VertexIndex] |= CLIPCODE_Y_GREATER;
  323.             }
  324.             else if(CurrentTestVertex.y < -CurrentTestVertex.w)
  325.             {
  326.                 ClipCode[VertexIndex] |= CLIPCODE_Y_LOWER;
  327.             }
  328.             else
  329.             {
  330.                 ClipCode[VertexIndex] |= CLIPCODE_Y_INSIDE;
  331.             }
  332.            
  333.             if(CurrentTestVertex.z > CurrentTestVertex.w)
  334.             {
  335.                 ClipCode[VertexIndex] |= CLIPCODE_Z_GREATER;
  336.             }
  337.             else if(CurrentTestVertex.z < -CurrentTestVertex.w)
  338.             {
  339.                 ClipCode[VertexIndex] |= CLIPCODE_Z_LOWER;
  340.             }
  341.             else
  342.             {
  343.                 ClipCode[VertexIndex] |= CLIPCODE_Z_INSIDE;
  344.                 VerticesInsideZRange++;
  345.             }
  346.            
  347.         }
  348.         // NOTE(shvayko):Check if all 3 points outside canonical volume
  349.         if(IsTrivialReject(ClipCode,Clipping_CheckX) ||
  350.            IsTrivialReject(ClipCode,Clipping_CheckY) ||  
  351.            IsTrivialReject(ClipCode,Clipping_CheckZ))
  352.         {
  353.             // NOTE(shvayko): Go to the next polygon
  354.             continue;
  355.         }
  356.        
  357.        
  358.         // NOTE(shvayko):Check if any vertex lying beyond near plane
  359.         if(IsBitSet(ClipCode[0],7) ||
  360.            IsBitSet(ClipCode[1],7) ||
  361.            IsBitSet(ClipCode[2],7))
  362.         {
  363.             if(VerticesInsideZRange == 1)
  364.             {
  365.                 // NOTE(shvayko): The simplest case where only one interior vertex.
  366.                 // Just interpolate each exterior vertex with interior vertex and that
  367.                 // will produce new vertices which will  represent one new triangle.
  368.                
  369.                 // NOTE(shvayko): TmpV0 - Interior vertex; TmpV1 - Exterior vertex;
  370.                 // TmpV2 - Exterior vertex
  371.                 v3 TmpV0,TmpV1,TmpV2;
  372.                 if(IsBitSet(ClipCode[0],8))
  373.                 {
  374.                     TmpV0 = V0;
  375.                     TmpV1 = V1;
  376.                     TmpV2 = V2;
  377.                 }
  378.                 else if(IsBitSet(ClipCode[1],8))
  379.                 {
  380.                     TmpV0 = V1;
  381.                     TmpV1 = V0;
  382.                     TmpV2 = V2;
  383.                 }
  384.                 else
  385.                 {
  386.                     TmpV0 = V2;
  387.                     TmpV1 = V0;
  388.                     TmpV2 = V1;
  389.                 }
  390.                
  391.                 // NOTE(shvayko): Solve for t when z component is equal to near z
  392.                 // Pi(x,y,z) = P0(x,y,z) + (P1(x,y,z) - P0(x,y,z))*t
  393.                
  394.                 // NOTE(shvayko): 1.0f is near plane Z
  395.                
  396.                 // NOTE(shvayko): TmpV0 and TmpV2
  397.                 f32 t = 1.0f-TmpV1.z / (TmpV0.z - TmpV1.z);
  398.                
  399.                 f32 x = TmpV1.x + (TmpV0.x - TmpV1.x)*t;
  400.                 f32 y = TmpV1.y + (TmpV0.y - TmpV1.y)*t;
  401.                 f32 z = TmpV1.z + (TmpV0.z - TmpV1.z)*t;
  402.                 TmpV1 = v3f(x,y,1.1f);
  403.                 // NOTE(shvayko): TmpV0 and TmpV2
  404.                
  405.                 f32 t1 = 1.0f-TmpV2.z / (TmpV0.z - TmpV2.z);
  406.                
  407.                 x = TmpV2.x + (TmpV0.x - TmpV2.x)*t1;
  408.                 y = TmpV2.y + (TmpV0.y - TmpV2.y)*t1;
  409.                 z = TmpV2.z + (TmpV0.z - TmpV2.z)*t1;
  410.                 TmpV2 = v3f(x,y,1.1f);
  411.                
  412.                 // NOTE(shvayko): New triangle
  413.                 v3 NT0 = TmpV0;
  414.                 v3 NT1 = TmpV1;
  415.                 v3 NT2 = TmpV2;
  416.                
  417.                 AddTriangle(NT0,NT1,NT2,Triangle->Color);
  418.                
  419.             }
  420.             else if(VerticesInsideZRange == 2)
  421.             {
  422.                
  423.                 // NOTE(shvayko): The  case where two interior vertex.
  424.                 // That case will produce 2 triangles
  425.                
  426.                 // NOTE(shvayko): TmpV0 - Interior vertex; TmpV1 - Interior vertex;
  427.                 // TmpV2 - Exterior vertex
  428.                
  429.                 v3 TmpV0,TmpV1,TmpV2;
  430.                 if(ClipCode[0] & CLIPCODE_Z_INSIDE)
  431.                 {
  432.                     TmpV0 = V0;
  433.                     if(ClipCode[1] & CLIPCODE_Z_INSIDE)
  434.                     {
  435.                         TmpV1 = V1;
  436.                         TmpV2 = V2;
  437.                     }
  438.                     else
  439.                     {
  440.                         TmpV1 = V2;
  441.                         TmpV2 = V1;
  442.                     }
  443.                 }
  444.                 else if(ClipCode[1] & CLIPCODE_Z_INSIDE)
  445.                 {
  446.                     TmpV0 = V1;
  447.                     TmpV1 = V2;
  448.                     TmpV2 = V0;
  449.                 }
  450.                
  451.                 // NOTE(shvayko): Solve for t when z component is equal to near z
  452.                
  453.                 // NOTE(shvayko): first created new vertex
  454.                
  455.                 // NOTE(shvayko): 1.0f is near plane Z
  456.                 f32 t = 1.0f-TmpV2.z / (TmpV0.z - TmpV2.z);
  457.                
  458.                 f32 X0i = TmpV2.x + (TmpV0.x - TmpV2.x)*t;
  459.                 f32 Y0i = TmpV2.y + (TmpV0.y - TmpV2.y)*t;
  460.                 f32 Z0i = TmpV2.z + (TmpV0.z - TmpV2.z)*t;
  461.                
  462.                 // NOTE(shvayko): second created new vertex
  463.                
  464.                 f32 t1 = 1.0f-TmpV2.z / (TmpV1.z - TmpV2.z);
  465.                
  466.                 f32 X1i = TmpV2.x + (TmpV1.x - TmpV2.x)*t1;
  467.                 f32 Y1i = TmpV2.y + (TmpV1.y - TmpV2.y)*t1;
  468.                 f32 Z1i = TmpV2.z + (TmpV1.z - TmpV2.z)*t1;
  469.                
  470.                 // NOTE(shvayko): Split into 2 triangles
  471.                
  472.                 AddTriangle(TmpV0,v3f(X0i,Y0i,1.1f),TmpV1,Triangle->Color);
  473.                 AddTriangle(TmpV0,TmpV1,v3f(X1i,Y1i,1.1f),Triangle->Color);
  474.             }
  475.             else
  476.             {
  477.                 assert(!"lol");
  478.             }
  479.         }
  480.         else
  481.         {
  482.             // NOTE(shvayko): All vertices is in Z range. Process without any clipping
  483.            
  484.             // NOTE(shvayko): Pespective divide. (Transforming from Clip Space into NDC space)
  485.            
  486.             v3 NdcV0,NdcV1,NdcV2;
  487.             TransformHomogeneousToNDC(ClipV0,ClipV1,ClipV2,&NdcV0,&NdcV1,&NdcV2);
  488.            
  489.             // NOTE(shvayko):Viewport tranformation(Transforming from NDC space(-1.0f - 1.0f))
  490.             // to screen space(0 - Width, 0 - Height)
  491.            
  492.             v3 WinPV0,WinPV1,WinPV2;
  493.             Viewport(NdcV0,NdcV1,NdcV2,&WinPV0,&WinPV1,&WinPV2,ClipV0.z,ClipV1.z,ClipV2.z);
  494.            
  495.             // NOTE(shvayko): Rasterization Stage
  496.             DrawTriangle(Backbuffer,WinPV0,WinPV1,WinPV2, Triangle->Color);
  497.         }
  498.     }
  499. }
  500.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement