Results 1 to 8 of 8

Thread: OBJ2Map [mesh-wise]

  1. #1
    Sergeant serthy's Avatar
    Join Date
    Nov 2012
    Posts
    450
    Thanks
    96
    Thanked 296 Times in 188 Posts

    OBJ2Map [mesh-wise]

    Hey

    i wrote this simple thing to convert *.obj to *.map!

    THIS IS USING ONLY MESHES!

    it is like the VMF2Map-converter, but in instead of brushes, it is using meshes

    Code:
    <?php
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    
    	ini_set( "memory_limit" , "500M" );
    	
    	$path = "X:\\MODDING\\COD2\\map_source\\";		//output path
    	$name = "objfile";					//input filename
    	$scale = 1;						//output scale
    	$snapToGrid = false;					//this may distort the output!
    	
    	echo "Converting $name.obj!\n";
    
    	$objString = file_get_contents( $name . ".obj" );
    	$obj = parse_OBJ( $objString );
    	$map = export_OBJ2MAP( $obj , $scale , $snapToGrid );
    	
    	file_put_contents( "$path$name.map" , $map );
    	
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    
    function parse_OBJ( $mapSourceString )
    {
    	$obj = array();
    	$obj["faces"] = array();
    	$obj["verts"] = array();
    			
    	$lines = explode( "\n" , $mapSourceString );
    	
    	foreach( $lines as $line )
    	{
    		$temp = explode( " " , $line );
    		$val = $temp[0];
    		
    		switch( $val )
    		{
    			case "#":			//skip the unwanted elements like
    			case "usemtl":			//bezier curves, splines, groubs, objects,
    			case "mtllib":			//materials, vertexnormals, vertextestures etc
    			case "s":			//to stay as easy as possible
    			case "vt":
    			case "vn":
    			case "o":
    				break;
    								
    			case "v":			//plain vertex: v xCoord yCoord zCoord weight
    							//strip only the 3 worldcoords
    							//keep the order to get the globalVertexIndex later on!
    							//this code ignores the lokalVertexIndex
    				$obj["verts"][] = array_slice( $temp , 1 , 3 );
    								
    				break;
    				
    			case "f":			//plain face: f globalVertIndex1/globalVertParamIndex1/globalVertNormalIndex1
    							//this discribes 1 vertex with the globalVertexIndex of the siad vertex
    							//if the globalVertexIndex is negative it will use the lokalVertexIndex! (not used here)
    				$temp = array_slice( $temp , 1 , 3 );
    				
    				//strip the elements and leave the globalVertexIndex
    				foreach( $temp as $key => $val )
    				{
    					$val = explode( "/" , $val );
    					$temp[$key] = $val[0];
    				}
    				
    				$obj["faces"][] = $temp;
    				
    				break;
    		}
    	}
    	
    	return $obj;
    }
    
    function export_OBJ2MAP( $obj , $scale = 1 , $snapToGrid = false )
    {
    	$map = "";
    	$map = "iwmap 4\n";
    	$map .= "{\n";
    	$map .= "\t\"classname\" \"worldspawn\"\n";
    	
    	foreach( $obj["faces"] as $face )
    	{
    		$vertStrArray = array();
    				
    		foreach( $face as $vertIndex )
    		{
    			$vertIndex = (int)$vertIndex - 1;
    			
    			if( $vertIndex < 0 || !isset( $obj["verts"][$vertIndex] ) )
    				break;
    		
    			$vert = $obj["verts"][$vertIndex];
    			
    			$vertStr = "v ";
    			
    			foreach( $vert as $coord )
    			{
    				$coord = (float)$coord * $scale;
    				
    				if( $snapToGrid )
    					$coord = round( $coord );
    					
    				$vertStr .= $coord;
    				$vertStr .= " ";
    			}
    
    			$vertStr .= "t -160 -160 -0.625 0.625\n";
    
    			$vertStrArray[] = $vertStr;
    		}
    
    		if( count( $vertStrArray ) != 3 )		//this code handles only trinagles!
    			continue;				//so your *.obj file should consists out of them!
    		
    		$faceStr = "";
    		$faceStr .= "\t{\n";
    		$faceStr .= "\t\tmesh\n";
    		$faceStr .= "\t\t{\n";
    		$faceStr .= "\t\t\tcaulk\n";
    		$faceStr .= "\t\t\tlightmap_grey\n";
    		$faceStr .= "\t\t\t2 2 16 8\n";
    		$faceStr .= "\t\t\t(\n";
    		$faceStr .= "\t\t\t\t$vertStrArray[0]";		//play with the indexes here
    		$faceStr .= "\t\t\t\t$vertStrArray[1]";		//there must be 3 uniques (0,1,2)
    		$faceStr .= "\t\t\t)\n";
    		$faceStr .= "\t\t\t(\n";
    		$faceStr .= "\t\t\t\t$vertStrArray[2]";		//and one duplicate > quad to triangle!
    		$faceStr .= "\t\t\t\t$vertStrArray[2]";		//this is the best for me right now
    		$faceStr .= "\t\t\t)\n";
    		$faceStr .= "\t\t}\n";
    		$faceStr .= "\t}\n";
    			
    		$map .= $faceStr;
    	}
    	
    	$map .= "}\n";
    	
    	return $map;
    }
    usage: VMF2Map


    cheers Serthy
    Last edited by serthy; 16th December 2012 at 13:40.

  2. The Following User Says Thank You to serthy For This Useful Post:

    kung foo man (16th December 2012)

  3. #2
    Assadministrator kung foo man's Avatar
    Join Date
    Jun 2012
    Location
    trailerpark
    Posts
    2,010
    Thanks
    2,102
    Thanked 1,084 Times in 753 Posts
    Hey, nice work

    Just tried it, but from inside its invisible. Is it only for decoration?

    Click image for larger version. 

Name:	obj2mesh.png 
Views:	105 
Size:	519.8 KB 
ID:	91
    timescale 0.01

  4. #3
    Sergeant serthy's Avatar
    Join Date
    Nov 2012
    Posts
    450
    Thanks
    96
    Thanked 296 Times in 188 Posts
    in Radiant:
    select all [i]
    flip normals [shift + i]

    the texturing is not working at all, also in fact that this is using triangles (and the *.map requires at least 2x2 vertices, so the fourth is just a copie of another) there is no way (for me right now) to point out the normals, textures, lightmaps. you cant also connect every plane to the next, since *.map uses 2 types of vertices (red & pink ones)

    to flip the normals you have to switch the Y and Z coordinate for every vertex of that mesh (in *.map)

    here is the *.OBJ file format reference.. Attachment 92 if someone is interested in it lol
    Last edited by serthy; 16th December 2012 at 19:10.

  5. The Following User Says Thank You to serthy For This Useful Post:

    kung foo man (16th December 2012)

  6. #4
    Assadministrator kung foo man's Avatar
    Join Date
    Jun 2012
    Location
    trailerpark
    Posts
    2,010
    Thanks
    2,102
    Thanked 1,084 Times in 753 Posts
    Hey, here is what i needed to do also:

    Select all: I
    Click some Texture
    Open Surface inspector (press S) then [Fit]-button
    Selection -> Rotate -> Rotate Y
    Selection -> Scale 100,100,100

    Then it looks usable

    Click image for larger version. 

Name:	obj2mesh.png 
Views:	110 
Size:	1.63 MB 
ID:	93
    timescale 0.01

  7. #5
    Sergeant serthy's Avatar
    Join Date
    Nov 2012
    Posts
    450
    Thanks
    96
    Thanked 296 Times in 188 Posts
    fixed rotation
    added paths
    PHP Code:
    <?php
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

        
    ini_set"memory_limit" "500M" );
        
        
    $name "testmap";                            //input filename
        
    $scale 35;                                //output scale
        
    $snapToGrid true;                        //this may distort the output!
        
    $texture "case";                        //default texture
        
    $version "cod2";                        //game version

        
    switch( $version )
        {
            case 
    "cod5":
                
    $path "G:\\Modding\\spiele\\cod5\\map_source\\SERTHYWARS\\";
                break;
            case 
    "cod2":
                
    $path "X:\\MODDING\\COD2\\map_source\\";
                break;
            default:
                
    $path "X:\\MODDING\\COD2\\map_source\\";
                break;
        }

        echo 
    "Converting $name.obj!\n";

        
    $objString file_get_contents$name ".obj" );
        
    $obj parse_OBJ$objString );
        
    $map export_OBJ2MAP$obj $scale $snapToGrid $texture $version );
        
        
    file_put_contents"$path$name.map" $map );
        
        echo 
    "Converting done!\n";

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    function parse_OBJ$mapSourceString )
    {
        
    $obj = array();
        
    $obj["faces"] = array();
        
    $obj["verts"] = array();
                
        
    $lines explode"\n" $mapSourceString );
        
        foreach( 
    $lines as $line )
        {
            
    $temp explode" " $line );
            
    $val $temp[0];
            
            switch( 
    $val )
            {
                case 
    "#":            //skip the unwanted elements like
                
    case "usemtl":        //bezier curves, splines, groubs, objects,
                
    case "mtllib":        //materials, vertexnormals, vertextestures etc
                
    case "s":            //to stay as easy as possible
                
    case "vt":
                case 
    "vn":
                case 
    "o":
                    break;
                                    
                case 
    "v":            //plain vertex: v xCoord yCoord zCoord weight
                                //strip only the 3 worldcoords
                                //keep the order to get the globalVertexIndex later on!
                                //this code ignores the lokalVertexIndex
                    
    $obj["verts"][] = array_slice$temp );
                                    
                    break;
                    
                case 
    "f":            //plain face: f globalVertIndex1/globalVertParamIndex1/globalVertNormalIndex1
                                //this discribes 1 vertex with the globalVertexIndex of the siad vertex
                                //if the globalVertexIndex is negative it will use the lokalVertexIndex! (not used here)
                    
    $temp array_slice$temp );
                    
                    
    //strip the elements and leave the globalVertexIndex
                    
    foreach( $temp as $key => $val )
                    {
                        
    $val explode"/" $val );
                        
    $temp[$key] = $val[0];
                    }
                    
                    
    $obj["faces"][] = $temp;
                    
                    break;
            }
        }
        
        return 
    $obj;
    }

    function 
    export_OBJ2MAP$obj $scale $snapToGrid true $texture "case" $version "cod2" )
    {
        
    $map "";
        
    $map .= "iwmap 4\n";

        if( 
    $version == "cod5" || $version == "cod4" )
        {
            
    $map .= "\"000_Global\" flags  active\n";
            
    $map .= "\"The Map\" flags\n";
        }

        
    $map .= "{\n";
        
    $map .= "\t\"classname\" \"worldspawn\"\n";
        
        foreach( 
    $obj["faces"] as $face )
        {
            
    $vertStrArray = array();
                    
            foreach( 
    $face as $vertIndex )
            {
                
    $vertIndex = (int)$vertIndex 1;
                
                if( 
    $vertIndex || !isset( $obj["verts"][$vertIndex] ) || count$obj["verts"][$vertIndex] ) != )
                    break;
            
                
    $vert $obj["verts"][$vertIndex];
                
                for( 
    $c $c $c++ )
                {
                    
    $coord = (float)$vert[$c] * $scale;

                    if( 
    $snapToGrid )
                        
    $coord round$coord );

                    
    $vert[$c] = $coord;
                }

                
    $vertStrArray[] = "v $vert[0] $vert[2] $vert[1] t -1600 -1600 -0.625 0.625\n";
            }

            if( 
    count$vertStrArray ) != )            //this code handles only trinagles!
                
    continue;                        //so your *.obj file should consists out of them!
            
            
    $faceStr "";
            
    $faceStr .= "\t{\n";
            
    $faceStr .= "\t\tmesh\n";
            
    $faceStr .= "\t\t{\n";
            
    $faceStr .= "\t\t\ttoolFlags splitGeo;\n";
            
    $faceStr .= "\t\t\t$texture\n";
            
    $faceStr .= "\t\t\tlightmap_gray\n";
            
    $faceStr .= "\t\t\t2 2 16 8\n";
            
    $faceStr .= "\t\t\t(\n";
            
    $faceStr .= "\t\t\t\t$vertStrArray[0]";        //play with the indexes here
            
    $faceStr .= "\t\t\t\t$vertStrArray[0]";        //there must be 3 uniques (0,1,2)
            
    $faceStr .= "\t\t\t)\n";
            
    $faceStr .= "\t\t\t(\n";
            
    $faceStr .= "\t\t\t\t$vertStrArray[1]";        //and one duplicate > quad to triangle!
            
    $faceStr .= "\t\t\t\t$vertStrArray[2]";        //this is the best for me right now
            
    $faceStr .= "\t\t\t)\n";
            
    $faceStr .= "\t\t}\n";
            
    $faceStr .= "\t}\n";
                
            
    $map .= $faceStr;
        }
        
        
    $map .= "}\n";
        
        return 
    $map;
    }
    to get the best & rly fast texture results:
    set $version to cod5
    convert
    open it in codwawRadiant
    select all [i]
    invert meshes [shift+i]
    hit a texture
    bring up the surface inspector [s]
    hit [LMAP]
    Last edited by serthy; 17th December 2012 at 13:02.

  8. The Following User Says Thank You to serthy For This Useful Post:

    kung foo man (17th December 2012)

  9. #6
    Assadministrator kung foo man's Avatar
    Join Date
    Jun 2012
    Location
    trailerpark
    Posts
    2,010
    Thanks
    2,102
    Thanked 1,084 Times in 753 Posts
    Hm, whats the difference to cod2-radiant?
    timescale 0.01

  10. #7
    Sergeant serthy's Avatar
    Join Date
    Nov 2012
    Posts
    450
    Thanks
    96
    Thanked 296 Times in 188 Posts
    1. waw CAP
    2. cod2 LMAP
    3. waw FIT
    4. waw LMAP (best results)
    5. waw NATURAL

  11. The Following User Says Thank You to serthy For This Useful Post:

    kung foo man (18th December 2012)

  12. #8
    ... connecting
    Join Date
    Apr 2024
    Posts
    1
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Hello, with the help of a ChatGPT 3.5, I fixed Serthy's OBJ2Map so now it uses the material names of your meshes from OBJ.

    Code:
    <?php
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    
        ini_set( "memory_limit" , "500M" );
        
        $name = "my_obj";                            //input filename
        $scale = 1;                                //output scale
        $snapToGrid = false;                        //this may distort the output!
        $texture = "case";                        //default texture
        $version = "cod2";                        //game version
    
        switch( $version )
        {
            case "cod5":
                $path = "D:/";
                break;
            case "cod2":
                $path = "D:/";
                break;
            default:
                $path = "D:/";
                break;
        }
    
        echo "Converting $name.obj!\n";
    
        $objString = file_get_contents( $name . ".obj" );
        $obj = parse_OBJ( $objString );
        $map = export_OBJ2MAP( $obj , $scale , $snapToGrid , $texture , $version );
        
        file_put_contents( "$path$name.map" , $map );
        
        echo "Converting done!\n";
    
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
    
    function parse_OBJ($mapSourceString)
    {
        $obj = array();
        $obj["faces"] = array();
        $obj["verts"] = array();
        $obj["materials"] = array(); // Store materials as associative array
                
        $lines = explode("\n", $mapSourceString);
        
        $currentMaterial = null;
    
        foreach ($lines as $line) {
            $temp = explode(" ", $line);
            $val = $temp[0];
            
            switch ($val) {
                case "#":
                    break;
                case "usemtl":
                    // Extract material name and store it
                    if (isset($temp[1])) {
                        $currentMaterial = trim($temp[1]);
                    }
                    break;
                case "mtllib":
                case "s":
                case "vt":
                case "vn":
                case "o":
                    break;
                                    
                case "v":
                    $obj["verts"][] = array_slice($temp, 1, 3);
                    break;
                    
                case "f":
                    $temp = array_slice($temp, 1, 3);
                    
                    foreach ($temp as $key => $val) {
                        $val = explode("/", $val);
                        $temp[$key] = $val[0];
                    }
                    
                    $materialName = $currentMaterial !== null ? $currentMaterial : "defaultMaterial";
                    $obj["faces"][] = array("indices" => $temp, "material" => $materialName);
                    break;
            }
        }
        
        return $obj;
    }
    
    function export_OBJ2MAP($obj, $scale = 1, $snapToGrid = true, $version = "cod2")
    {
        $map = "";
        $map .= "iwmap 4\n";
    
        if ($version == "cod5" || $version == "cod4") {
            $map .= "\"000_Global\" flags  active\n";
            $map .= "\"The Map\" flags\n";
        }
    
        $map .= "{\n";
        $map .= "\t\"classname\" \"worldspawn\"\n";
    
        foreach ($obj["faces"] as $face) {
            $vertStrArray = array();
    
            foreach ($face["indices"] as $vertIndex) {
                $vertIndex = (int)$vertIndex - 1;
    
                if ($vertIndex < 0 || !isset($obj["verts"][$vertIndex]) || count($obj["verts"][$vertIndex]) != 3)
                    break;
    
                $vert = $obj["verts"][$vertIndex];
    
                for ($c = 0; $c < 3; $c++) {
                    $coord = (float)$vert[$c] * $scale;
    
                    if ($snapToGrid)
                        $coord = round($coord);
    
                    $vert[$c] = $coord;
                }
    
                $vertStrArray[] = "v $vert[0] $vert[2] $vert[1] t -1600 -1600 -0.625 0.625\n";
            }
    
            if (count($vertStrArray) != 3)            //this code handles only triangles!
                continue;                        //so your *.obj file should consist only of them!
    
            $materialName = $face["material"];
    
            $faceStr = "";
            $faceStr .= "\t{\n";
            $faceStr .= "\t\tmesh\n";
            $faceStr .= "\t\t{\n";
            $faceStr .= "\t\t\ttoolFlags splitGeo;\n";
            $faceStr .= "\t\t\t$materialName\n"; // Use the material name associated with the face
            $faceStr .= "\t\t\tlightmap_gray\n";
            $faceStr .= "\t\t\t2 2 16 8\n";
            $faceStr .= "\t\t\t(\n";
            $faceStr .= "\t\t\t\t$vertStrArray[0]";        //play with the indexes here
            $faceStr .= "\t\t\t\t$vertStrArray[0]";        //there must be 3 uniques (0,1,2)
            $faceStr .= "\t\t\t)\n";
            $faceStr .= "\t\t\t(\n";
            $faceStr .= "\t\t\t\t$vertStrArray[1]";        //and one duplicate > quad to triangle!
            $faceStr .= "\t\t\t\t$vertStrArray[2]";        //this is the best for me right now
            $faceStr .= "\t\t\t)\n";
            $faceStr .= "\t\t}\n";
            $faceStr .= "\t}\n";
    
            $map .= $faceStr;
        }
    
        $map .= "}\n";
    
        return $map;
    }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •