r5368 - trunk/misc

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Thu Jan 1 08:05:57 EST 2009


Author: div0
Date: 2009-01-01 08:05:55 -0500 (Thu, 01 Jan 2009)
New Revision: 5368

Modified:
   trunk/misc/entmerge.pl
Log:
try to properly support "origin" brushes


Modified: trunk/misc/entmerge.pl
===================================================================
--- trunk/misc/entmerge.pl	2008-12-31 13:49:34 UTC (rev 5367)
+++ trunk/misc/entmerge.pl	2009-01-01 13:05:55 UTC (rev 5368)
@@ -2,6 +2,10 @@
 
 use strict;
 use warnings;
+use Carp;
+$SIG{__DIE__} = sub { 
+	Carp::cluck "Exception: $@";
+};
 
 # ent file managing tool
 # usage:
@@ -18,9 +22,225 @@
 #   ent -> bsp:                                            
 #     perl bsptool.pl mapname.bsp -rentities                  < mapname.ent
 
+sub DotProduct($$)
+{
+	my ($a, $b) = @_;
+	return	$a->[0]*$b->[0]
+		+	$a->[1]*$b->[1]
+		+	$a->[2]*$b->[2];
+}
+
+sub CrossProduct($$)
+{
+	my ($a, $b) = @_;
+	return	[
+		$a->[1]*$b->[2] - $a->[2]*$b->[1],
+		$a->[2]*$b->[0] - $a->[0]*$b->[2],
+		$a->[0]*$b->[1] - $a->[1]*$b->[0]
+	];
+}
+
+sub VectorMAM(@)
+{
+	my (@data) = @_;
+	my $out = [0, 0, 0];
+	for my $coord(0..2)
+	{
+		my $c = 0;
+		$c += $data[2*$_ + 0] * $data[2*$_ + 1]->[$coord]
+			for 0..(@data/2 - 1);
+		$out->[$coord] = $c;
+	}
+	return $out;
+}
+
+sub VectorLength2($)
+{
+	my ($v) = @_;
+	return DotProduct $v, $v;
+}
+
+sub VectorLength($)
+{
+	my ($v) = @_;
+	return sqrt VectorLength2 $v;
+}
+
+sub VectorNormalize($)
+{
+	my ($v) = @_;
+	return VectorMAM 1/VectorLength($v), $v;
+}
+
+sub Polygon_QuadForPlane($$)
+{
+	my ($plane, $quadsize) = @_;
+
+	my $quadup;
+	if(abs($plane->[2]) > abs($plane->[0]) && abs($plane->[2]) > abs($plane->[1]))
+	{
+		$quadup = [1, 0, 0];
+	}
+	else
+	{
+		$quadup = [0, 0, 1];
+	}
+
+	$quadup = VectorMAM 1, $quadup, -DotProduct($quadup, $plane), $plane;
+	$quadup = VectorMAM $plane->[3], VectorNormalize $quadup;
+
+	my $quadright = CrossProduct $quadup, $plane;
+
+	return [
+		VectorMAM($plane->[3], $plane, -$quadsize*2, $quadright, +$quadsize*2, $quadup),
+		VectorMAM($plane->[3], $plane, +$quadsize*2, $quadright, +$quadsize*2, $quadup),
+		VectorMAM($plane->[3], $plane, +$quadsize*2, $quadright, -$quadsize*2, $quadup),
+		VectorMAM($plane->[3], $plane, -$quadsize*2, $quadright, -$quadsize*2, $quadup)
+	];
+}
+
+sub Polygon_Clip($$$)
+{
+	my ($points, $plane, $epsilon) = @_;
+
+	if(@$points < 1)
+	{
+		return [];
+	}
+
+	my $n = 0;
+	my $ndist = DotProduct($points->[$n], $plane) - $plane->[3];
+
+	my @outfrontpoints = ();
+
+	for my $i(0..@$points - 1)
+	{
+		my $p = $n;
+		my $pdist = $ndist;
+		$n = ($i+1) % @$points;
+		$ndist = DotProduct($points->[$n], $plane) - $plane->[3];
+		if($pdist >= -$epsilon)
+		{
+			push @outfrontpoints, $points->[$p];
+		}
+		if(($pdist > $epsilon && $ndist < -$epsilon) || ($pdist < -$epsilon && $ndist > $epsilon))
+		{
+			my $frac = $pdist / ($pdist - $ndist);
+			push @outfrontpoints, VectorMAM 1-$frac, $points->[$p], $frac, $points->[$n];
+		}
+	}
+
+	return \@outfrontpoints;
+}
+
+sub MakePlane($$$)
+{
+	my ($p, $q, $r) = @_;
+
+	my $a = VectorMAM 1, $q, -1, $p;
+	my $b = VectorMAM 1, $r, -1, $p;
+	my $n = VectorNormalize CrossProduct $a, $b;
+
+	return [ @$n, DotProduct $n, $p ];
+}
+
+sub GetBrushWindings($)
+{
+	my ($planes) = @_;
+
+	my @windings = ();
+
+	for my $i(0..(@$planes - 1))
+	{
+		my $winding = Polygon_QuadForPlane $planes->[$i], 65536;
+
+		for my $j(0..(@$planes - 1))
+		{
+			next
+				if $i == $j;
+			$winding = Polygon_Clip $winding, $planes->[$j], 1/64.0;
+		}
+
+		push @windings, $winding
+			unless @$winding == 0;
+	}
+
+	return \@windings;
+}
+
+sub GetBrushMinMax($)
+{
+	my ($brush) = @_;
+
+	if($brush->[0] =~ /^\(/)
+	{
+		# plain brush
+		my @planes = ();
+		for(@$brush)
+		{
+			/^\(\s+(\S+)\s+(\S+)\s+(\S+)\s+\)\s+\(\s+(\S+)\s+(\S+)\s+(\S+)\s+\)\s+\(\s+(\S+)\s+(\S+)\s+(\S+)\s+\)\s+/
+				or die "Invalid line in plain brush: $_";
+			push @planes, MakePlane [ $1, $2, $3 ], [ $4, $5, $6 ], [ $7, $8, $9 ];
+			# for any three planes, find their intersection
+			# check if the intersection is inside all other planes
+		}
+		
+		my $windings = GetBrushWindings \@planes;
+
+		my (@mins, @maxs);
+
+		for(@$windings)
+		{
+			for my $v(@$_)
+			{
+				if(@mins)
+				{
+					for(0..2)
+					{
+						$mins[$_] = $v->[$_] if $mins[$_] > $v->[$_];
+						$maxs[$_] = $v->[$_] if $maxs[$_] < $v->[$_];
+					}
+				}
+				else
+				{
+					@mins = @$v;
+					@maxs = @$v;
+				}
+			}
+		}
+
+		return undef
+			unless @mins;
+		return \@mins, \@maxs;
+	}
+
+	die "Cannot decode this brush yet! brush is @$brush";
+}
+
 sub BrushOrigin($)
 {
-	warn "Origin brushes not supported yet";
+	my ($brushes) = @_;
+
+	my @org = ();
+
+	for my $brush(@$brushes)
+	{
+		my $isorigin = 0;
+		for(@$brush)
+		{
+			$isorigin = 1
+				if /\bcommon\/origin\b/;
+		}
+		if($isorigin)
+		{
+			my ($mins, $maxs) = GetBrushMinMax $brush;
+			@org = map { 0.5 * ($mins->[$_] + $maxs->[$_]) } 0..2
+				if defined $mins;
+		}
+	}
+
+	return \@org
+		if @org;
 	return undef;
 }
 
@@ -230,6 +450,18 @@
 			}
 		}
 
+		if(defined $ent->{model} and $ent->{model} =~ /^\*(\d+)$/)
+		{
+			my $entfileorigin = [ split /\s+/, ($ent->{origin} || "0 0 0") ];
+			my $baseorigin = BrushOrigin $submodels[$1];
+
+			if(defined $baseorigin)
+			{
+				my $org = VectorMAM 1, $entfileorigin, -1, $baseorigin;
+				$ent->{origin} = sprintf "%.6f %.6f %.6f", @$org;
+			}
+		}
+
 		push @entities_entfile, $ent;
 		$first = 0;
 	}
@@ -281,9 +513,14 @@
 
 		if(defined $e{model} and $e{model} =~ /^\*(\d+)$/)
 		{
-			my $org = BrushOrigin $submodels{$e{origin}};
-			$e{origin} = $org
-				if defined $org;
+			my $oldorigin = [ split /\s+/, ($e{origin} || "0 0 0") ];
+			my $org = BrushOrigin $submodels[$1];
+
+			if(defined $org)
+			{
+				$org = VectorMAM 1, $org, 1, $oldorigin;
+				$e{origin} = sprintf "%.6f %.6f %.6f", @$org;
+			}
 		}
 
 		$e{gridsize} = "64 64 128" if not exists $e{gridsize};




More information about the nexuiz-commits mailing list