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;
}