Horde3D http://horde3d.org/forums/ |
|
AC3D to Horde3D file converter http://horde3d.org/forums/viewtopic.php?f=8&t=573 |
Page 1 of 1 |
Author: | jimbo [ 03.12.2008, 21:14 ] |
Post subject: | AC3D to Horde3D file converter |
I'm writing a converter for AC3D ".ac" file format directly to Horde3D's ".geo" and ".xml" formats. I'm running into a problem concerning texture coordinates. In the AC3D format texture coordinates are defined per face vertex and in the .geo format they seem to be defined per vertex. How do I go about converting this, should I add arbitrary vertices to the mesh, remap all indices etc? |
Author: | swiftcoder [ 03.12.2008, 23:24 ] |
Post subject: | Re: AC3D to Horde3D file converter |
jimbo wrote: I'm writing a converter for AC3D ".ac" file format directly to Horde3D's ".geo" and ".xml" formats. Yes, and the process is often called 'vertex welding', in case you want to google it. The same operation is required for wavefront .obj files.
I'm running into a problem concerning texture coordinates. In the AC3D format texture coordinates are defined per face vertex and in the .geo format they seem to be defined per vertex. How do I go about converting this, should I add arbitrary vertices to the mesh, remap all indices etc? |
Author: | jimbo [ 07.12.2008, 14:44 ] |
Post subject: | Re: AC3D to Horde3D file converter |
Thanks, I've made a first version of the converter with a demo project which can be downloaded here: http://corrado.bsdwebhosting.com/~jimbo/ac3dtest.zip The converter is written in Perl, so you need something like http://strawberryperl.com/ to run it. There are a few questions I have: For unwelding I'm adding vertices that have different texture coordinates. For the cube this means it now has 29 vertices instead of 8. Ofcourse unwelding completely would make the cube 36 vertices. But then there are the normals, which are also per vertex. So does this mean: - I can use optimized unwelding for smooth normals? - I need to completely unweld for normals with sharp edges, because no normal can be shared? I hope this makes any sense. |
Author: | swiftcoder [ 07.12.2008, 14:52 ] |
Post subject: | Re: AC3D to Horde3D file converter |
jimbo wrote: For unwelding I'm adding vertices that have different texture coordinates. For the cube this means it now has 29 Ja, that is about right. For hard edges, you need unique normals on either side, so you need to have duplicate vertices, while for smooth edges it doesn't matter.vertices instead of 8. Ofcourse unwelding completely would make the cube 36 vertices. But then there are the normals, which are also per vertex. So does this mean: - I can use optimized unwelding for smooth normals? - I need to completely unweld for normals with sharp edges, because no normal can be shared? Some model formats record information about hard edges separately, but if not, you need to do an angle-check for each vertex (and in each direction). |
Author: | jimbo [ 09.12.2008, 21:28 ] |
Post subject: | Re: AC3D to Horde3D file converter |
Okay, I've updated the converter (v0.2); features are now: - Converts multiple objects/groups to Horde3D .geo format. - Creates material files for textures. - Calculates normals/tangents/bitangents for smooth and hard surfaces. - Support for parallax normal maps. I've included a Windows executable made from the Perl source so anyone can test it. I think the normals could be a bit better for the ball which should be smooth. A demo application is provided. http://corrado.bsdwebhosting.com/~jimbo ... orde3d.zip |
Author: | jimbo [ 13.12.2008, 00:01 ] |
Post subject: | Re: AC3D to Horde3D file converter |
v0.4: http://corrado.bsdwebhosting.com/~jimbo/ac3d2horde3d.zip I made a bunch of changes in v0.4, first all vertices are unwelded, then normals are calculated and vertices are welded again. I succesfully converted a scene with 140.000 vertices and it looks good with the standard.shader. But there still is a problem with parallax mapping. I have normal maps for all models, but when loading them with the parallax shader things look bad: I think the calc_vertex_normals() function is correct, but I don't understand why this visual garbage happens. |
Author: | marciano [ 13.12.2008, 01:41 ] |
Post subject: | Re: AC3D to Horde3D file converter |
Maybe it is a problem with the tangent space calculation? More generally speaking, I think it is great that we get exporters for more and more DCC packages. So thanks a lot for your efforts jimbo! The only issue I see is that all the exporters need to do a lot of code duplication, for example for calculating the tangent space basis or optimizing the vertices for better cache usage. Furthermore, they need to be updated if the Horde formats should change. One way out of that dilemma could be to have a very simple intermediate format that the DCC exporter outputs and that is processed by ColladaConv. So updates and improvements just need to be implemented at one place, namely in ColladaConv. Here is a quick idea for such an intermediate format, inspired by the famous OBJ format. It is no specification and probably something is missing. Code: # Comment
MATERIAL "id" # Material definition with unique name tex "semantic" "image" # Texture semantic (e.g. diffuse, normal, specular) to file mapping # Mesh with name, transformation matrix and optional parent MESH "name"/tm0/tm1/tm2/tm3/tm4/tm5/tm6/tm7/tm8/tm9/tm10/tm11/tm12/tm13/tm14/tm15/["parent"] v x/y/z # Vertex position vt0 u/v # Vertex texture coordinate set 0 vt1 u/v # Vertex texture coordinate set 1 (optional, but must match vt0 if defined) vn x/y/z # Vertex normal vs "joint"/weight ["joint"/weight] usemtl "ref_mtl_id" # Bind a material for the following faces f v/vt/vn/vs v/vt/vn/vs v/vt/vn/vs # Face indexing vertex data defmorph "name" # Morph target definition for mesh mv x/y/z # Vertex position mvn x/y/z # Vertex normal m v/mv/mvn # Morph-Vertex # Joint with name, parent, inverse bind matrix and transformation JOINT "name"/"parent"/bm0/bm1/bm2/bm3/bm4/bm5/bm6/bm7/bm8/bm9/bm10/bm11/bm12/bm13/bm14/bm15/tm0/tm1/tm2/tm3/tm4/tm5/tm6/tm7/tm8/tm9/tm10/tm11/tm12/tm13/tm14/tm15 |
Author: | Mikmacer [ 13.12.2008, 16:46 ] |
Post subject: | Re: AC3D to Horde3D file converter |
jimbo wrote: v0.4: http://corrado.bsdwebhosting.com/~jimbo/ac3d2horde3d.zip I made a bunch of changes in v0.4, first all vertices are unwelded, then normals are calculated and vertices are welded again. I succesfully converted a scene with 140.000 vertices and it looks good with the standard.shader. But there still is a problem with parallax mapping. I have normal maps for all models, but when loading them with the parallax shader things look bad: I think the calc_vertex_normals() function is correct, but I don't understand why this visual garbage happens. Do you have the height map in the alpha channel? This could be the problem, since the normal map only is not enough for the parallax shader. |
Author: | jimbo [ 14.12.2008, 20:57 ] |
Post subject: | Re: AC3D to Horde3D file converter |
I'm a bit stuck on this, my normals/tangents/bitangents calculation works as follows: - Unweld the model completely (no indices point to the same vertex). - Create a map of indices with the same vertex. - Calculate normals/tangents/bitangents for each face and add to all matching indices from the map - Weld all vertices with same coordinates, texture coordinates and normals. Still parallax doesn't look correct (even if I skip welding). If I disable smoothing things look a bit better, but not correct either. I've made a little demo to demonstrate the problem: http://corrado.bsdwebhosting.com/~jimbo/trouble.zip Also I've added the same model converted to .obj then to Collada, and then with colladaconv to horde3d, which looks correct. The problem part must be in these functions: Code: # find vertices with same coordinates, this is for normal smoothing, return of list of matching indices
sub find_same_vertices { my $object = shift; my $indices_map = shift; my $index = shift; my $vertex = $object->{numvert}->[$index]; return @{ $indices_map->{ $vertex->as_string } }; } # create map of indices with same vertices sub make_indices_map { my $object = shift; my %indices_map; foreach my $surface ( @{ $object->{numsurf} } ) { # only average out smooth vertex normals next if ( $surface->{SURF}->{shading} ne 'smooth' ); foreach my $ref ( @{ $surface->{refs} } ) { my $v = $object->{numvert}->[ $ref->{index} ]; push @{ $indices_map{ $v->as_string } }, $ref->{index}; } } return \%indices_map; } sub calc_vertex_normals { my $object = shift; warn "calculating normals: $object->{name}\n"; my @normals; my @tangents; my @bitangents; my $indices_map = make_indices_map($object); foreach my $surface ( @{ $object->{numsurf} } ) { my $index0 = $surface->{refs}->[0]->{index}; my $index1 = $surface->{refs}->[1]->{index}; my $index2 = $surface->{refs}->[2]->{index}; my $v0 = $object->{numvert}->[$index0]; my $v1 = $object->{numvert}->[$index1]; my $v2 = $object->{numvert}->[$index2]; my $d0 = $v1 - $v0; my $d1 = $v2 - $v0; my $v = ( $d0 x $d1 )->normalized; # # Calculate the normal,tangent and bitangent for this face and add it # to the running sum of normals for each of the # vertices involved # my $Edge0uv = uv_sub( $surface->{refs}->[1], $surface->{refs}->[0] ); my $Edge1uv = uv_sub( $surface->{refs}->[2], $surface->{refs}->[0] ); my $cp = $Edge0uv->{u} * $Edge1uv->{v} - $Edge1uv->{u} * $Edge0uv->{v}; my $r = 0; if ( $cp != 0 ) { $r = 1.0 / $cp; } my $tangent = ( $d0 * $Edge1uv->{v} - $d1 * $Edge0uv->{v} ) * $r; my $bitangent = ( $d1 * $Edge0uv->{u} - $d0 * $Edge1uv->{u} ) * $r; my @indices; push @indices, find_same_vertices( $object, $indices_map, $index0 ); push @indices, find_same_vertices( $object, $indices_map, $index1 ); push @indices, find_same_vertices( $object, $indices_map, $index2 ); foreach my $index (@indices) { $normals[$index] ||= vec3(); $tangents[$index] ||= vec3(); $bitangents[$index] ||= vec3(); $normals[$index] += $v; $tangents[$index] += $tangent; $bitangents[$index] += $bitangent; } } # Normalize and fixup the vertex normal vectors, tangents en bitangents my $numVerts = int( @{ $object->{numvert} } ); for ( my $j = 0 ; $j < $numVerts ; $j++ ) { my $n = $normals[$j]->normalized; my $t = $tangents[$j]; # orthogonalize $tangents[$j] = ( $t - $n * ( $n * $t ) )->normalized; $normals[$j] = $n; if ( ( $n x $t ) * $bitangents[$j] < 0 ) { $bitangents[$j] = ( $n * -1 ) x $t; } else { $bitangents[$j] = $n x $t; } } $object->{normals} = \@normals; $object->{tangents} = \@tangents; $object->{bitangents} = \@bitangents; } |
Author: | jimbo [ 20.05.2009, 08:00 ] |
Post subject: | Re: AC3D to Horde3D file converter |
Just to let you know all fixed and done, download release here: http://www.horde3d.org/forums/viewtopic.php?f=6&t=748 |
Author: | Volker [ 20.05.2009, 08:57 ] |
Post subject: | Re: AC3D to Horde3D file converter |
Thanks again. I added a link to the wiki. Feel free to add additional information. |
Author: | marciano [ 24.05.2009, 20:48 ] |
Post subject: | Re: AC3D to Horde3D file converter |
Good work, jimbo. It is great to have better support for less expensive modelling packages. |
Page 1 of 1 | All times are UTC + 1 hour |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |