- 2024年10月
- 2021年5月
- 2020年8月
- 2020年6月
- 2020年5月
- 2019年1月
- 2018年8月
- 2018年6月
- 2018年5月
- 2018年3月
- 2018年1月
- 2017年12月
- 2017年11月
- 2017年10月
- 2017年9月
- 2017年8月
- 2017年7月
- 2017年6月
- 2016年11月
- 2013年9月
- 2013年8月
- 2013年6月
- 2013年5月
- 2013年4月
- 2013年3月
- 2013年2月
- 2013年1月
- 2012年12月
- 2012年11月
- 2012年10月
- 2012年9月
- 2012年6月
- 2012年5月
- 2012年4月
- 2012年2月
- 2011年7月
- 2011年5月
- 2011年4月
- 2011年2月
- 2010年12月
- 2010年11月
- 2010年10月
- 2010年9月
- 2010年8月
- 2010年7月
- 2010年6月
- 2010年5月
- 2010年4月
- 2010年3月
- 2010年2月
- 2010年1月
- 2009年12月
- 2008年2月
- 2008年1月
- 2007年12月
- 2007年5月
- 2007年4月
- 2007年3月
- 2007年2月
JavaScriptでテキストデータの読み込み / magicien
JavaScriptでXファイルを読み込んだときに使った方法。バイナリデータの読み込みについて書きかけの状態ですが、今回はテキストデータの読み込みについて。
実行速度よりも実装のしやすさを優先するなら、Ginがおすすめ。
実際の使い方としてはこんな感じ。
var xfileGrammar;
function start()
{
xfileGrammar = new Gin.Grammar({
XFile: / XFileHeader:header (XObjectLong)* /,
XFileHeader: / 'xof ':xof VersionNumber FormatType:showValue FloatSize:showValue /,
VersionNumber: / <\d\d>:showValue <\d\d>:showValue /,
FormatType: / 'txt ' | 'bin ' | 'tzip' | 'bzip' /,
FloatSize: / '0064' | '0032' /,
XObject: / Template | Animation | AnimationKey | AnimationOptions | AnimationSet | AnimTicksPerSecond | Boolean | Boolean2d | ColorRGB | ColorRGBA | Coords2d | DeclData | EffectDWorld | EffectFloats | EffectInstance | EffectParamDWorld | EffectParamFloats | EffectString | FaceAdjacency | FloatKeys | Frame | FrameTransformMatrix | FVFData | Header | IndexedColor | Material | Matrix4x4 | MeshFaceWraps | MeshFace | MeshMaterialList | MeshNormals | MeshTextureCoords | MeshVertexColors | Mesh | Patch | PatchMesh9 | PatchMesh | PMAttributeRange | PMInfo | PMVSplitRecord | SkinWeights | TextureFilename | TimedFloatKeys | Vector | VertexDuplicationIndices | VertexElement | XSkinMeshHeader /,
XObjectLong: / Template | AnimationLong | AnimationKeyLong | AnimationOptionsLong | AnimationSetLong | AnimTicksPerSecondLong | BooleanLong | Boolean2dLong | ColorRGBLong | ColorRGBALong | Coords2dLong | DeclDataLong | EffectDWorldLong | EffectFloatsLong | EffectInstanceLong | EffectParamDWorldLong | EffectParamFloatsLong | EffectStringLong | FaceAdjacencyLong | FloatKeysLong | FrameLong | FrameTransformMatrixLong | FVFDataLong | HeaderLong | IndexedColorLong | MaterialLong | Matrix4x4Long | MeshFaceWrapsLong | MeshFaceLong | MeshMaterialListLong | MeshNormalsLong | MeshTextureCoordsLong | MeshVertexColorsLong | MeshLong | PatchLong | PatchMeshLong | PatchMesh9Long | PMAttributeRangeLong | PMInfoLong | PMVSplitRecordLong | SkinWeightsLong | TextureFilenameLong | TimedFloatKeysLong | VectorLong | VertexDuplicationIndicesLong | VertexElementLong | XSkinMeshHeaderLong /,
XString: / <[0-9A-Za-z]*> /,
Identifier: / XString /,
Name: / XString /,
UUID: / '<' (<[0-9A-Za-z]|->)* '>' /,
Member: / ('array' TemplateType Name '[' ($INT | XString) ']') | (TemplateType Name) /,
TemplateType: / XString /,
XArray: / '[' $INT ']' /,
XObjectTemplate: / Identifier:identifier Name:name '{' UUID ('[...]' | ('[' Name ']') | (Member ';'))* '}' /,
Template: / 'template':template Name '{' UUID ('[...]' | ('[' Name ']') | (Member ';'))* '}' /,
IntValue: / $INT ';' ::first /,
IntArray: / $INT (',' $INT)* (',')? ';' /,
FloatValue: / $REAL ';' ::first /,
FloatArray: / $REAL (',' $REAL)* (',')? ';' /,
Header: / HeaderLong | (HeaderValue ';') /,
HeaderLong: / 'Header' (Name)? '{' (UUID)? HeaderValue '}' /,
HeaderValue: / IntValue:major IntValue:minor IntValue:flags /,
Animation: / AnimationLong | ( AnimationValue ';') /,
AnimationLong: / 'Animation' (Name)? '{' (UUID)? AnimationValue '}' /,
AnimationValue: / $ANY /,
AnimationKey: / AnimationKeyLong | ( AnimationKeyValue ';') /,
AnimationKeyLong: / 'AnimationKey' (Name)? '{' (UUID)? AnimationKeyValue '}' /,
AnimationKeyValue: / $ANY /,
AnimationOptions: / AnimationOptionsLong | ( AnimationOptionsValue ';') /,
AnimationOptionsLong: / 'AnimationOptions' (Name)? '{' (UUID)? AnimationOptionsValue '}' /,
AnimationOptionsValue: / $ANY /,
AnimationSet: / AnimationSetLong | ( AnimationSetValue ';') /,
AnimationSetLong: / 'AnimationSet' (Name)? '{' (UUID)? AnimationSetValue '}' /,
AnimationSetValue: / $ANY /,
AnimTicksPerSecond: / AnimTicksPerSecondLong | ( AnimTicksPerSecondValue ';') /,
AnimTicksPerSecondLong: / 'AnimTicksPerSecond' (Name)? '{' (UUID)? AnimTicksPerSecondValue '}' /,
AnimTicksPerSecondValue: / $ANY /,
Boolean: / BooleanLong | ( BooleanValue ';') /,
BooleanLong: / 'Boolean' (Name)? '{' (UUID)? BooleanValue '}' /,
BooleanValue: / $ANY /,
Boolean2d: / Boolean2dLong | ( Boolean2dValue ';') /,
Boolean2dLong: / 'Boolean2d' (Name)? '{' (UUID)? Boolean2dValue '}' /,
Boolean2dValue: / $ANY /,
ColorRGB: / ColorRGBLong | (ColorRGBValue ';') /,
ColorRGBLong: / 'ColorRGB' (Name)? '{' (UUID)? ColorRGBValue '}' /,
ColorRGBValue: / FloatValue:red FloatValue:green FloatValue:blue /,
ColorRGBA: / ColorRGBALong | (ColorRGBAValue ';') /,
ColorRGBALong: / 'ColorRGBA' (Name)? '{' (UUID)? ColorRGBAValue '}' /,
ColorRGBAValue: / FloatValue:red FloatValue:green FloatValue:blue FloatValue:alpha /,
Coords2d: / Coords2dLong | (Coords2dValue ';') /,
Coords2dLong: / 'Coords2d' (Name)? '{' (UUID)? Coords2dValue '}' /,
Coords2dArray: / Coords2dValue (',' Coords2dValue)* (',')? ';' /,
Coords2dValue: / FloatValue:u FloatValue:v /,
(中略)
XSkinMeshHeader: / XSkinMeshHeaderLong | ( XSkinMeshHeaderValue ';') /,
XSkinMeshHeaderLong: / 'XSkinMeshHeader' (Name)? '{' (UUID)? XSkinMeshHeaderValue '}' /,
XSkinMeshHeaderValue: / $ANY /,
}, "XFile", Gin.SPACE);
function XFileHandler() { this._s = [] };
XFileHandler.prototype = {
first: function(v){ return v[0]; },
header: function(v){ alert("version: " + v[1]); },
identifier: function(v){ alert("identifier:" + v[0]); },
xof: function(v){ alert("xof"); },
showValue: function(v){ alert("value:" + v); },
name: function(v){ alert("name:" + v); },
(中略)
// Mesh
mesh: function(v){ alert("Mesh start"); },
nVertices: function(v){ alert("nVertices: " + v); },
vertices: function(v){},
nFaces: function(v){ alert("nFaces: " + v); },
faces: function(v){},
(中略)
};
var match;
function parseXFile(request)
{
var text = request.responseText;
var handler = new XFileHandler();
match = xfileGrammar.parse(text, handler);
if(match && match.full) {
alert("OK");
}else{
alert("NG");
}
}
var url = "xfile.x";
var myAjax = new Ajax.Request(
url,
{
method: 'get',
onComplete: parseXFile
});
}
パースしたいデータの構文が分かっているなら、それをそのまま書いてやれば簡単にパーサが実装できる。速度を優先するなら、各ファイル形式に合わせて自分で実装すべし。
xファイルのパーサはこんな感じで作りました。
var XParser = Class.create({
_text: null,
(中略)
parse: function(text){
this._text = text;
if(!this._obj){
this._obj = new XModel();
}
this._offset = 0;
this._err = 0;
if(!this.XFileHeader(this._obj)){
alert("header format error");
this._err = 1;
return null;
}
while(this.XObjectLong(this._obj)){}
if(this._err){
alert("obj format error:" + this._err);
return null;
}
this.splitFaceNormals();
return this._obj;
},
moveIndex: function(len) {
this._text = this._text.substring(len);
this._offset += len;
},
getString: function(pattern) {
this.skip();
var str = this._text.match(pattern);
if(str != null){
this.moveIndex(str[0].length);
return str[0];
}
return null;
},
/* matching patterns */
skip: function() {
var i=0;
var code;
while(1){
code = this._text.charCodeAt(i);
if(code != 32 && (code < 9 || code > 13)){
break;
}
i++;
}
if(i>0){
this.moveIndex(i);
}
},
_integerPattern: new RegExp(/^(-|\+)?\d+;?/),
getInteger: function() {
var str = this.getString(this._integerPattern);
var val = parseInt(str);
return val;
},
_floatPattern: new RegExp(/^(-|\+)?(\d)*\.(\d)*;?/),
getFloat: function() {
var str = this.getString(this._floatPattern);
var val = parseFloat(str);
return val;
},
(中略)
XObjectLong: function(parent){
var id = this.getWord();
if(id == null){
return null;
}
switch(id){
case "template":
return this.Template(parent);
case "Header":
return this.Header(parent);
case "Mesh":
return this.Mesh(parent);
case "MeshMaterialList":
return this.MeshMaterialList(parent);
case "MeshNormals":
return this.MeshNormals(parent);
case "MeshTextureCoords":
return this.MeshTextureCoords(parent);
case "MeshVertexColors":
return this.MeshVertexColors(parent);
default:
alert("unknown type:" + id);
break;
}
return false;
},
(中略)
Mesh: function(parent) {
this.getLeftBrace();
// vertices
var nVertices = this.getInteger();
var skinArray = $A();
for(var i=0; i<nVertices; i++){
var skin = new Skin();
var pos = new DHVector3();
pos.x = this.getFloat();
pos.y = this.getFloat();
pos.z = -this.getFloat();
skin.position = pos;
skin.boneIndex[0] = 0;
skin.boneIndex[1] = -1;
skin.boneIndex[2] = -1;
skin.boneIndex[3] = -1;
skin.skinWeight[0] = 1;
skin.skinWeight[1] = 0;
skin.skinWeight[2] = 0;
skin.skinWeight[3] = 0;
skinArray.push(skin);
this.getCommaOrSemicolon();
}
this._obj.skinArray = skinArray;
this._obj.dynamicSkinOffset = -1;
// faces
var nFaces = this.getInteger();
var faces = $A();
for(var i=0; i<nFaces; i++){
var face = this.getIntegerArray();
faces.push(face);
}
this._indices = faces;
this.getRightBrace();
return true;
},
(中略)
}
タグ:
この記事のURL: https://darkhorse2.0spec.jp/176/
2012/10/05(Fri) 01:21:39
