using System;
using System.Xml;
using CDAColladaNET.Import.Attributes;
// Copyright (c) 2005 Accelerated Pictures, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
namespace ColladaNET.Import{
public class PolygonGroup : ColladaNode // NOTE: does not inherit from NamedNode because no id or name attrs
{
#region Constants
public static readonly string kDoubleSided_ParamName = "DOUBLE_SIDED";
public static bool kDoubleSided_Default = true;
private static readonly string kParams = "dae:param";
private static readonly string kInputs = "dae:input";
private static readonly string kPolygons = "dae:p";
private static readonly string kMaterial = "@material";
#endregion
#region Accessors
private Mesh mMesh;
public Mesh Mesh { get { return mMesh; } }
#region MaterialUrl
private bool mbMaterialUrl = false;
private string mMaterialUrl;
public string MaterialUrl
{
get
{
if ( mbMaterialUrl == false )
{
mMaterialUrl = XmlSource.SelectSingleNode( kMaterial , Collada.NS ).Value ;
mbMaterialUrl = true;
}
return mMaterialUrl;
}
}
#endregion
private CDA.InputsAttr mInputs;
public CDA.InputsAttr Inputs { get { return mInputs; } }
private CDA.ParamsAttr mParams;
public CDA.ParamsAttr Params { get { return mParams; } }
#region RawPolygons
private bool mbRawPolygons = false;
private int [][] mRawPolygons;
private int [][] RawPolygons
{
get
{
if ( mbRawPolygons == false )
{
XmlNodeList nodes = XmlSource.SelectNodes( kPolygons , Collada.NS );
mRawPolygons = new int[ nodes.Count ][];
for ( int polyIndex = 0 ; polyIndex < nodes.Count ; polyIndex++ )
{
string innerText = nodes[polyIndex].InnerText;
string [] tokens = innerText.Split( kWhitespace );
int nonNullTokenCount = 0;
for ( int scanIndex = 0 ; scanIndex < tokens.Length ; scanIndex++ )
{
if ( tokens[scanIndex].Length > 0 )
{
nonNullTokenCount++;
}
}
int[] verts = new int[ nonNullTokenCount ];
int tokenIndex = 0;
for( int vertIndex = 0 ; (tokenIndex < tokens.Length)&&(vertIndex < verts.Length) ; vertIndex++ )
{
string token = tokens[tokenIndex++];
while ( ( tokenIndex < tokens.Length )
&&( token.Length == 0 ) )
{
token = tokens[tokenIndex++];
}
verts[vertIndex] = int.Parse(token);
}
mRawPolygons[polyIndex] = verts;
}
mbRawPolygons = true;
}
return mRawPolygons;
}
}
#endregion
public int [][] GetPolygonIndexData( string semantic )
{
Input [] inputs = this.Inputs.GetBySemantic( semantic );
if ( inputs.Length == 0 )
{
return new int[0][]; // ---- EARLY RETURN ----
}
Input input = inputs[0];
int dataStart = input.Idx;
int inputCount = this.Inputs.Length;
int [][] result = new int[RawPolygons.Length][];
for( int polygonIndex = 0 ; polygonIndex < result.Length; polygonIndex++ )
{
int [] data = RawPolygons[ polygonIndex ];
int faceSize = data.Length / inputCount;
int [] face = new int[faceSize];
int dataIndex = dataStart;
for ( int vertIndex = 0 ; (vertIndex < faceSize)&&(dataIndex < data.Length) ; vertIndex++ )
{
face[vertIndex] = data[dataIndex];
dataIndex += inputCount;
}
result[polygonIndex] = face;
}
return result;
}
#region Normals
private bool mbNormals = false;
private float [][] mNormals;
public float [][] Normals
{
get
{
if ( mbNormals == false )
{
Input [] inputs = Inputs.GetBySemantic( Collada.kCommon_Input_NORMAL );
if ( inputs.Length == 0 )
{
return new float[0][]; // ----- EARLY RETURN -----
}
string normalSourceUrl = inputs[0].SourceUrl;
Source normalSource = ((Source)(Mesh.Resolver.ResolveUrl( normalSourceUrl )));
int stride = normalSource.Techniques.GetByProfile( Collada.kCommon )[0].Accessors[0].Stride; // HACK: spec allows multiple accessors but doesn't say how to select which one
if ( stride != 3 )
{
throw new System.NotSupportedException( "Strides other than 3 are not supported at this time" );
}
mNormals = new float[normalSource.Floats.Length/stride][];
int rawIndex = 0;
for( int vertIndex = 0 ; vertIndex < mNormals.Length ; vertIndex++ )
{
float [] normal = new float[stride];
for ( int strideIndex = 0 ; strideIndex < stride ; strideIndex++ )
{
normal[strideIndex] = normalSource.Floats[rawIndex++];
}
mNormals[vertIndex] = normal;
}
mbNormals = true;
}
return mNormals;
}
}
#endregion
#region TexCoords
private bool mbTexCoords = false;
private float [][] mTexCoords;
public float [][] TexCoords
{
get
{
if ( mbTexCoords == false )
{
Input [] inputs = Inputs.GetBySemantic( Collada.kCommon_Input_TEXCOORD );
if ( inputs.Length == 0 )
{
return new float[0][]; // ----- EARLY RETURN -----
}
string texCoordSourceUrl = inputs[0].SourceUrl;
Source texCoordSource = ((Source)(Mesh.Resolver.ResolveUrl( texCoordSourceUrl )));
int stride = texCoordSource.Techniques.GetByProfile( Collada.kCommon )[0].Accessors[0].Stride; // HACK: spec allows multiple accessors but doesn't say how to select which one
if ( stride != 2 )
{
throw new System.NotSupportedException( "Strides other than 2 are not supported at this time" );
}
mTexCoords = new float[texCoordSource.Floats.Length/stride][];
int rawIndex = 0;
for( int vertIndex = 0 ; vertIndex < mTexCoords.Length ; vertIndex++ )
{
float [] texCoord = new float[stride];
for ( int strideIndex = 0 ; strideIndex < stride ; strideIndex++ )
{
texCoord[strideIndex] = texCoordSource.Floats[rawIndex++];
}
mTexCoords[vertIndex] = texCoord;
}
mbTexCoords = true;
}
return mTexCoords;
}
}
#endregion
#endregion
#region Constructors
public PolygonGroup( XmlNode source , Mesh mesh ) : base( source )
{
mInputs = new CDA.InputsAttr( source , kInputs );
mParams = new CDA.ParamsAttr( source , kParams );
mMesh = mesh;
}
#endregion
}
}
|