class Node(Editable): FLAG_NO_TRANSLATE = 0x1 FLAG_NO_ROTATE = 0x2 FLAG_NO_SCALE = 0x4 FLAG_NO_PIVOT = 0x8 FLAG_PIVOT_REVC = 0x200 FLAG_PIVOT_REVD = 0x400 def define(self): self.uint16('flag_') for i in range(3): for j in range(3): self.int16('rot_{0}{1}_fx16'.format(i, j), default=int(i == j) * 4096) self.int32('trans_x_fx32') self.int32('trans_y_fx32') self.int32('trans_z_fx32') self.int16('pivot_a_fx16') self.int16('pivot_b_fx16') self.int32('scale_x_fx32', default=4096) self.int32('scale_y_fx32', default=4096) self.int32('scale_z_fx32', default=4096) self.int32('inv_scale_x_fx32', default=4096) self.int32('inv_scale_y_fx32', default=4096) self.int32('inv_scale_z_fx32', default=4096) def load(self, reader): reader = BinaryIO.reader(reader) self.flag_ = reader.readUInt16() self.rot_00_fx16 = reader.readInt16() if self.flag_ & self.FLAG_NO_TRANSLATE: self.trans_x_fx32 = 0 self.trans_y_fx32 = 0 self.trans_z_fx32 = 0 else: self.trans_x_fx32 = reader.readInt32() self.trans_y_fx32 = reader.readInt32() self.trans_z_fx32 = reader.readInt32() if self.flag_ & self.FLAG_NO_ROTATE: for i in range(3): for j in range(3): setattr(self, 'rot_{0}{1}_fx16'.format(i, j), int(i == j) * 4096) elif self.flag_ & self.FLAG_NO_PIVOT: self.rot_01_fx16 = reader.readInt16() self.rot_02_fx16 = reader.readInt16() self.rot_10_fx16 = reader.readInt16() self.rot_11_fx16 = reader.readInt16() self.rot_12_fx16 = reader.readInt16() self.rot_20_fx16 = reader.readInt16() self.rot_21_fx16 = reader.readInt16() self.rot_22_fx16 = reader.readInt16() else: for i in range(3): for j in range(3): setattr(self, 'rot_{0}{1}_fx16'.format(i, j), int(i == j) * 4096) self.pivot_a_fx16 = reader.readInt16() self.pivot_b_fx16 = reader.readInt16() pivot = (self.flag_ >> 4) & 0xf if self.flag_ & self.FLAG_PIVOT_REVC: pivoc_c = -self.pivot_b_fx16 else: pivoc_c = self.pivot_b_fx16 if self.flag_ & self.FLAG_PIVOT_REVD: pivoc_d = -self.pivot_a_fx16 else: pivoc_d = self.pivot_a_fx16 if pivot == 0: self.rot_11_fx16 = self.pivot_a_fx16 self.rot_12_fx16 = self.pivot_b_fx16 self.rot_21_fx16 = pivoc_c self.rot_22_fx16 = pivoc_d elif pivot == 4: self.rot_00_fx16 = self.pivot_a_fx16 self.rot_02_fx16 = self.pivot_b_fx16 self.rot_20_fx16 = pivoc_c self.rot_22_fx16 = pivoc_d elif pivot == 8: self.rot_00_fx16 = self.pivot_a_fx16 self.rot_01_fx16 = self.pivot_b_fx16 self.rot_10_fx16 = pivoc_c self.rot_11_fx16 = pivoc_d else: raise NotImplementedError( 'Pivot {0} is not supported'.format(pivot)) if self.flag_ & self.FLAG_NO_SCALE: self.scale_x_fx32 = 4096 self.scale_y_fx32 = 4096 self.scale_z_fx32 = 4096 self.inv_scale_x_fx32 = 4096 self.inv_scale_y_fx32 = 4096 self.inv_scale_z_fx32 = 4096 else: self.scale_x_fx32 = reader.readInt32() self.scale_y_fx32 = reader.readInt32() self.scale_z_fx32 = reader.readInt32() self.inv_scale_x_fx32 = reader.readInt32() self.inv_scale_y_fx32 = reader.readInt32() self.inv_scale_z_fx32 = reader.readInt32() def save(self, writer): writer = BinaryIO.writer(writer) flag = self.flag writer.writeUInt16(flag) writer.writeInt16(self.rot_00_fx16) if not (self.flag & self.FLAG_NO_TRANSLATE): writer.writeInt32(self.trans_x_fx32) writer.writeInt32(self.trans_y_fx32) writer.writeInt32(self.trans_z_fx32) if not (self.flag & self.FLAG_NO_ROTATE): writer.writeInt16(self.rot_01_fx16) writer.writeInt16(self.rot_02_fx16) writer.writeInt16(self.rot_10_fx16) writer.writeInt16(self.rot_11_fx16) writer.writeInt16(self.rot_20_fx16) writer.writeInt16(self.rot_21_fx16) writer.writeInt16(self.rot_22_fx16) if not (self.flag & self.FLAG_NO_SCALE): try: self.inv_scale_x = 1 / self.scale_x except ZeroDivisionError: self.inv_scale_x = 0.0 try: self.inv_scale_y = 1 / self.scale_y except ZeroDivisionError: self.inv_scale_y = 0.0 try: self.inv_scale_z = 1 / self.scale_z except ZeroDivisionError: self.inv_scale_z = 0.0 writer.writeInt32(self.scale_x_fx32) writer.writeInt32(self.scale_y_fx32) writer.writeInt32(self.scale_z_fx32) writer.writeInt32(self.inv_scale_x_fx32) writer.writeInt32(self.inv_scale_y_fx32) writer.writeInt32(self.inv_scale_z_fx32) return writer @property def flag(self): flag = 0 if not self.trans_x_fx32 and not self.trans_y_fx32 and\ not self.trans_z_fx32: flag |= self.FLAG_NO_TRANSLATE for i in range(3): for j in range(3): if getattr(self, 'rot_{0}{1}_fx16'.format(i, j))\ != int(i == j)*4096: break else: continue break else: flag |= self.FLAG_NO_ROTATE flag |= self.FLAG_NO_PIVOT if self.scale_x_fx32 == 4096 and self.scale_y_fx32 == 4096\ and self.scale_z_fx32 == 4096: flag |= self.FLAG_NO_SCALE # TODO: make sure inv_scale match return flag @flag.setter def flag(self, value): self.flag_ = value trans_x = Editable.fx_property('trans_x_fx32') trans_y = Editable.fx_property('trans_y_fx32') trans_z = Editable.fx_property('trans_z_fx32') pivot_a = Editable.fx_property('pivot_a_fx16') pivot_b = Editable.fx_property('pivot_b_fx16') scale_x = Editable.fx_property('scale_x_fx32') scale_y = Editable.fx_property('scale_y_fx32') scale_z = Editable.fx_property('scale_z_fx32') inv_scale_x = Editable.fx_property('inv_scale_x_fx32') inv_scale_y = Editable.fx_property('inv_scale_y_fx32') inv_scale_z = Editable.fx_property('inv_scale_z_fx32')
trans_y = Editable.fx_property('trans_y_fx32') trans_z = Editable.fx_property('trans_z_fx32') pivot_a = Editable.fx_property('pivot_a_fx16') pivot_b = Editable.fx_property('pivot_b_fx16') scale_x = Editable.fx_property('scale_x_fx32') scale_y = Editable.fx_property('scale_y_fx32') scale_z = Editable.fx_property('scale_z_fx32') inv_scale_x = Editable.fx_property('inv_scale_x_fx32') inv_scale_y = Editable.fx_property('inv_scale_y_fx32') inv_scale_z = Editable.fx_property('inv_scale_z_fx32') for i in range(3): for j in range(3): setattr(Node, 'rot_{0}{1}'.format(i, j), Editable.fx_property('rot_{0}{1}_fx16'.format(i, j))) class NodeSet(object): def __init__(self): self.nodedict = G3DResDict() self.nodes = [] def load(self, reader): start = reader.tell() self.nodedict.load(reader) self.nodes = [] for i in range(self.nodedict.num): ofs, = struct.unpack('I', self.nodedict.data[i]) reader.seek(start + ofs) self.nodes.append(Node(reader=reader))