The Forum is up for sale: XeNTaX Forum looking for new owner

3D Ripper DX 3DS MAX POV PLUGIN REQUEST (Works in Blender)

Post questions about game models here, or help out others!
Post Reply
ReeceMix
advanced
Posts: 64
Joined: Sat Nov 10, 2007 3:01 pm
Has thanked: 6 times
Been thanked: 14 times

3D Ripper DX 3DS MAX POV PLUGIN REQUEST (Works in Blender)

Post by ReeceMix »

For those of you familiar with '3D Ripper DX' you will know that if you cant input the correct POV information the captured model is terribly skewed

Below is a working .PY plugin for Blender that corrects the proportions beautifully and allows you to combine multiiple rips.

I am hoping that someone will be able to convert this plugin into a 3DS max (2015 pref) version (I have tried contacting the original author who did attempt a 3dsmax plugin but he couldnt get it to work properly)

(Secondly a working 3DR import for Max 2015 would also be epic)

Code: Select all

#!BPY

"""
Name: 'Correct3DRipper'
Blender: 248
Group: 'Mesh'
"""

__author__ = "Dusan Pavlicek"
__email__ = "pavlicd@volny.cz"

import Blender
import math

from Blender import *
from Blender.Mathutils import *


BUTTON_ASSIGN_GROUND = 1
BUTTON_ASSIGN_FRONT = 2
BUTTON_ASSIGN_SIDE = 3
BUTTON_ADJUST_SCALES = 4
BUTTON_ALIGN_PLANES = 5

SELECTED_VERTS_GROUND = []
SELECTED_VERTS_FRONT = []
SELECTED_VERTS_SIDE = []

AXIS_X = 1
AXIS_Y = 2
AXIS_Z = 3

PLANE_XY = 1
PLANE_XZ = 2
PLANE_YZ = 3


def GetVisibleMeshObjects():
	editmode = Window.EditMode()
	Window.EditMode(0)
	meshObjects = []
	scene = Scene.GetCurrent()
	if scene != None:
		for object in scene.objects:
			if object.type != 'Mesh':
				continue
			visible = False
			for objectLayer in object.layers:
				if objectLayer in scene.layers:
					visible = True
					break
			if not visible:
				continue
			meshObjects.append(object)
	Window.EditMode(editmode)
	return meshObjects

	
def GetSelectedVisibleMeshObjects():
	editmode = Window.EditMode()
	Window.EditMode(0)
	meshObjects = []
	scene = Scene.GetCurrent()
	if scene != None:
		for object in scene.objects:
			if not object.sel:
				continue
			if object.type != 'Mesh':
				continue
			visible = False
			for objectLayer in object.layers:
				if objectLayer in scene.layers:
					visible = True
					break
			if not visible:
				continue
			meshObjects.append(object)
	Window.EditMode(editmode)
	return meshObjects


def GetMeshFromObject(object):
	if object.type != 'Mesh':
		return None
	return object.getData(mesh=True)


def GetSelectedVisibleVertices(onlySelectedMeshes):
	vertices = []
	if onlySelectedMeshes:
		objects = GetSelectedVisibleMeshObjects()
	else:
		objects = GetVisibleMeshObjects()
	for object in objects:
		objectMatrix = object.getMatrix()
		mesh = GetMeshFromObject(object)
		for vertex in mesh.verts:
			if not vertex.sel:
				continue
			if vertex.hide:
				continue
			vertices.append([object, vertex])
	return vertices


def CalcScaleTransform(axis, p1, p2, p3, q1, q2, q3):
	a = Vector(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z)
	b = Vector(p3.x - p1.x, p3.y - p1.y, p3.z - p1.z)
	c = Vector(q2.x - q1.x, q2.y - q1.y, q2.z - q1.z)
	d = Vector(q3.x - q1.x, q3.y - q1.y, q3.z - q1.z)
	u = (a.y * b.z - a.z * b.y) * (c.y * d.z - c.z * d.y)
	v = (a.z * b.x - a.x * b.z) * (c.z * d.x - c.x * d.z)
	w = (a.x * b.y - a.y * b.x) * (c.x * d.y - c.y * d.x)
	sx = 1
	sy = 1
	sz = 1
	if axis == AXIS_X:
		if v + w != 0:
			t = -u / (v + w)
		else:
			t = -1
		if t > 0:
			s = math.sqrt(t)
			sx = s
	elif axis == AXIS_Y:
		if u + w != 0:
			t = -v / (u + w)
		else:
			t = -1
		if t > 0:
			s = math.sqrt(t)
			sy = s
	elif axis == AXIS_Z:
		if u + v != 0:
			t = -w / (u + v)
		else:
			t = -1
		if t > 0:
			s = math.sqrt(t)
			sz = s
	if t > 0:
		Draw.PupMenu('Axis scale multiplied by %f.' % s)
		if s == 1:
			return None
	else:
		if abs(u + v + w) < 1e-4:
			Draw.PupMenu('Planes are already perpendicular.')
		else:
			Draw.PupMenu('Sorry, I cannot make the two planes perpendicular.')
		return None
	return ScaleMatrix(sx, sy, sz)


def ScaleMatrix(sx, sy, sz):
	return Matrix(
		[sx, 0, 0, 0],
		[0, sy, 0, 0],
		[0, 0, sz, 0],
		[0, 0, 0, 1])


def CorrectAxisScale(axis, selectedVerts1, selectedVerts2):
	Window.WaitCursor(1)
	matrix = CalcScaleTransform(
			axis,
			selectedVerts1[0][1].co * selectedVerts1[0][0].getMatrix(),
			selectedVerts1[1][1].co * selectedVerts1[1][0].getMatrix(), 
			selectedVerts1[2][1].co * selectedVerts1[2][0].getMatrix(),
			selectedVerts2[0][1].co * selectedVerts2[0][0].getMatrix(), 
			selectedVerts2[1][1].co * selectedVerts2[1][0].getMatrix(), 
			selectedVerts2[2][1].co * selectedVerts2[2][0].getMatrix())
	if matrix != None:
		objects = GetVisibleMeshObjects()
		for object in objects:
			object.setMatrix(object.getMatrix() * matrix)
	Window.WaitCursor(0)
	Redraw()
	return


def CalcPlaneNormal(p1, p2, p3):
	u = Vector([p2.x - p1.x, p2.y - p1.y, p2.z - p1.z])
	v = Vector([p3.x - p1.x, p3.y - p1.y, p3.z - p1.z])
	return CrossVecs(u, v).normalize()


def CalcRotationTransform(p1, p2, p3, alignPlane):
	if alignPlane == PLANE_XY:
		i = Vector(0, 0, 1)
	elif alignPlane == PLANE_XZ:
		i = Vector(0, 1, 0)
	elif alignPlane == PLANE_YZ:
		i = Vector(1, 0, 0)

	normalPos = CalcPlaneNormal(p1, p2, p3)
	normalNeg = -normalPos
	anglePos = AngleBetweenVecs(normalPos, i)
	angleNeg = AngleBetweenVecs(normalNeg, i)
	if anglePos < angleNeg:
		angle = anglePos
		normal = normalPos
	else:
		angle = angleNeg
		normal = normalNeg

	if alignPlane == PLANE_XY:
		axis = Vector([-normal.y, normal.x, 0])
	elif alignPlane == PLANE_XZ:
		axis = Vector([-normal.z, 0, normal.x])
	elif alignPlane == PLANE_YZ:
		axis = Vector([0, -normal.z, normal.y])
	if axis.length < 1e-5:
		return Matrix().resize4x4().identity()

	matrixPos = RotationMatrix(+angle, 4, 'r', axis)
	matrixNeg = RotationMatrix(-angle, 4, 'r', axis)
	testPos = normal * matrixPos
	testNeg = normal * matrixNeg
	anglePos = AngleBetweenVecs(testPos, i)
	angleNeg = AngleBetweenVecs(testNeg, i)
	if anglePos < angleNeg:
		matrix = matrixPos
	else:
		matrix = matrixNeg
	return matrix


def CalcAlignTransform(p1, p2, p3, alignPlane):
	matrixRot = CalcRotationTransform(p1, p2, p3, alignPlane)
	test = p1 * matrixRot
	if alignPlane == PLANE_XY:
		matrixTrans = TranslationMatrix(Vector(0, 0, -test.z))
	elif alignPlane == PLANE_XZ:
		matrixTrans = TranslationMatrix(Vector(0, -test.y, 0))
	elif alignPlane == PLANE_YZ:
		matrixTrans = TranslationMatrix(Vector(-test.x, 0, 0))
	return matrixRot * matrixTrans


def AlignGeometry(p1, p2, p3, alignPlane):
	Window.WaitCursor(1)
	matrix = CalcAlignTransform(p1, p2, p3, alignPlane)
	objects = GetVisibleMeshObjects()
	for object in objects:
		object.setMatrix(object.getMatrix() * matrix)
	Window.WaitCursor(0)
	Redraw()
	return


def DrawGUI():
	YPOS = 360
	BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
	BGL.glColor3f(0, 0, 0)
	
	BGL.glRasterPos2d(10, YPOS)
	Draw.Text('This script adjusts scales of X, Y and Z axes so that')
	BGL.glRasterPos2d(10, YPOS - 15)
	Draw.Text('the specified ground, front and side planes become')
	BGL.glRasterPos2d(10, YPOS - 30)
	Draw.Text('perpendicular.')
	BGL.glRasterPos2d(10, YPOS - 45)
	Draw.Text('It also aligns the ground plane with the XY plane.')

	BGL.glRasterPos2d(10, YPOS - 80)
	Draw.Text('1) For each plane, select three vertices and click')
	BGL.glRasterPos2d(25, YPOS - 95)
	Draw.Text('a button to define the corresponding plane:')

	Draw.Button('Assign GROUND plane', BUTTON_ASSIGN_GROUND, 25, YPOS - 130, 150, 20)
	Draw.Button('Assign FRONT plane', BUTTON_ASSIGN_FRONT, 25, YPOS - 155, 150, 20)
	Draw.Button('Assign SIDE plane', BUTTON_ASSIGN_SIDE, 25, YPOS - 180, 150, 20)

	BGL.glRasterPos2d(10, YPOS - 205)
	Draw.Text('2) Then press the button to automatically')
	BGL.glRasterPos2d(25, YPOS - 220)
	Draw.Text('adjust all three axis scales.')

	Draw.Button('Adjust axes scales', BUTTON_ADJUST_SCALES, 25, YPOS - 255, 150, 20)

	BGL.glRasterPos2d(10, YPOS - 280)
	Draw.Text('3) Then press the button to automatically align')
	BGL.glRasterPos2d(25, YPOS - 295)
	Draw.Text('the three planes with the world coordinate system.')

	Draw.Button('Align planes', BUTTON_ALIGN_PLANES, 25, YPOS - 330, 150, 20)
	return


def HandleEvent(event, value):
	if event == Draw.ESCKEY:
		Draw.Exit()
	return


def HandleButton(button):
	global SELECTED_VERTS_GROUND
	global SELECTED_VERTS_FRONT
	global SELECTED_VERTS_SIDE

	if button == BUTTON_ASSIGN_GROUND:
		SELECTED_VERTS_GROUND = GetSelectedVisibleVertices(True)
		if len(SELECTED_VERTS_GROUND) != 3:
			Draw.PupMenu('Select exactly 3 vertices please.')
		return
	if button == BUTTON_ASSIGN_FRONT:
		SELECTED_VERTS_FRONT = GetSelectedVisibleVertices(True)
		if len(SELECTED_VERTS_FRONT) != 3:
			Draw.PupMenu('Select exactly 3 vertices please.')
		return
	if button == BUTTON_ASSIGN_SIDE:
		SELECTED_VERTS_SIDE = GetSelectedVisibleVertices(True)
		if len(SELECTED_VERTS_SIDE) != 3:
			Draw.PupMenu('Select exactly 3 vertices please.')
		return
	if button == BUTTON_ADJUST_SCALES:
		if len(SELECTED_VERTS_GROUND) == 0:
			Draw.PupMenu('Assign GROUND plane please.')
			return
		if len(SELECTED_VERTS_FRONT) == 0:
			Draw.PupMenu('Assign FRONT plane please.')
			return
		if len(SELECTED_VERTS_SIDE) == 0:
			Draw.PupMenu('Assign SIDE plane please.')
			return
		CorrectAxisScale(AXIS_Y, SELECTED_VERTS_GROUND, SELECTED_VERTS_FRONT)
		CorrectAxisScale(AXIS_X, SELECTED_VERTS_FRONT, SELECTED_VERTS_SIDE)
		CorrectAxisScale(AXIS_Z, SELECTED_VERTS_GROUND, SELECTED_VERTS_SIDE)
		return
	if button == BUTTON_ALIGN_PLANES:
		if len(SELECTED_VERTS_GROUND) == 0:
			Draw.PupMenu('Assign GROUND plane please.')
			return
		if len(SELECTED_VERTS_FRONT) == 0:
			Draw.PupMenu('Assign FRONT plane please.')
			return
		p1 = SELECTED_VERTS_GROUND[0][1].co * SELECTED_VERTS_GROUND[0][0].getMatrix()
		p2 = SELECTED_VERTS_GROUND[1][1].co * SELECTED_VERTS_GROUND[1][0].getMatrix()
		p3 = SELECTED_VERTS_GROUND[2][1].co * SELECTED_VERTS_GROUND[2][0].getMatrix()
		AlignGeometry(p1, p2, p3, PLANE_XY)
		p1 = SELECTED_VERTS_FRONT[0][1].co * SELECTED_VERTS_FRONT[0][0].getMatrix()
		p2 = SELECTED_VERTS_FRONT[1][1].co * SELECTED_VERTS_FRONT[1][0].getMatrix()
		p3 = SELECTED_VERTS_FRONT[2][1].co * SELECTED_VERTS_FRONT[2][0].getMatrix()
		AlignGeometry(p1, p2, p3, PLANE_XZ)
		return
	return


def Main():
	Draw.Register(DrawGUI, HandleEvent, HandleButton)
	return


Main()
Post Reply