假设我有一个线框,3D对象,例如https://free3d.com/3d-model/freerealsichand-85561.html
假设我想将所述物体的手腕固定为加速度计腕表的读数(例如,通过航位推算得到位置)。
如何在rgl
?
如何根据加速度计数据的变化旋转/翻译所述图像?
奖励:如何播放此活动的animation
。 (例如,图书馆animation
)
加速度计是3-DOF:x-acc,y-acc,z-acc,没有任何其他数据。
答案 0 :(得分:1)
该链接包含多种格式的手,但rgl
目前无法读取它们。它最接近.OBJ格式,但无法读取该文件中记录的法线或纹理,因此失败。您可能想尝试更新readOBJ
以支持更多OBJ格式;或者,你可以删除这样的信息:
hand <- readLines("hand.OBJ")
poly <- grepl("^f ", hand)
hand[poly] <- gsub("/[^ ]+", "", hand[poly])
handmesh <- readOBJ(textConnection(hand))
这会给出一些警告,因为它会忽略该文件的其他部分,但会产生rgl
可以处理的对象。您可以这样绘制:
shade3d(handmesh, col = "pink")
要翻译和旋转形状,请使用translate3d
上的rotate3d
和userMatrix
功能,例如
par3d(userMatrix = rotate3d(par3d("userMatrix"), 0.1, 1,0,0))
围绕x轴旋转手指0.1弧度。 (如果您想要永久性更改,也可以轮换handmesh
本身。)
您需要花一些时间来确定手腕的坐标,并将您的3-DOF数据转换为正确的坐标系。
动画不需要animation
;请参阅?rgl::play3d
中的示例。例如,要围绕x轴旋转手,可以使用
open3d()
shade3d(handmesh, col = "pink")
play3d(spin3d(axis = c(1, 0, 0)))
答案 1 :(得分:0)
根据@ user2554330提供的答案,我挖掘了细节。
rgl :: readOBJ有点不完美,我通知了R-forge:rgl:https://r-forge.r-project.org/tracker/index.php?func=detail&aid=6543&group_id=234&atid=949
# rgl::readOBJ
beginT = Sys.time();
hand <- readLines("hand.OBJ")
poly <- grepl("^f ", hand)
hand[poly] <- gsub("/[^ ]+", "", hand[poly])
handmesh <- readOBJ(textConnection(hand))
endT = Sys.time(); print(endT-beginT);
# Time difference of 1.555696964263916 secs
我的黑客有四个功能:
#' Convert String Matrix to Numeric Matrix
#'
#' @param m string matrix
#'
#' @return numeric matrix
#' @export
numericMatrix = function(m)
{
m = as.matrix(m);
mdim = dim(m);
nm <- mapply(m, FUN=as.numeric);
matrix(data=nm, nrow=mdim[1], ncol=mdim[2])
}
#' Convert String List of "f" to numeric multi-dimensional array
#'
#' @param fobj
#'
#' @return fn, multidimension array of rows, cols, and values
#' @export
#'
numericF = function(fobj)
{
rdim = dim(fobj)[1]; # rows
cdim = dim(fobj)[2]; # cols
ddim = 3;
fn = array(NA,dim=c(rdim,cdim,ddim));
for(rn in 1:rdim)
{
for(cn in 1:cdim)
{
rcdat = fobj[rn,cn];
fdat = as.numeric(unlist(strsplit(rcdat,"/",fixed=T))); # basic numeric case
fn[rn,cn,] = fdat;
}
}
#fn[1:10,1:4,1:3]
fn;
}
#' Internally equivalent to rgl 'readOBJ'
#'
#' @param rawobj Raw object read in using parseFileOBJ
#'
#' rgl::readOBJ
#' hand <- readLines("hand.OBJ")
#' poly <- grepl("^f ", hand)
#' hand[poly] <- gsub("/[^ ]+", "", hand[poly])
#' handmesh <- readOBJ(textConnection(hand))
#'
#' mymesh = buildBasicMeshFromOBJ(parseFileOBJ("hand.OBJ"));
#'
#' These appear to be equivalent in the basic form
#'
#' @return list object equivalent to readOBJ output
#' @export
#'
buildBasicMeshFromOBJ <- function(rawobj)
{
mesh = list();
vb = as.matrix(rawobj$v);
vb = cbind(vb,1);
mesh$vb = t(vb);
mesh$it = matrix(0,nrow=3,ncol=0);
mesh$primitivetype = "triangle";
mesh$ib = t(as.matrix(rawobj$fn[,,1]));
attr(mesh,"class") = c("mesh3d","shape3d");
mesh;
}
#' Parse file of type OBJ
#'
#' Specification for OBJ format can be found here:
#' http://www.martinreddy.net/gfx/3d/OBJ.spec
#'
#' Requires gdata::trim
#'
#' @param filename
#'
#' @return list 'rawobj' with all details from the file
#' @export
#'
#' @examples
#' rawobj = parseFileOBJ("hand.obj");
parseFileOBJ <- function(filename)
{
linestxt <- readLines(filename) # read all lines
linestxt = gsub("\\s+"," ",gdata::trim(linestxt)); # replace multiple spaces with single space
linesobj = strsplit(linestxt," ",fixed=T); # split on spaces
rawobj = list();
rawobj$lines = c();
rawobj$comments = c();
for(i in 1:length(linesobj))
{
hir = gdata::trim(linesobj[[i]]);
key = hir[1];
rdat = hir[-1];
rlen = length(rdat);
rstr = paste(rdat,collapse=" ");
if (key=="#") {
rawobj$lines = c(rawobj$lines,"comments");
rawobj$comments = c(rawobj$comments,rstr);
} else { rawobj$lines = c(rawobj$lines,key);
if(is.null(rawobj[[key]])) { rawobj[[key]] = rdat; } else
{ rawobj[[key]] = rbind(rawobj[[key]],rdat);}
}
}
if(!is.null(rawobj[["v"]])) { rawobj[["v"]] = numericMatrix(rawobj[["v"]]); }
if(!is.null(rawobj[["vn"]])) { rawobj[["vn"]] = numericMatrix(rawobj[["vn"]]); }
if(!is.null(rawobj[["vt"]])) { rawobj[["vt"]] = numericMatrix(rawobj[["vt"]]); }
# "f" could be numeric (f 1 2 3 4) or (f -4 -3 -2 -1) or references to v,vn,vt (f 1/1/1 2/2/2 3/3/3 4/4/4) or (f v/vt/vn v/vt/vn v/vt/vn v/vt/vn) or (f 1//1 2//2 3//3 4//4)
# rdat = c("1102/9904/4404","2981/9909/4404","3943/9910/4404","2854/9905/4404");
# rdat = c('1//1','2//2','3//3',4//4');
if(!is.null(rawobj[["f"]])) { rawobj[["fn"]] = numericF(rawobj[["f"]]); }
rawobj;
}
基本用法:
# Takes longer, but processes "all" info in the file
beginT = Sys.time();
rawobj = parseFileOBJ("hand.OBJ");
endT = Sys.time(); print(endT-beginT); beginT = endT;
# Time difference of 6.9523830413818359 secs
mymesh = buildBasicMeshFromOBJ(rawobj);
endT = Sys.time(); print(endT-beginT);
# Time difference of 0.0030009746551513672 secs
rawobject具有全部根据此规范在OBJ文件中找到的信息:http://www.martinreddy.net/gfx/3d/OBJ.spec