| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |         triangle *Triangle = &gTriangles[TriangleIndex];
        v3 V0 = Triangle->Vertex[0];
        v3 V1 = Triangle->Vertex[1];
        v3 V2 = Triangle->Vertex[2];
        
        // NOTE(shvayko): Transform to clip space
        f32 FOV = 90.0f; // NOTE(shvayko): 
        f32 n = 1.0f; // NOTE: Near plane
        f32 f = 15.0f; // NOTE: Far plane
        f32 AspectRatio = (f32)WINDOW_WIDTH / (f32)WINDOW_HEIGHT;
        v4 ClipV0,ClipV1,ClipV2;
        TransformIntoClipSpace(FOV,n,f,AspectRatio,V0,V1,V2,
                               &ClipV0, &ClipV1, &ClipV2);
        
 | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | // NOTE(shvayko): Count how much vertices have Z > NearPlane
        u32 VerticesInsideZRange = 0;
        v4 TestVertices[3] = {ClipV0,ClipV1,ClipV2};
        
        for(u32 VertexIndex = 0;
            VertexIndex < 3;
            VertexIndex++)
        {
            v4 CurrentTestVertex = TestVertices[VertexIndex];
            if(CurrentTestVertex.x > CurrentTestVertex.w)
            {
                ClipCode[VertexIndex] |= CLIPCODE_X_GREATER;
            }
            else if(CurrentTestVertex.x < -CurrentTestVertex.w)
            {
                ClipCode[VertexIndex] |= CLIPCODE_X_LOWER;
            }
            else
            {
                ClipCode[VertexIndex] |= CLIPCODE_X_INSIDE;
            }
            
            if(CurrentTestVertex.y > CurrentTestVertex.w)
            {
                ClipCode[VertexIndex] |= CLIPCODE_Y_GREATER;
            }
            else if(CurrentTestVertex.y < -CurrentTestVertex.w)
            {
                ClipCode[VertexIndex] |= CLIPCODE_Y_LOWER;
            }
            else
            {
                ClipCode[VertexIndex] |= CLIPCODE_Y_INSIDE;
            }
            
            if(CurrentTestVertex.z > CurrentTestVertex.w)
            {
                ClipCode[VertexIndex] |= CLIPCODE_Z_GREATER;
            }
            else if(CurrentTestVertex.z < -CurrentTestVertex.w)
            {
                ClipCode[VertexIndex] |= CLIPCODE_Z_LOWER;
            }
            else
            {
                ClipCode[VertexIndex] |= CLIPCODE_Z_INSIDE;
                VerticesInsideZRange++;
            }
            
        }
        // NOTE(shvayko):Check if all 3 points outside canonical volume
        if(IsTrivialReject(ClipCode,Clipping_CheckX) ||
           IsTrivialReject(ClipCode,Clipping_CheckY) ||  
           IsTrivialReject(ClipCode,Clipping_CheckZ))
        {
            // NOTE(shvayko): Go to the next polygon
            continue;
        }
        
 | 
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |         // NOTE(shvayko):Check if any vertex lying beyond near plane
        if(IsBitSet(ClipCode[0],7) ||
           IsBitSet(ClipCode[1],7) ||
           IsBitSet(ClipCode[2],7))
        {
            if(VerticesInsideZRange == 1)
            {
                // NOTE(shvayko): The simplest case where only one interior vertex. 
                // Just interpolate each exterior vertex with interior vertex and that 
                // will produce new vertices which will  represent one new triangle.
                
                // NOTE(shvayko): TmpV0 - Interior vertex; TmpV1 - Exterior vertex; 
                // TmpV2 - Exterior vertex
                v3 TmpV0,TmpV1,TmpV2;
                if(IsBitSet(ClipCode[0],8))
                {
                    TmpV0 = V0;
                    TmpV1 = V1;
                    TmpV2 = V2;
                }
                else if(IsBitSet(ClipCode[1],8))
                {
                    TmpV0 = V1;
                    TmpV1 = V0;
                    TmpV2 = V2;
                }
                else
                {
                    TmpV0 = V2;
                    TmpV1 = V0;
                    TmpV2 = V1;
                }
                
                // NOTE(shvayko): Solve for t when z component is equal to near z
                // Pi(x,y,z) = P0(x,y,z) + (P1(x,y,z) - P0(x,y,z))*t
                
                // NOTE(shvayko): 1.0f is near plane Z
                
                // NOTE(shvayko): TmpV0 and TmpV2
                f32 t = 1.0f-TmpV1.z / (TmpV0.z - TmpV1.z); 
                
                f32 x = TmpV1.x + (TmpV0.x - TmpV1.x)*t;
                f32 y = TmpV1.y + (TmpV0.y - TmpV1.y)*t;
                f32 z = TmpV1.z + (TmpV0.z - TmpV1.z)*t;
                TmpV1 = v3f(x,y,1.1f);
                // NOTE(shvayko): TmpV0 and TmpV2
                
                f32 t1 = 1.0f-TmpV2.z / (TmpV0.z - TmpV2.z); 
                
                x = TmpV2.x + (TmpV0.x - TmpV2.x)*t1;
                y = TmpV2.y + (TmpV0.y - TmpV2.y)*t1;
                z = TmpV2.z + (TmpV0.z - TmpV2.z)*t1;
                TmpV2 = v3f(x,y,1.1f);
                
                // NOTE(shvayko): New triangle
                v3 NT0 = TmpV0;
                v3 NT1 = TmpV1;
                v3 NT2 = TmpV2;
                
                AddTriangle(NT0,NT1,NT2,Triangle->Color);
                
            }
            else if(VerticesInsideZRange == 2)
            {
                
                // NOTE(shvayko): The  case where two interior vertex. 
                // That case will produce 2 triangles
                
                // NOTE(shvayko): TmpV0 - Interior vertex; TmpV1 - Interior vertex; 
                // TmpV2 - Exterior vertex
                
                v3 TmpV0,TmpV1,TmpV2;
                if(ClipCode[0] & CLIPCODE_Z_INSIDE)
                {
                    TmpV0 = V0;
                    if(ClipCode[1] & CLIPCODE_Z_INSIDE)
                    {
                        TmpV1 = V1;
                        TmpV2 = V2;
                    }
                    else
                    {
                        TmpV1 = V2;
                        TmpV2 = V1;
                    }
                } 
                else if(ClipCode[1] & CLIPCODE_Z_INSIDE)
                {
                    TmpV0 = V1;
                    TmpV1 = V2;
                    TmpV2 = V0;
                }
                
                // NOTE(shvayko): Solve for t when z component is equal to near z
                
                // NOTE(shvayko): first created new vertex
                
                // NOTE(shvayko): 1.0f is near plane Z
                f32 t = 1.0f-TmpV2.z / (TmpV0.z - TmpV2.z); 
                
                f32 X0i = TmpV2.x + (TmpV0.x - TmpV2.x)*t;
                f32 Y0i = TmpV2.y + (TmpV0.y - TmpV2.y)*t;
                f32 Z0i = TmpV2.z + (TmpV0.z - TmpV2.z)*t;
                
                // NOTE(shvayko): second created new vertex
                
                f32 t1 = 1.0f-TmpV2.z / (TmpV1.z - TmpV2.z);
                
                f32 X1i = TmpV2.x + (TmpV1.x - TmpV2.x)*t1;
                f32 Y1i = TmpV2.y + (TmpV1.y - TmpV2.y)*t1;
                f32 Z1i = TmpV2.z + (TmpV1.z - TmpV2.z)*t1;
                
                // NOTE(shvayko): Split into 2 triangles
                
                AddTriangle(TmpV0,v3f(X0i,Y0i,1.1f),TmpV1,Triangle->Color);
                AddTriangle(TmpV0,TmpV1,v3f(X1i,Y1i,1.1f),Triangle->Color);
            }
            else
            {
                assert(!"lol");
            }
        }
        else
        {
            // NOTE(shvayko): All vertices is in Z range. Process without any clipping
            
            // NOTE(shvayko): Pespective divide. (Transforming from Clip Space into NDC space)
            
            v3 NdcV0,NdcV1,NdcV2;
            TransformHomogeneousToNDC(ClipV0,ClipV1,ClipV2,&NdcV0,&NdcV1,&NdcV2);
            
            // NOTE(shvayko):Viewport tranformation(Transforming from NDC space(-1.0f - 1.0f))
            // to screen space(0 - Width, 0 - Height)
            
            v3 WinPV0,WinPV1,WinPV2;
            Viewport(NdcV0,NdcV1,NdcV2,&WinPV0,&WinPV1,&WinPV2,ClipV0.z,ClipV1.z,ClipV2.z);
            
            // NOTE(shvayko): Rasterization Stage
            DrawTriangle(Backbuffer,WinPV0,WinPV1,WinPV2, Triangle->Color);
        }
 | 
| 1 2 3 4 | f32 t = 1.0f-TmpV1.z / (TmpV0.z - TmpV1.z); // Should be f32 t = (1.0f-TmpV1.z) / (TmpV0.z - TmpV1.z); | 
| 1 2 | f32 t = ( -w - TmpV1.z ) / ( TmpV0.z - TmpV1.z ); // But what is w ? | 
| 1 2 3 4 5 | v3 inside = v3( TmpV0.x / TmpV0.w, TmpV0.y / TmpV0.w, TmpV0.z / TmpV0.w ); v3 outside = v3( TmpV1.x / TmpV1.w, TmpV1.y / TmpV1.w, TmpV1.z / TmpV1.w ); // In ndc space, -1.0 is the near plane f32 t = ( -1.0f - outside.z ) / ( inside.z - outside.z ); v3 new_point_in_ndc = outside + ( inside - outside ) * t; | 
ExTray2020
Thanks for your answer. I appreciate that.
A very dumb mistake with parentheses. Fixed it. it's working better now. Thank you.
I think you are right about that I cannot use vertices like that. Your way seems resonable but I need to give the AddTriangle function vertices in world's coordinates not in NDC. So I don't know how to approach that. May be you know how to translate ndc coordinates into world space? Also, I think I may change architecture of my rendering loop without adding new triangles in the end list. I just will render and transform my new constructed triangles right in place. By the way, can you suggest way to handle that?