+ // Create V reference based on first displacement.
+ // TODO: This is not the most stable selection method!
+ // faces can come in any order, so the first disp will of course
+ // always vary. Additionaly the triangle can be oriented differently.
+ //
+ // Improvement can be made by selecting a first disp/triangle based
+ // on deterministic factors.
+ //
+ if( disp_count == 0 )
+ {
+ struct cxr_texinfo tx;
+ v3f tri_ref[3];
+ v3_copy( cxr_ab_ptr(abverts,dispedge[0]), tri_ref[0] );
+ v3_copy( cxr_ab_ptr(abverts,dispedge[4]), tri_ref[1] );
+ v3_copy( cxr_ab_ptr(abverts,dispedge[8]), tri_ref[2] );
+ cxr_calculate_axis( &tx, tri_ref, corner_uvs, (v2f){512,512} );
+
+ v3_muls( tx.vaxis, -1.0, refv );
+ int v_cardinal = cxr_cardinal( refv, n_cardinal );
+ v3_copy( avg_normal, refn );
+ int u_cardinal = 0;
+ if( u_cardinal == n_cardinal || u_cardinal == v_cardinal ) u_cardinal ++;
+ if( u_cardinal == n_cardinal || u_cardinal == v_cardinal ) u_cardinal ++;
+
+ v3_zero(refu);
+ refu[u_cardinal] = tx.uaxis[u_cardinal] > 0.0? 1.0: -1.0;
+
+ v3f p0, pv, pu, pn;
+
+ v3_copy( face_center, p0 );
+ v3_muladds( face_center, refn, 1.5, pn );
+ v3_muladds( face_center, refv, 1.5, pv );
+ v3_muladds( face_center, refu, 1.5, pu );
+
+ cxr_debug_line( p0, pn, (v4f){0.0,0.0,1.0,1.0});
+ cxr_debug_line( p0, pv, (v4f){0.0,1.0,0.0,1.0});
+ cxr_debug_line( p0, pu, (v4f){1.0,0.0,0.0,1.0});
+ cxr_debug_line( tri_ref[0], tri_ref[1], (v4f){1.0,1.0,1.0,1.0} );
+ cxr_debug_line( tri_ref[1], tri_ref[2], (v4f){1.0,1.0,1.0,1.0} );
+ cxr_debug_line( tri_ref[2], tri_ref[0], (v4f){1.0,1.0,1.0,1.0} );
+ }
+
+ // Create world cordinates
+ v3f world_corners[8];
+ v2f world_uv[4];
+
+ for( int j=0; j<4; j++ )
+ {
+ v2f local_uv;
+ v2_sub( corner_uvs[j], uv_center, local_uv );
+ v2_copy( corner_uvs[j], world_uv[j] );
+ v2_muls( local_uv, sf, local_uv );
+
+ v3_muls( refu, local_uv[0], world_corners[j] );
+ v3_muladds( world_corners[j], refv, local_uv[1], world_corners[j] );
+ v3_add( face_center, world_corners[j], world_corners[j] );
+ }
+
+ double *colour = colours_random[cxr_range(disp_count,8)];
+ cxr_debug_arrow( world_corners[0], world_corners[1], avg_normal, 0.1, colour );
+ cxr_debug_arrow( world_corners[1], world_corners[2], avg_normal, 0.1, colour );
+ cxr_debug_arrow( world_corners[2], world_corners[3], avg_normal, 0.1, colour );
+ cxr_debug_arrow( world_corners[3], world_corners[0], avg_normal, 0.1, colour );
+
+ for( int j=0; j<4; j++ )
+ v3_muladds( world_corners[j], refn, -1.0, world_corners[j+4] );
+
+ // Apply world transform
+ for( int j=0; j<8; j++ )
+ {
+ v3_muls( world_corners[j], cxr_context.scale_factor, world_corners[j] );
+ world_corners[j][2] += cxr_context.offset_z;
+ }
+
+ if( disp_count == 0 )
+ {
+ cxr_calculate_axis( &texinfo_shared, world_corners, world_uv,
+ (v2f){ matptr->res[0], matptr->res[1] } );
+ }
+
+ // Write brush
+ cxr_vdf_node( output, "solid" );
+ cxr_vdf_ki32( output, "id", ++ cxr_context.brush_count );
+
+ int sides[6][3] =
+ {{ 0, 1, 2 },
+ { 4, 6, 5 },
+ { 4, 1, 0 },
+ { 7, 0, 3 },
+ { 6, 2, 1 },
+ { 6, 3, 2 }};
+
+ v3f normals[25];
+ double distances[25];
+
+ v3f lside0, lside1, lref, vdelta, vworld;
+ double tx, ty;
+
+ for( int j=0; j<5; j++ )
+ {
+ ty = (double)j/(double)(5-1);
+
+ v3_lerp( world_corners[0], world_corners[3], ty, lside0 );
+ v3_lerp( world_corners[1], world_corners[2], ty, lside1 );
+
+ for( int k=0; k<5; k++ )
+ {
+ int index = j*5+k;
+
+ tx = (double)k/(double)(5-1);
+ v3_lerp( lside0, lside1, tx, lref );
+ v3_muls( cxr_ab_ptr(abverts, grid[index]), cxr_context.scale_factor, vworld );
+ vworld[2] += cxr_context.offset_z;
+
+ v3_sub( vworld, lref, vdelta );
+ v3_copy( vdelta, normals[index] );
+ v3_normalize( normals[index] );
+ distances[index] = v3_dot( vdelta, normals[index] );
+ }
+ }
+
+ for( int j=0; j<6; j++ )
+ {
+ int *side = sides[j];
+
+ cxr_vdf_node( output, "side" );
+ cxr_vdf_ki32( output, "id", ++ cxr_context.face_count );
+ cxr_vdf_plane( output, "plane", world_corners[side[2]],
+ world_corners[side[1]],
+ world_corners[side[0]] );
+
+ cxr_vdf_kv( output, "material", matptr->vmt_path );
+
+ cxr_vdf_kaxis( output, "uaxis",
+ texinfo_shared.uaxis,
+ texinfo_shared.offset[0],
+ texinfo_shared.scale[0] );
+ cxr_vdf_kaxis( output, "vaxis",
+ texinfo_shared.vaxis,
+ texinfo_shared.offset[1],
+ texinfo_shared.scale[1] );
+
+ cxr_vdf_kdouble( output, "rotation", 0.0 );
+ cxr_vdf_ki32( output, "lightmapscale", cxr_settings.lightmap_scale );
+ cxr_vdf_ki32( output, "smoothing_groups", 0 );
+
+ if( j == 0 )
+ {
+ cxr_vdf_node( output, "dispinfo" );
+ cxr_vdf_ki32( output, "power", 2 );
+ cxr_vdf_kv3f( output, "startposition", world_corners[0] );
+ cxr_vdf_ki32( output, "flags", 0 );
+ cxr_vdf_kdouble( output, "elevation", 0.0 );
+ cxr_vdf_ki32( output, "subdiv", 0 );
+
+ cxr_vdf_node( output, "normals" );
+ for( int k=0; k<5; k++ )
+ cxr_vdf_karrv3f( output, "row", k, &normals[k*5], 5 );
+ cxr_vdf_edon( output );
+
+ cxr_vdf_node( output, "distances" );
+ for( int k=0; k<5; k++ )
+ cxr_vdf_karrdouble( output, "row", k, &distances[k*5], 5 );
+ cxr_vdf_edon( output );
+
+ // TODO: This might be needed for compiling...
+ /*
+ cxr_vdf_node( output, "offsets" );
+ for( int k=0; k<5; k++ )
+ cxr_vdf_printf( output, "\"row%d\" \"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\"\n", k );
+ cxr_vdf_edon( output );
+
+ cxr_vdf_node( output, "offset_normals" );
+ for( int k=0; k<5; k++ )
+ cxr_vdf_printf( output, "\"row%d\" \"0 0 1 0 0 1 0 0 1 0 0 1 0 0 1\"\n", k );
+ cxr_vdf_edon( output );
+
+ cxr_vdf_node( output, "alphas" );
+ for( int k=0; k<5; k++ )
+ cxr_vdf_printf( output, "\"row%d\" \"0 0 0 0 0\"\n", k );
+ cxr_vdf_edon( output );
+
+ cxr_vdf_node( output, "triangle_tags" );
+ for( int k=0; k<5-1; k++ )
+ cxr_vdf_printf( output, "\"row%d\" \"9 9 9 9 9 9 9 9\"\n", k );
+ cxr_vdf_edon( output );
+
+ cxr_vdf_node( output, "allowed_verts" );
+ cxr_vdf_printf( output, "\"10\" \"-1 -1 -1 -1 -1 -1 -1 -1 -1 -1\"\n" );
+ cxr_vdf_edon( output );
+ */
+ cxr_vdf_edon( output );
+ }
+
+ cxr_vdf_edon( output );
+ }
+
+ cxr_vdf_node(output, "editor");
+ cxr_vdf_colour255(output,"color", colours_random[cxr_range(cxr_context.brush_count,8)]);
+ cxr_vdf_ki32(output,"visgroupshown",1);
+ cxr_vdf_ki32(output,"visgroupautoshown",1);
+ cxr_vdf_edon(output);
+
+ cxr_vdf_edon( output );
+ disp_count ++;