xyzzy lisp

lightwave関連

  • ソース

バイナリ(ライトウェーブはビッグエンディアン)からfloatにする方法が、新しく分かった。
print-f4関数あたり。
残りはサーフェースサブチャンク

;;; light wave のファイルを調べる関数群
;;;
;;; todo:
;;; サーフェイス サブチャンクの表示がない
;;;

(defun print-chunck-tag (in)
  (let ((name (print-id4 in "tag")))
    (print-chunck-length in name)))

(defun print-u2 (in name)
  (let ((ch)(val 0))
    (dotimes (cnt 2) (setq ch (read-char in nil))
      (if (= cnt 0) (setq val (char-code ch))
	(setq val (+ (* #x100 val) (char-code ch)))))
    (princ (format nil "\t~A: ~D\n" name val))))

(defun print-f4 (in)
  (let ((ch)(val ""))
    (dotimes (cnt 4) (setq ch (read-char in nil))
      (progn
	(setq val (concat (format nil "~C" ch) val))))
    (princ (format nil "~E, " (si::unpack-float (si::make-string-chunk val) 0)
		   ))))

(defun print-vec12 (in)
  (let ((ch)(val 0))
    (princ "\t\t")
    (print-f4 in)
    (print-f4 in)
    (print-f4 in)
    (princ "\n")))

(defun print-id4 (in name2)
  (let ((name "")(ch))
    (dotimes (cnt 4) (setq ch (read-char in nil))
      (if (not ch) (return))
      (setq name (concat name (format nil "~C" ch))))
    (if ch (progn (princ (format nil "~A: ~A\n" name2 name))))
    (string name)))

(defun print-numvert-flags (in)
  (let ((ch)(val 0))
    (dotimes (cnt 2) (setq ch (read-char in nil))
      (if (= cnt 0) (setq val (char-code ch))
	(setq val (+ (* #x100 val) (char-code ch)))))
    (princ (format nil "\tflags: ~D\n" (ash (logand val #b1111110000000000) -10)))
    (princ (format nil "\tnumvert: ~D\n" (logand val #b1111111111)))
    (logand val #b1111111111)))

(defun print-vx (in)
  (let ((ch)(val 0)(by))
    (setq ch (read-char in nil))
    (if (= #xff (char-code ch))
	(progn (dotimes (cnt 3) (setq ch (read-char in nil))
		 (if (= cnt 0) (setq val (char-code ch))
		   (setq val (+ (* #x100 val) (char-code ch)))))
	  (setq by 4))
      (progn (setq val (+ (* #x100 val) (char-code ch)))
	(setq ch (read-char in nil))
	(setq val (+ (* #x100 val) (char-code ch)))
	(setq by 2)))
    (princ (format nil "~D" val))
    by
    ))

(defun print-chunck-length (in name)
  (let ((ch)(val 0))
    (dotimes (cnt 4) (setq ch (read-char in nil))
      (if (null ch) (return))
      (if (= cnt 0) (setq val (char-code ch))
	(setq val (+ (* #x100 val) (char-code ch)))))
    (if ch (progn
	     (princ (format nil "\tlength: ~D\n" val))
	     (cond ((string= name "FORM")
		    (skip-stream in 4)
		    (print-chunck-tag in))
		   ((string= name "TAGS")
		    (print-tags-name in val)
		    (print-chunck-tag in))
		   ((string= name "LAYR")
		    (print-u2 in "number")
		    (print-u2 in "flags")
		    (princ "\tpivot:\n")
		    (print-vec12 in)
		    (print-tags-name in (- val 18))
		    (print-u2 in "parent")
		    (print-chunck-tag in))
		   ((string= name "PNTS")
		    (princ "\tpoint-location:\n")
		    (dotimes (i (/ val 12))
		      (print-vec12 in))
		    (print-chunck-tag in))
		   ((string= name "BBOX")
		    (princ "\tmin:\n")
		    (print-vec12 in)
		    (princ "\tmax:\n")
		    (print-vec12 in)
		    (print-chunck-tag in))
		   ((string= name "POLS")
		    (print-id4 in "\ttype")
		    (setq val (- val 4))
		    (let ((vn))
		      (while (> val 0)
			(setq vn (print-numvert-flags in))
			(princ "\tvert:\n\t\t")
			(dotimes (cnt vn)
			  (setq val (- val (print-vx in)))
			  (princ ", "))
			(setq val (- val 2))
			(princ "\n")))
		    (print-chunck-tag in))
		   ((string= name "PTAG")
		    (print-id4 in "\ttype")
		    (setq val (- val 4))
		    (while (> val 0)
		      (princ "\tpoly: ")
		      (setq val (- val (print-vx in)))
		      (princ "\n")
		      (print-u2 in "tag")
		      (setq val (- val 2)))
		    (print-chunck-tag in))
		   ((string= name "SURF")
		    (setq val (- val (print-s0 in "name")))
		    (setq val (- val (print-s0 in "source")))
		    (skip-stream in val)
		    (print-chunck-tag in))
		   (t (message "なんか分からないチャンクがありました"))
		   )))))

(defun print-tags-name (in len)
  (let ((ch)(tmp "")(prech 1))
    (dotimes (cnt len) (setq ch (read-char in nil))
      (if (= 0 (char-code ch))
	  (if (/= prech 0)
	      (setq tmp (concat tmp "\n\t\t")))
	(setq tmp (concat tmp (format nil "~C" ch))))
      (setq prech (char-code ch)))
    (princ (format nil "\ttagname: \n\t\t~A\n" tmp))))

(defun print-s0 (in name)
  (let ((ch)(tmp "")(len 0))
    (while (/= 0 (char-code (setq ch (read-char in nil))))
      (setq tmp (concat tmp (format nil "~C" ch)))
      (incf len))
    (princ (format nil "\t~A: \n\t\t~A\n" name tmp))
    len))

(defun skip-stream (in cnt)
  (dotimes (x cnt) (read-char in nil)))

(defun scan-lwo (fn)
  "lightwaveオブジェクトファイル解析"
  (interactive "F")
  (with-output-to-temp-buffer ("*lwo解析結果*")
    (with-open-file (in fn :direction :input :encoding :binary)
      (let ((ch)(stat 0)(cnt 0)(val 0)(tag "")(tmp))
	(print-chunck-tag in)))))

(defun scan-lws (fn)
  "lightwaveシーンファイルを解析する"
  (interactive "F")
  (with-output-to-temp-buffer ("*lws解析結果*")
    (let ((sbuffer (buffer-stream-buffer *standard-output*)))
      (save-excursion
	(with-open-file (in fn :direction :input)
	  (let ((tmp "")(tmp2))
	    (while (setq tmp (read-line in nil))
	      (if (string-match "AddNullObject \\(.+\\)" tmp) ; null object
		  (princ (concat "nullオブジェクト: " (match-string 1) "\n"))
		)
	      (if (string-match "LoadObjectLayer \\w+ \\(.+\\)" tmp) ; object layer
		  (princ (concat "オブジェクト・レイヤ: " (match-string 1) "\n"))
		)
	      (if (string-match "LightName \\(.+\\)" tmp) ; light
		  (princ (concat "ライト: " (match-string 1) "\n"))
		)
	      (if (string-match "CameraName \\(.+\\)" tmp) ; camera
		  (princ (concat "カメラ: " (match-string 1) "\n"))
		)
	      (if (string-match "^FirstFrame \\(.+\\)" tmp) ; first frame
		  (princ (concat "開始フレーム: " (match-string 1) "\n"))
		)
	      (if (string-match "^LastFrame \\(.+\\)" tmp) ; last frame
		  (princ (concat "終了フレーム: " (match-string 1) "\n"))
		)
	      )))))))

(provide "lightwave")
  • 結果

調子に乗ってクラインの壷を解析したら、うまく動いたが、2万行近い出力になった。
箱の解析結果で我慢する。

tag: FORM
	length: 382
tag: TAGS
	length: 14
	tagname: 
		DkBlu
		Default
		
tag: LAYR
	length: 18
	number: 0
	flags: 0
	pivot:
		0.0, 0.0, 0.0, 
	tagname: 
		
	parent: 0
tag: PNTS
	length: 96
	point-location:
		-0.95, -1.1, -1.05, 
		-0.95, 0.95, -1.05, 
		0.95, 0.95, -1.05, 
		0.95, -1.1, -1.05, 
		-0.95, -1.1, 0.0, 
		-0.95, 0.95, 0.0, 
		0.95, 0.95, 0.0, 
		0.95, -1.1, 0.0, 
tag: BBOX
	length: 24
	min:
		-0.95, -1.1, -1.05, 
	max:
		0.95, 0.95, 0.0, 
tag: POLS
	length: 64
	type: FACE
	flags: 0
	numvert: 4
	vert:
		0, 1, 2, 3, 
	flags: 0
	numvert: 4
	vert:
		0, 4, 5, 1, 
	flags: 0
	numvert: 4
	vert:
		1, 5, 6, 2, 
	flags: 0
	numvert: 4
	vert:
		3, 2, 6, 7, 
	flags: 0
	numvert: 4
	vert:
		0, 3, 7, 4, 
	flags: 0
	numvert: 4
	vert:
		4, 7, 6, 5, 
tag: PTAG
	length: 28
	type: COLR
	poly: 0
	tag: 0
	poly: 1
	tag: 0
	poly: 2
	tag: 0
	poly: 3
	tag: 0
	poly: 4
	tag: 0
	poly: 5
	tag: 0
tag: PTAG
	length: 28
	type: SURF
	poly: 0
	tag: 1
	poly: 1
	tag: 1
	poly: 2
	tag: 1
	poly: 3
	tag: 1
	poly: 4
	tag: 1
	poly: 5
	tag: 1
tag: SURF
	length: 42
	name: 
		Default
	source: